agentix-cli 0.87.0 → 0.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{board-dashboard-YKQ7BCJY.js → board-dashboard-GL6GQ32D.js} +534 -221
- package/dist/board-dashboard-GL6GQ32D.js.map +1 -0
- package/dist/{chunk-UBU7DBAG.js → chunk-3CHAPGUX.js} +4 -4
- package/dist/{chunk-CPXZWVKN.js → chunk-BFY4D4RH.js} +2 -2
- package/dist/{chunk-F7LZTO6I.js → chunk-BUELCBBV.js} +27 -27
- package/dist/{chunk-F7LZTO6I.js.map → chunk-BUELCBBV.js.map} +1 -1
- package/dist/{chunk-CL53UVOF.js → chunk-DWZYVYZS.js} +2 -2
- package/dist/chunk-DWZYVYZS.js.map +1 -0
- package/dist/{chunk-O5U5NVLR.js → chunk-OAA7TNB6.js} +2 -2
- package/dist/{chunk-RKHIVWFE.js → chunk-X2F3AVGR.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/processes-TXEWMXXJ.js +2 -0
- package/dist/{program-KGILRYLG.js → program-QKXRASTV.js} +4 -4
- package/package.json +1 -1
- package/dist/board-dashboard-YKQ7BCJY.js.map +0 -1
- package/dist/chunk-CL53UVOF.js.map +0 -1
- package/dist/processes-5EXCTSD5.js +0 -2
- /package/dist/{chunk-UBU7DBAG.js.map → chunk-3CHAPGUX.js.map} +0 -0
- /package/dist/{chunk-CPXZWVKN.js.map → chunk-BFY4D4RH.js.map} +0 -0
- /package/dist/{chunk-O5U5NVLR.js.map → chunk-OAA7TNB6.js.map} +0 -0
- /package/dist/{chunk-RKHIVWFE.js.map → chunk-X2F3AVGR.js.map} +0 -0
- /package/dist/{processes-5EXCTSD5.js.map → processes-TXEWMXXJ.js.map} +0 -0
- /package/dist/{program-KGILRYLG.js.map → program-QKXRASTV.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as A,b as
|
|
1
|
+
import{a as A,b as or,c as sr,d as ir,e as lr,f as _e,g as cr,h as dr,i as Et,k as pr,n as ur,o as mr,p as fr,q as hr,r as gr,v as xr,w as vr,x as yr,y as wr,z as kr}from"./chunk-BUELCBBV.js";import{a as br}from"./chunk-BYD5B3P3.js";import{a as rr}from"./chunk-BFY4D4RH.js";import{a as kt,b as z,c as er,d as M,i as be,j as _t,k as re,l as K,m as St,n as tr,o as ar,p as nr}from"./chunk-OAA7TNB6.js";import{a as Zn}from"./chunk-2NYP4OQU.js";import{a as ce,b as Qn}from"./chunk-JWDJMFU6.js";import{A as ft,D as Pn,E as jn,Ea as Wn,F as On,Ga as Oe,La as Gn,M as U,N as Nn,Na as Ne,O as Dn,Oa as xt,Pa as vt,Qa as bt,Ra as yt,Sa as Xn,Ta as Kn,Ua as Jn,Va as wt,Xa as Vn,_a as Yn,a as _n,c as dt,d as aa,e as Sn,i as pt,l as We,n as En,sa as zn,ua as qn,va as Fn,w as ra,wa as Un,x as Ln,y as oa,z as mt}from"./chunk-X2F3AVGR.js";import"./chunk-GTJIKXDB.js";import{g as wn,h as kn}from"./chunk-C3VCIEZS.js";import{a as N,b as Hn,c as Bn}from"./chunk-DWZYVYZS.js";import{p as Tn,t as An}from"./chunk-S2GAEH2F.js";import"./chunk-7QDAGGOD.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Cn,e as na}from"./chunk-ACFQBLPX.js";import{g as ut}from"./chunk-LQE73AZR.js";import{b as In,c as Mn}from"./chunk-2D3RYIDU.js";import{m as Rn,n as ht,o as gt,q as $n}from"./chunk-XIYWXCNU.js";import{a as hn,f as gn,g as ea,h as ta,l as xn,m as vn,n as bn,u as it,v as lt,w as ct,x as le,y as yn}from"./chunk-KIXDJEGA.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-BOENB3IK.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-HQWMWSSE.js";import"./chunk-I6HCIQCQ.js";import"./chunk-N4HFUAPN.js";import"./chunk-7OEFPYQJ.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 fn}from"./chunk-HOXHUFZB.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-ECCPLASB.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{F as ln,I as xl,J as cn,K as dn,M as pn,O as un,S as mn,a as tn,b as an,c as fl,da as X,ga as st,q as rt,r as hl,s as Qt,t as Zt,w as gl}from"./chunk-54VYZE7A.js";import{a as ve,i as sn}from"./chunk-PN6XHTG5.js";import{a as nn,b as ot,c as Yt,d as rn,h as on}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function sa(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 _r(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:sa(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Se=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Tt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Se(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Sr(t={}){return M({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
|
|
2
2
|
|
|
3
3
|
<div class="bf-head">
|
|
4
4
|
<div>
|
|
@@ -7,8 +7,8 @@ import{a as A,b as er,c as tr,d as ar,e as nr,f as we,g as rr,h as or,i as sr,m
|
|
|
7
7
|
</div>
|
|
8
8
|
<div class="bf-sync">
|
|
9
9
|
<span class="bf-sync__t" id="synced">Gathering…</span>
|
|
10
|
-
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${
|
|
11
|
-
<button class="ax-btn" id="refresh" title="Refresh now">${
|
|
10
|
+
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${Se(oe.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${Se(oe.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{a as A,b as er,c as tr,d as ar,e as nr,f as we,g as rr,h as or,i as sr,m
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${Tt(oe.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
|
|
25
25
|
<div id="you" class="bf-col"></div>
|
|
26
26
|
|
|
27
|
-
${
|
|
27
|
+
${Tt(oe.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed — not yet automatic</span>')}
|
|
28
28
|
<div id="agents" class="bf-col"></div>
|
|
29
29
|
<button class="ax-btn ax-btn--sm" id="more-actions" hidden></button>
|
|
30
30
|
|
|
31
31
|
<div id="handled"></div>
|
|
32
32
|
</section>
|
|
33
33
|
<aside class="bf-col">
|
|
34
|
-
${
|
|
34
|
+
${Tt(oe.pulse,"In motion","run-count")}
|
|
35
35
|
<div id="running" class="bf-col"></div>
|
|
36
36
|
</aside>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
${
|
|
39
|
+
${Tt(oe.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${
|
|
41
|
+
<div class="bf-search">${Se(oe.search)}
|
|
42
42
|
<input id="search" type="search" placeholder="Search sessions…" 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 @@ ${_t(oe.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">${
|
|
49
|
+
<div class="bf-connect__head">${Se(oe.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">${
|
|
53
|
+
<button class="ax-btn" id="discover">${Se(oe.search)} Discover CLIs</button>
|
|
54
54
|
</div>
|
|
55
55
|
<div class="bf-cli" id="discovered"></div>
|
|
56
56
|
<details class="bf-manual">
|
|
57
|
-
<summary>${
|
|
57
|
+
<summary>${Se(oe.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 @@ ${_t(oe.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:vl,scripts:`<script>${z({decayOf:sa,rankByDecay:_r})}const ICON = ${JSON.stringify(oe)};${bl}</script>`})}var vl=`
|
|
89
89
|
.bf{max-width:1240px;margin:0 auto;padding:22px 24px 48px}
|
|
90
90
|
.bf-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
91
91
|
.bf :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
|
|
@@ -361,7 +361,7 @@ button.bf-tag.is-on{background:color-mix(in oklch,var(--ax-accent) 14%,transpare
|
|
|
361
361
|
.bf{padding:16px 14px 36px}
|
|
362
362
|
.bf-head{flex-direction:column;gap:14px;align-items:stretch}
|
|
363
363
|
.bf-sync{justify-content:space-between}
|
|
364
|
-
}`,
|
|
364
|
+
}`,bl=String.raw`
|
|
365
365
|
(function(){
|
|
366
366
|
const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
367
367
|
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
@@ -776,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
|
|
779
|
+
})();`;function ia(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 la(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 Er(t,e=[],a){let{bands:n,gaps:r}=ia(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:c,track:0,left:f,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>la(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 yl}from"crypto";import{readFileSync as wl,statSync as kl}from"fs";import{resolve as _l,dirname as Sl}from"path";import{fileURLToPath as El}from"url";var Tr=new Map;function At(t){let e=Tr.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Sl(El(import.meta.url)),r=_l(n,"web",t),o=kl(r),s=o.size<8e6?yl("sha1").update(wl(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Tr.set(t,a),a}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},Ct=(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>",Tl=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["person","Person",se.user],["node","Node",se.mesh]],Ar={timeline:"Every run on the mesh, from task traces. The axis breaks over silence — quiet stretches are labelled, not drawn.",map:"The fleet as a transit map: projects are lines, agents are stations, work in flight is a train. Live."};function Cr(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return M({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
|
|
780
780
|
|
|
781
781
|
<div class="ac-head">
|
|
782
782
|
<div>
|
|
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">${
|
|
785
|
+
<p class="ac-sub" id="sub">${Ar[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",se.timeline],["map","Map",se.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${
|
|
789
|
+
${[["timeline","Timeline",se.timeline],["map","Map",se.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Ct(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":""}>${
|
|
794
|
+
<button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${Ct(se.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
|
-
${
|
|
802
|
+
${Tl.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ct(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">${
|
|
809
|
+
<span class="ac-k">${Ct(se.x,11)}canceled</span>
|
|
810
810
|
</div>
|
|
811
811
|
</div>
|
|
812
812
|
|
|
@@ -816,10 +816,10 @@ refresh();
|
|
|
816
816
|
</div>
|
|
817
817
|
|
|
818
818
|
<div id="view-map" class="ac-map"${a?"":" hidden"}>
|
|
819
|
-
<div id="ax-fleet-root" data-hours="24" data-src="${
|
|
819
|
+
<div id="ax-fleet-root" data-hours="24" data-src="${At("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Al,scripts:`<script>${z({computeBands:ia,packTracks:la,buildTimeline:Er})}const ICON = ${JSON.stringify(se)};const SUB = ${JSON.stringify(Ar)};${Cl}</script>`})}var Al=`
|
|
823
823
|
.ac{max-width:1440px;margin:0 auto;padding:22px 24px 48px}
|
|
824
824
|
.ac :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
|
|
825
825
|
.ac-head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:14px}
|
|
@@ -905,7 +905,7 @@ refresh();
|
|
|
905
905
|
@media (max-width:640px){.ac{padding:16px 16px 32px}.ac-head{flex-direction:column;gap:10px}
|
|
906
906
|
.ac-tools{flex-wrap:wrap;padding-top:0}.ac-map{height:calc(100vh - 250px);margin:0 -16px;
|
|
907
907
|
border-left:none;border-right:none;border-radius:0}}
|
|
908
|
-
`,
|
|
908
|
+
`,Cl=String.raw`
|
|
909
909
|
const $=id=>document.getElementById(id);
|
|
910
910
|
const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
911
911
|
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
@@ -1024,7 +1024,7 @@ history.replaceState(null,'',u);
|
|
|
1024
1024
|
if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
|
|
1025
1025
|
$('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
|
|
1026
1026
|
show(view);
|
|
1027
|
-
`;function
|
|
1027
|
+
`;function Ir(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return M({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Il,scripts:`<script src="${At("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Il=`
|
|
1028
1028
|
/* Preload the fonts the redesign's CSS references. Placed in the shell so
|
|
1029
1029
|
* they start fetching while the React bundle is still parsing. */
|
|
1030
1030
|
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
|
|
@@ -1045,8 +1045,8 @@ body { margin: 0; overflow: hidden; }
|
|
|
1045
1045
|
font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1046
1046
|
text-align: center;
|
|
1047
1047
|
}
|
|
1048
|
-
`;import{createServer as
|
|
1049
|
-
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...
|
|
1048
|
+
`;import{createServer as gm}from"http";import{appendFileSync as xm,existsSync as rl,mkdirSync as vm}from"fs";import{readFile as bm}from"fs/promises";import{fileURLToPath as ym}from"url";import{dirname as wm,resolve as tt}from"path";xl();function De(t,e){if(!t)return"absent";let a=Cn(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ee=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function It(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Mr(t.headers["sec-fetch-mode"]),n.site=Mr(t.headers["sec-fetch-site"]),n}function Mr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Ml}from"zlib";var Ll=[41,121,255],Rl=[255,255,255],Lr=new Map;function He(t){let e=Lr.get(t);return e||(e=Pl(t,$l(t)),Lr.set(t,e)),e}function $l(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?Rl:Ll;a.set(c,o*e+1+s*3)}return a}function Pl(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]),ca("IHDR",a),ca("IDAT",Ml(e)),ca("IEND",Buffer.alloc(0))])}function ca(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(Ol(n)),Buffer.concat([a,n,r])}var jl=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 Ol(t){let e=4294967295;for(let a of t)e=jl[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}st();gl();var Nl=7,Dl={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Hl(t,e){let a=t.toLowerCase().split("@")[0],n=Dl[a]??t,r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(r){let o=r[2]==="issue"?"issue":r[2]==="pull"?"pull request":"merge request";return`${n} ${o} #${r[3]} in ${r[1]}`}return n}function Rr(t,e,a){let n=t.toLowerCase().split("@")[0],r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(!r)return null;let[,o,s,i]=r;return n==="gitlab"?`${(a.gitlab||"https://gitlab.com").replace(/\/+$/,"")}/${o}/-/${s==="issue"?"issues":"merge_requests"}/${i}`:n==="github"?`${(a.github||"https://github.com").replace(/\/+$/,"")}/${o}/${s==="issue"?"issues":"pull"}/${i}`:null}function $r(t,e,a={}){let n=a.now??Date.now(),s=(t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?t.prepare("PRAGMA table_info(requests)").all():[]).some(u=>u.name==="person"),i=u=>({id:u.id,state:u.state,agentId:u.agent_id,text:u.text,channel:u.channel,chatId:u.chat_id,createdAt:u.created_at,updatedAt:u.updated_at,closedAt:u.closed_at??null,question:u.question??null,attentionReason:u.attention_reason??null,evidence:u.evidence??null,where:{label:Hl(u.channel,u.chat_id),url:a.linkFor?.(u.channel,u.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Qt.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...Qt).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Zt.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1049
|
+
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...Zt,n-Nl*864e5).map(i):[],p=[];try{p=Et(t,e,10)}catch{}return{open:l,recent:c,runs:p}}function Pr(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function jr(t,e){return!t||e-t>=3e4||t>e}function Mt(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 Or(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 Bl="<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 da(t){return`<meta charset="utf-8">
|
|
1050
1050
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1051
1051
|
<meta name="theme-color" content="#2979FF">
|
|
1052
1052
|
<meta name="referrer" content="no-referrer">
|
|
@@ -1056,8 +1056,8 @@ body { margin: 0; overflow: hidden; }
|
|
|
1056
1056
|
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1057
1057
|
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1058
1058
|
<title>${t}</title>
|
|
1059
|
-
${
|
|
1060
|
-
<style>${
|
|
1059
|
+
${Bl}
|
|
1060
|
+
<style>${kt}${Fl}</style>`}function Nr(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Dr=`
|
|
1061
1061
|
var CACHE = 'agentx-member-v1';
|
|
1062
1062
|
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
1063
1063
|
self.addEventListener('install', function (e) {
|
|
@@ -1087,9 +1087,9 @@ self.addEventListener('fetch', function (e) {
|
|
|
1087
1087
|
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
1088
1088
|
}
|
|
1089
1089
|
});
|
|
1090
|
-
`;function
|
|
1090
|
+
`;function Hr(){return`<!doctype html>
|
|
1091
1091
|
<html lang="en">
|
|
1092
|
-
<head>${
|
|
1092
|
+
<head>${da("My work \xB7 AgentX")}<style>${Ul}</style></head>
|
|
1093
1093
|
<body>
|
|
1094
1094
|
<header class="bar">
|
|
1095
1095
|
<div><h1>My work</h1><p id="who" class="who">Connecting\u2026</p></div>
|
|
@@ -1103,11 +1103,11 @@ self.addEventListener('fetch', function (e) {
|
|
|
1103
1103
|
<section aria-labelledby="h-runs"><h2 id="h-runs">Latest turns</h2><ul id="runs" class="list"><li class="muted">Loading\u2026</li></ul></section>
|
|
1104
1104
|
<p id="updated" class="muted small"></p>
|
|
1105
1105
|
</main>
|
|
1106
|
-
<script>${z({workState:
|
|
1106
|
+
<script>${z({workState:zl,ageText:ql})}${Kl}</script>
|
|
1107
1107
|
</body>
|
|
1108
|
-
</html>`}function
|
|
1108
|
+
</html>`}function Br(){return`<!doctype html>
|
|
1109
1109
|
<html lang="en">
|
|
1110
|
-
<head>${
|
|
1110
|
+
<head>${da("Pair this machine \xB7 AgentX")}<style>${Wl}</style></head>
|
|
1111
1111
|
<body>
|
|
1112
1112
|
<main class="card">
|
|
1113
1113
|
<h1>Pair this machine</h1>
|
|
@@ -1124,20 +1124,20 @@ self.addEventListener('fetch', function (e) {
|
|
|
1124
1124
|
</form>
|
|
1125
1125
|
<p class="muted">No code? Ask the owner to run <code>agentx people invite <you></code>. A code works once, for 10 minutes.</p>
|
|
1126
1126
|
</main>
|
|
1127
|
-
<script>${z({formatPairInput:
|
|
1127
|
+
<script>${z({formatPairInput:Mt})}${Gl}</script>
|
|
1128
1128
|
</body>
|
|
1129
|
-
</html>`}function
|
|
1129
|
+
</html>`}function zr(){return`<!doctype html>
|
|
1130
1130
|
<html lang="en">
|
|
1131
|
-
<head>${
|
|
1131
|
+
<head>${da("Waiting for the owner \xB7 AgentX")}</head>
|
|
1132
1132
|
<body>
|
|
1133
1133
|
<main class="card">
|
|
1134
1134
|
<h1>Waiting for the owner</h1>
|
|
1135
1135
|
<p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens by itself when they do.</p>
|
|
1136
1136
|
<p class="muted">If they said no, this page will ask for a new code.</p>
|
|
1137
1137
|
</main>
|
|
1138
|
-
<script>${
|
|
1138
|
+
<script>${Xl}</script>
|
|
1139
1139
|
</body>
|
|
1140
|
-
</html>`}function
|
|
1140
|
+
</html>`}function zl(t){let e=String(t||"");return e==="in_progress"?{label:"In progress",tone:"ok"}:e==="waiting_owner"?{label:"Waiting on the owner",tone:"warn"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"warn"}:e==="needs_attention"?{label:"Stuck: needs attention",tone:"bad"}:e==="done"?{label:"Done",tone:"ok"}:e==="declined"?{label:"Declined",tone:"bad"}:e==="dropped"?{label:"Dropped",tone:"muted"}:{label:e.replace(/_/g," "),tone:"muted"}}function ql(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min":Math.floor(r/24)+" d "+r%24+" h"}var Fl=`
|
|
1141
1141
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
1142
1142
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
1143
1143
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -1146,7 +1146,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1146
1146
|
.muted { color: var(--ax-text-2); }
|
|
1147
1147
|
.small { font-size: var(--ax-fs-xs); }
|
|
1148
1148
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
1149
|
-
`,
|
|
1149
|
+
`,Ul=`
|
|
1150
1150
|
body { display: flex; flex-direction: column; }
|
|
1151
1151
|
.bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; background: var(--ax-surface); border-bottom: var(--ax-border-w) solid var(--ax-border); }
|
|
1152
1152
|
.bar h1 { font-size: 18px; margin: 0; font-weight: 700; }
|
|
@@ -1169,7 +1169,7 @@ main h2 { font-size: 16px; margin: 12px 0 8px; }
|
|
|
1169
1169
|
[data-theme="dark"] .state.bad { color: var(--ax-red); }
|
|
1170
1170
|
.state.muted { color: var(--ax-text-2); }
|
|
1171
1171
|
a { color: var(--ax-accent); }
|
|
1172
|
-
`,
|
|
1172
|
+
`,Wl=`
|
|
1173
1173
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
1174
1174
|
.pair-form label { font-weight: 600; }
|
|
1175
1175
|
.pair-form input { box-sizing: border-box; width: 100%; min-height: 48px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: 2px solid var(--ax-border); border-radius: var(--ax-radius-sm); }
|
|
@@ -1181,7 +1181,7 @@ a { color: var(--ax-accent); }
|
|
|
1181
1181
|
.pair-msg.bad { color: var(--ax-red-ink); }
|
|
1182
1182
|
[data-theme="dark"] .pair-msg.bad { color: var(--ax-red); }
|
|
1183
1183
|
.pair-offline { margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
|
|
1184
|
-
`,
|
|
1184
|
+
`,Gl=`
|
|
1185
1185
|
(function () {
|
|
1186
1186
|
var form = document.getElementById('pair-form');
|
|
1187
1187
|
var machine = document.getElementById('machine');
|
|
@@ -1225,7 +1225,7 @@ a { color: var(--ax-accent); }
|
|
|
1225
1225
|
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1226
1226
|
});
|
|
1227
1227
|
})();
|
|
1228
|
-
`,
|
|
1228
|
+
`,Xl=`
|
|
1229
1229
|
(function () {
|
|
1230
1230
|
var msg = document.getElementById('msg');
|
|
1231
1231
|
function check() {
|
|
@@ -1236,7 +1236,7 @@ a { color: var(--ax-accent); }
|
|
|
1236
1236
|
}
|
|
1237
1237
|
setInterval(check, 5000);
|
|
1238
1238
|
})();
|
|
1239
|
-
|
|
1239
|
+
`,Kl=`
|
|
1240
1240
|
(function () {
|
|
1241
1241
|
var who = document.getElementById('who');
|
|
1242
1242
|
var offline = document.getElementById('offline');
|
|
@@ -1297,10 +1297,10 @@ a { color: var(--ax-accent); }
|
|
|
1297
1297
|
load();
|
|
1298
1298
|
setInterval(load, 30000);
|
|
1299
1299
|
})();
|
|
1300
|
-
`;var Ct="agentx_member",Pl=90*86400,jl=new ft,Dr=t=>t.replace(/^\[app\]/,"[member]"),Ol=new _e(t=>console.log(Dr(t))),jr=new WeakMap;function Nl(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Ol;let e=jr.get(t.log);return e||jr.set(t.log,e=new _e(a=>t.log(Dr(a)))),e}var Or=null;function It(t,e=G){try{return Or=e().people}catch{return Or??t}}async function Hr(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new X(r.root),s=r.members??new ot(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new dt(r.root),limiter:r.pairLimiter??jl,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return xe(e,200,"application/manifest+json",Mr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),xe(e,200,"text/javascript; charset=utf-8",Lr);if(a==="/member/icon-192.png")return xe(e,200,"image/png",De(192),"public, max-age=86400");if(a==="/member/icon-512.png")return xe(e,200,"image/png",De(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await lr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Nr(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Ee(e,p.status,p.body)}let l=cr(Dl(t),i,ir(t));if(!l.ok){if(l.status===401){let p=ca(t);return Nl(r).record(a.slice(0,120),Tt(t,Ne(da(t,Ct),o),p?Ne(p,o):null)),a==="/member"?xe(e,401,"text/html; charset=utf-8",$r()):Ee(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?xe(e,202,"text/html; charset=utf-8",Pr()):Ee(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId);if(n==="GET"&&a==="/member"){let p=da(t,Ct);return p&&!ca(t)&&e.setHeader("Set-Cookie",Nr(p)),xe(e,200,"text/html; charset=utf-8",Rr())}if(n==="GET"&&a==="/api/member/me")return Ee(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let p=r.db?.()??null;return p?Ee(e,200,Tr(p,l.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Ee(e,503,{error:"the work list needs the database"})}return Ee(e,404,{error:"not found"})}function Nr(t){return`${Ct}=${t}; Path=/; Max-Age=${Pl}; HttpOnly; Secure; SameSite=Lax`}function Dl(t){return ca(t)??da(t,Ct)}function ca(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function da(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function xe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ee(t,e,a){return xe(t,e,"application/json",JSON.stringify(a))}Qi();var Br='/*! 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 Lt,readFileSync as Kr,writeFileSync as Jr,rmSync as Lf,mkdirSync as Ul,copyFileSync as Wl,readdirSync as Gl}from"fs";import{resolve as He}from"path";Zi();function qr(t){let e=at.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:at.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 Mt(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=at.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var zr=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Fr(t){return Mt(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 Ur(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Mt((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:zr(t?.chats),senders:zr(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function Wr(t){let e=String(t?.id??"");return Mt(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 Gr(t){let e=String(t?.id??"");return Mt(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}"`})}rt();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 Xr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Oe({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.`})+wt([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Bl()+Vn,css:ql,scripts:`${e}<script>${Yn}
|
|
1301
|
-
${
|
|
1302
|
-
${
|
|
1303
|
-
${
|
|
1300
|
+
`;var Lt="agentx_member",Jl=90*86400,Vl=new gt,Wr=t=>t.replace(/^\[app\]/,"[member]"),Yl=new Ee(t=>console.log(Wr(t))),qr=new WeakMap;function Ql(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Yl;let e=qr.get(t.log);return e||qr.set(t.log,e=new Ee(a=>t.log(Wr(a)))),e}var Fr=null;function Ge(t,e=X){try{return Fr=e().people}catch{return Fr??t}}async function Gr(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new it(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ut(r.root),limiter:r.pairLimiter??Vl,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return ye(e,200,"application/manifest+json",Nr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),ye(e,200,"text/javascript; charset=utf-8",Dr);if(a==="/member/icon-192.png")return ye(e,200,"image/png",He(192),"public, max-age=86400");if(a==="/member/icon-512.png")return ye(e,200,"image/png",He(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await mr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Ur(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Te(e,p.status,p.body)}let l=hr(Zl(t),i,ur(t));if(!l.ok){if(l.status===401){let p=pa(t);return Ql(r).record(a.slice(0,120),It(t,De(ua(t,Lt),o),p?De(p,o):null)),a==="/member"?ye(e,401,"text/html; charset=utf-8",Br()):Te(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?ye(e,202,"text/html; charset=utf-8",zr()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId);if(n==="GET"&&a==="/member"){let p=ua(t,Lt);return p&&!pa(t)&&e.setHeader("Set-Cookie",Ur(p)),ye(e,200,"text/html; charset=utf-8",Hr())}if(n==="GET"&&a==="/api/member/me")return Te(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let p=r.db?.()??null;return p?Te(e,200,$r(p,l.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Te(e,503,{error:"the work list needs the database"})}return Te(e,404,{error:"not found"})}function Ur(t){return`${Lt}=${t}; Path=/; Max-Age=${Jl}; HttpOnly; Secure; SameSite=Lax`}function Zl(t){return pa(t)??ua(t,Lt)}function pa(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ua(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 ye(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Te(t,e,a){return ye(t,e,"application/json",JSON.stringify(a))}fl();var Xr='/*! 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 $t,readFileSync as to,writeFileSync as ao,rmSync as Yf,mkdirSync as oc,copyFileSync as sc,readdirSync as ic}from"fs";import{resolve as Be}from"path";hl();function Jr(t){let e=rt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:rt.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 Rt(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=rt.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 Kr=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Vr(t){return Rt(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 Yr(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Rt((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:Kr(t?.chats),senders:Kr(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 Qr(t){let e=String(t?.id??"");return Rt(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 Zr(t){let e=String(t?.id??"");return Rt(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}"`})}st();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 eo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=be({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.`})+_t([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+tc()+tr,css:nc,scripts:`${e}<script>${ar}
|
|
1301
|
+
${nr}
|
|
1302
|
+
${ec}
|
|
1303
|
+
${rc}</script>`})}var ec=`
|
|
1304
1304
|
(function(){
|
|
1305
1305
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1306
1306
|
async function voiceMissing() {
|
|
@@ -1394,8 +1394,8 @@ ${Fl}</script>`})}var Hl=`
|
|
|
1394
1394
|
refresh();
|
|
1395
1395
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1396
1396
|
document.addEventListener('ax-config-saved', refresh);
|
|
1397
|
-
})();`;function
|
|
1398
|
-
`:"";return
|
|
1397
|
+
})();`;function tc(){let t=Bn().business?`<button data-tab="business">Business</button>
|
|
1398
|
+
`:"";return ac.replace("__BUSINESS_TABS__",t)}var ac=`
|
|
1399
1399
|
<div id="peer-banner" class="peer-banner">
|
|
1400
1400
|
<span class="label">Managing</span>
|
|
1401
1401
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -1647,10 +1647,10 @@ ${Fl}</script>`})}var Hl=`
|
|
|
1647
1647
|
</div>
|
|
1648
1648
|
</details>
|
|
1649
1649
|
|
|
1650
|
-
<div id="ch-chatapps-label">${
|
|
1650
|
+
<div id="ch-chatapps-label">${St({label:"Chat apps"})}</div>
|
|
1651
1651
|
<div class="ax-connectors" id="ch-chatapps"></div>
|
|
1652
1652
|
|
|
1653
|
-
<div id="ch-devtools-label">${
|
|
1653
|
+
<div id="ch-devtools-label">${St({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
|
|
1654
1654
|
<div class="ax-connectors" id="ch-devtools"></div>
|
|
1655
1655
|
|
|
1656
1656
|
<!-- Active-channel configuration panes. One shows at a time; clicking
|
|
@@ -1811,7 +1811,7 @@ ${Fl}</script>`})}var Hl=`
|
|
|
1811
1811
|
${K({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."})}
|
|
1812
1812
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
1813
1813
|
${re({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."})}
|
|
1814
|
-
${
|
|
1814
|
+
${St({label:"Connected peers"})}
|
|
1815
1815
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
1816
1816
|
<div class="add-form">
|
|
1817
1817
|
<h3>Add a peer</h3>
|
|
@@ -2054,7 +2054,7 @@ ${Fl}</script>`})}var Hl=`
|
|
|
2054
2054
|
<div class="hint-block">Every setting is documented in the <code>docs/reference/config.md</code> reference. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
|
|
2055
2055
|
</section>
|
|
2056
2056
|
</main>
|
|
2057
|
-
`,
|
|
2057
|
+
`,nc=`
|
|
2058
2058
|
|
|
2059
2059
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
2060
2060
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2262,7 +2262,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2262
2262
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2263
2263
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2264
2264
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2265
|
-
`,
|
|
2265
|
+
`,rc=`
|
|
2266
2266
|
const $ = (id) => document.getElementById(id);
|
|
2267
2267
|
let state = null;
|
|
2268
2268
|
|
|
@@ -5146,11 +5146,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
5146
5146
|
})();
|
|
5147
5147
|
|
|
5148
5148
|
refresh();
|
|
5149
|
-
`;function Vr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xr({peers:a,localToken:n}))}async function Yr(t,e){let a=ma();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Qr(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await sc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Xl(t),r={"GET /api/admin/state":()=>Jl(),"POST /api/admin/agents":()=>tc(n),"PATCH /api/admin/agents":()=>ac(n),"DELETE /api/admin/agents":()=>nc(n),"POST /api/admin/agents/access":()=>Vl(n),"POST /api/admin/channels/telegram":()=>rc(n),"DELETE /api/admin/channels/telegram":()=>Cc(n),"POST /api/admin/channels/telegram/toggle":()=>Ic(n),"POST /api/admin/crons":()=>Mc(n),"DELETE /api/admin/crons":()=>Lc(n),"POST /api/admin/config/raw":()=>Rc(n),"GET /api/admin/tokens":()=>Yl(),"POST /api/admin/tokens":()=>Ql(n),"DELETE /api/admin/tokens":()=>Zl(n),"POST /api/admin/agents/test":()=>ec(n),"POST /api/admin/agents/integrations":()=>uc(n),"DELETE /api/admin/agents/integrations":()=>mc(n),"PATCH /api/admin/agents/integrations":()=>fc(n),"PATCH /api/admin/channels/telegram":()=>oc(n),"POST /api/admin/channels/slack":()=>wc(n),"POST /api/admin/channels/slack/toggle":()=>kc(n),"POST /api/admin/channels/discord":()=>_c(n),"POST /api/admin/channels/discord/toggle":()=>Ec(n),"POST /api/admin/channels/gitlab":()=>Sc(n),"POST /api/admin/channels/gitlab/toggle":()=>Tc(n),"POST /api/admin/channels/request-status":()=>pr(n),"GET /api/admin/channels/whatsapp/state":()=>We("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>We("/webrtc/history"),"POST /api/admin/actions":()=>Wc(n),"DELETE /api/admin/actions":()=>Gc(n),"POST /api/admin/actions/run":()=>Xc(n),"GET /api/admin/channels/whatsapp/chats":()=>We("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>We("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ue("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Ac(n),"POST /api/admin/webhooks":()=>hc(n),"PATCH /api/admin/webhooks":()=>gc(n),"DELETE /api/admin/webhooks":()=>yc(n),"POST /api/admin/whatsapp-triage":()=>Fr(n),"POST /api/admin/whatsapp-triage/rules":()=>Ur(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Wr(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Gr(n),"POST /api/admin/mesh/peers":()=>xc(n),"DELETE /api/admin/mesh/peers":()=>vc(n),"POST /api/admin/mesh/toggle":()=>bc(n),"GET /api/admin/files":()=>ic(t),"GET /api/admin/files/read":()=>lc(t),"PUT /api/admin/files":()=>cc(n),"POST /api/admin/files/skill":()=>dc(n),"DELETE /api/admin/files/skill":()=>pc(n),"POST /api/admin/business/orgchart":()=>$c(n),"DELETE /api/admin/business/orgchart":()=>Pc(n),"POST /api/admin/business/project":()=>jc(n),"DELETE /api/admin/business/project":()=>Dc(n),"POST /api/admin/business/client":()=>Oc(n),"DELETE /api/admin/business/client":()=>Nc(n),"POST /api/admin/business/contact":()=>Hc(n),"DELETE /api/admin/business/contact":()=>Bc(n),"POST /api/admin/boards":()=>zc(n),"DELETE /api/admin/boards":()=>qc(n),"POST /api/admin/boards/columns":()=>Fc(n),"DELETE /api/admin/boards/columns":()=>Uc(n),"POST /api/admin/notifications":()=>Jc(n),"POST /api/admin/screen":()=>Vc(n),"POST /api/admin/webhooks/triggers":()=>Yc(n),"POST /api/admin/mesh/health":()=>Kc(n),"GET /api/admin/projects":()=>We("/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){pa(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();pa(e,200,i)}catch(n){pa(e,400,{error:n.message||"admin op failed"})}}function pa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Xl(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 Kl(t){let e=He(process.cwd(),t);if(!Lt(e))return[];let a=[];for(let n of Gl(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Kr(He(e,n.name),"utf-8")))}catch{}return a}function ma(){let t=He(process.cwd(),"agentx.json");return Lt(t)?JSON.parse(Kr(t,"utf-8")):null}function Jl(){let t=ma();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[T,y]of Object.entries(v))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?w[T]=process.env[y]?"set":"unset":typeof y=="string"&&(w[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},_={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:wn(k.local),ntfy:mr(t.channels?.ntfy)},E=[];try{E=Kl(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:dr(t),whatsappTriage:qr(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:Wn(t.screen),actions:E}}function Vl(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 Yl(){return new X().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 Ql(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 X().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Zl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new X().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function ec(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=G();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 tc(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=eo(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=He(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=He(i,"CLAUDE.md");if(!Lt(c))try{Ul(i,{recursive:!0}),Jr(c,`# ${a}
|
|
5149
|
+
`;function no(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(eo({peers:a,localToken:n}))}async function ro(t,e){let a=ha();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function oo(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await wc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await lc(t),r={"GET /api/admin/state":()=>dc(),"POST /api/admin/agents":()=>gc(n),"PATCH /api/admin/agents":()=>xc(n),"DELETE /api/admin/agents":()=>vc(n),"POST /api/admin/agents/access":()=>pc(n),"POST /api/admin/channels/telegram":()=>bc(n),"DELETE /api/admin/channels/telegram":()=>Fc(n),"POST /api/admin/channels/telegram/toggle":()=>Uc(n),"POST /api/admin/crons":()=>Wc(n),"DELETE /api/admin/crons":()=>Gc(n),"POST /api/admin/config/raw":()=>Xc(n),"GET /api/admin/tokens":()=>uc(),"POST /api/admin/tokens":()=>mc(n),"DELETE /api/admin/tokens":()=>fc(n),"POST /api/admin/agents/test":()=>hc(n),"POST /api/admin/agents/integrations":()=>Ac(n),"DELETE /api/admin/agents/integrations":()=>Cc(n),"PATCH /api/admin/agents/integrations":()=>Ic(n),"PATCH /api/admin/channels/telegram":()=>yc(n),"POST /api/admin/channels/slack":()=>Oc(n),"POST /api/admin/channels/slack/toggle":()=>Nc(n),"POST /api/admin/channels/discord":()=>Dc(n),"POST /api/admin/channels/discord/toggle":()=>Hc(n),"POST /api/admin/channels/gitlab":()=>Bc(n),"POST /api/admin/channels/gitlab/toggle":()=>zc(n),"POST /api/admin/channels/request-status":()=>vr(n),"GET /api/admin/channels/whatsapp/state":()=>Xe("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Xe("/webrtc/history"),"POST /api/admin/actions":()=>sd(n),"DELETE /api/admin/actions":()=>id(n),"POST /api/admin/actions/run":()=>ld(n),"GET /api/admin/channels/whatsapp/chats":()=>Xe("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Xe("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>qc(n),"POST /api/admin/webhooks":()=>Mc(n),"PATCH /api/admin/webhooks":()=>Lc(n),"DELETE /api/admin/webhooks":()=>jc(n),"POST /api/admin/whatsapp-triage":()=>Vr(n),"POST /api/admin/whatsapp-triage/rules":()=>Yr(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Qr(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Zr(n),"POST /api/admin/mesh/peers":()=>Rc(n),"DELETE /api/admin/mesh/peers":()=>$c(n),"POST /api/admin/mesh/toggle":()=>Pc(n),"GET /api/admin/files":()=>kc(t),"GET /api/admin/files/read":()=>_c(t),"PUT /api/admin/files":()=>Sc(n),"POST /api/admin/files/skill":()=>Ec(n),"DELETE /api/admin/files/skill":()=>Tc(n),"POST /api/admin/business/orgchart":()=>Kc(n),"DELETE /api/admin/business/orgchart":()=>Jc(n),"POST /api/admin/business/project":()=>Vc(n),"DELETE /api/admin/business/project":()=>Zc(n),"POST /api/admin/business/client":()=>Yc(n),"DELETE /api/admin/business/client":()=>Qc(n),"POST /api/admin/business/contact":()=>ed(n),"DELETE /api/admin/business/contact":()=>td(n),"POST /api/admin/boards":()=>ad(n),"DELETE /api/admin/boards":()=>nd(n),"POST /api/admin/boards/columns":()=>rd(n),"DELETE /api/admin/boards/columns":()=>od(n),"POST /api/admin/notifications":()=>dd(n),"POST /api/admin/screen":()=>pd(n),"POST /api/admin/webhooks/triggers":()=>ud(n),"POST /api/admin/mesh/health":()=>cd(n),"GET /api/admin/projects":()=>Xe("/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){ma(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ma(e,200,i)}catch(n){ma(e,400,{error:n.message||"admin op failed"})}}function ma(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function lc(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 cc(t){let e=Be(process.cwd(),t);if(!$t(e))return[];let a=[];for(let n of ic(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(to(Be(e,n.name),"utf-8")))}catch{}return a}function ha(){let t=Be(process.cwd(),"agentx.json");return $t(t)?JSON.parse(to(t,"utf-8")):null}function dc(){let t=ha();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[T,y]of Object.entries(v))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?w[T]=process.env[y]?"set":"unset":typeof y=="string"&&(w[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},_={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:Tn(k.local),ntfy:yr(t.channels?.ntfy)},S=[];try{S=cc(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:xr(t),whatsappTriage:Jr(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:Vn(t.screen),actions:S}}function pc(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 uc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function mc(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function fc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function hc(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function gc(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=io(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=Be(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=Be(i,"CLAUDE.md");if(!$t(c))try{oc(i,{recursive:!0}),ao(c,`# ${a}
|
|
5150
5150
|
|
|
5151
5151
|
${s||"You are "+a+"."}
|
|
5152
|
-
`)}catch{}return{summary:l}}function ac(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=eo(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 nc(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 rc(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 oc(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 We(t){let{url:e,headers:a}=fa(),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}=fa(),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 sc(t,e){try{let{url:a,headers:n}=fa(),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 fa(){let t="http://127.0.0.1:18800",e={};try{let a=G();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ge(t){let a=ma()?.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 ua(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ic(t){let e=ua(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=je(Ge(e));return{agentId:e,...a}}function lc(t){let e=ua(t,"agent").trim(),a=ua(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return ht(Ge(e),a)}function cc(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=gt(Ge(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function dc(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=xt(Ge(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function pc(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=vt(Ge(e),a);return{summary:`removed skill "${a}"`,...n}}function uc(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 mc(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 fc(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 Zr=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function hc(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!Zr.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 gc(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"&&Zr.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 xc(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 vc(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 bc(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 yc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function wc(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function kc(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 _c(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 Ec(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 Sc(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 Tc(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 Ac(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-F6NRVZ7W.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 Cc(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 Ic(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 Mc(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 Lc(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 Rc(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=He(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Lt(n))try{Wl(n,r)}catch{}Jr(n,JSON.stringify(a,null,2)+`
|
|
5153
|
-
`,"utf-8");try{let s=G().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 eo(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function $c(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 Pc(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 jc(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 Oc(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 Nc(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 Dc(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 Hc(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 Bc(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 zc(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 qc(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 Fc(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 Uc(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 Wc(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 Gc(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 Xc(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 Kc(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 Jc(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=kn(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=fr(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 Vc(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 Yc(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}}rt();import{resolve as ed}from"path";function to(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5152
|
+
`)}catch{}return{summary:l}}function xc(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=io(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 vc(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 bc(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 yc(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 Xe(t){let{url:e,headers:a}=ga(),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}=ga(),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 wc(t,e){try{let{url:a,headers:n}=ga(),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 ga(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ke(t){let a=ha()?.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 fa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function kc(t){let e=fa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Ne(Ke(e));return{agentId:e,...a}}function _c(t){let e=fa(t,"agent").trim(),a=fa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return xt(Ke(e),a)}function Sc(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=vt(Ke(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Ec(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=bt(Ke(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Tc(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=yt(Ke(e),a);return{summary:`removed skill "${a}"`,...n}}function Ac(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 Cc(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 Ic(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 so=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Mc(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(!so.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 Lc(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"&&so.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 Rc(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 $c(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 Pc(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 jc(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 Oc(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 Nc(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 Dc(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 Hc(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 Bc(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 zc(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 qc(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-F6NRVZ7W.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 Fc(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 Uc(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 Wc(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 Gc(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 Xc(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=Be(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if($t(n))try{sc(n,r)}catch{}ao(n,JSON.stringify(a,null,2)+`
|
|
5153
|
+
`,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function io(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Kc(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 Jc(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 Vc(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 Yc(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 Qc(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 Zc(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 ed(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 td(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 ad(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 nd(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 rd(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 od(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 sd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function id(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function ld(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 cd(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 dd(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=An(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=wr(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 pd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=Yn(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function ud(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}}st();import{resolve as hd}from"path";function lo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5154
5154
|
|
|
5155
5155
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
5156
5156
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -5205,7 +5205,7 @@ ${s||"You are "+a+"."}
|
|
|
5205
5205
|
<h2>Recent classifications</h2>
|
|
5206
5206
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
5207
5207
|
<div id="recent"></div>
|
|
5208
|
-
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5208
|
+
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:md,scripts:`${e}<script>${fd}</script>`})}var md=`
|
|
5209
5209
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
5210
5210
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
5211
5211
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5309,7 +5309,7 @@ details {
|
|
|
5309
5309
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5310
5310
|
}
|
|
5311
5311
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5312
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
5312
|
+
details[open] summary { margin-bottom: 8px; }`,fd=`
|
|
5313
5313
|
const $ = (id) => document.getElementById(id);
|
|
5314
5314
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5315
5315
|
|
|
@@ -5529,7 +5529,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5529
5529
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5530
5530
|
|
|
5531
5531
|
refresh();
|
|
5532
|
-
`;function
|
|
5532
|
+
`;function po(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lo({peers:a,localToken:n}))}async function uo(t,e,a){try{let n=t.method==="GET"?void 0:await Sd(t),r=gd(),o={"GET /api/admin/graph/state":()=>xd(r),"POST /api/admin/graph/classifications/approve":()=>vd(r,n),"POST /api/admin/graph/classifications/reject":()=>bd(r,n),"POST /api/admin/graph/nodes":()=>yd(r,n),"PATCH /api/admin/graph/nodes":()=>wd(r,n),"DELETE /api/admin/graph/nodes":()=>kd(r,n),"PUT /api/admin/graph/schema":()=>_d(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){xa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();xa(e,200,l)}catch(n){xa(e,400,{error:n?.message||"graph op failed"})}}function gd(){let t=X(),e=hd(process.cwd(),t.graph.baseDir);return new fn({baseDir:e})}function xd(t){let e=X(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function vd(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=mo(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=va(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function bd(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=mo(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function mo(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 yd(t,e){let a=co(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?co(String(e.parentId)):null,o=va({[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 wd(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=va({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function kd(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function _d(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 va(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 co(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function xa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Sd(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 fo=`
|
|
5533
5533
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
5534
5534
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
5535
5535
|
<p class="apv__lead">What you asked agents for that is not finished, oldest first. Nothing leaves this list by getting old: close it as done, or drop it.</p>
|
|
@@ -5546,7 +5546,7 @@ refresh();
|
|
|
5546
5546
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5547
5547
|
</form>
|
|
5548
5548
|
</details>
|
|
5549
|
-
</section>`,
|
|
5549
|
+
</section>`,ho=`
|
|
5550
5550
|
.apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
|
|
5551
5551
|
.apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
|
|
5552
5552
|
.apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
|
|
@@ -5555,7 +5555,7 @@ refresh();
|
|
|
5555
5555
|
.apv__state.is-needs_attention { color: var(--ax-err); }
|
|
5556
5556
|
.apv__state.is-waiting_owner { color: var(--ax-amber-ink); }
|
|
5557
5557
|
.apv__req input[type=text].apv__evidence { flex: 1 1 220px; min-width: 0; font: inherit; font-size: 13px; padding: 8px 10px; border-radius: var(--ax-radius-sm); border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-text); }
|
|
5558
|
-
`,
|
|
5558
|
+
`,go=`
|
|
5559
5559
|
(function(){
|
|
5560
5560
|
var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
|
|
5561
5561
|
function $(id){ return document.getElementById(id); }
|
|
@@ -5650,7 +5650,7 @@ load();
|
|
|
5650
5650
|
document.addEventListener('apv:decided', load);
|
|
5651
5651
|
setInterval(function(){ if (document.visibilityState === 'visible' && !$('req-section').contains(document.activeElement)) load(); }, 60000);
|
|
5652
5652
|
})();
|
|
5653
|
-
`;function
|
|
5653
|
+
`;function xo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
5654
5654
|
<header class="apv__head">
|
|
5655
5655
|
<div>
|
|
5656
5656
|
<h1>Approvals</h1>
|
|
@@ -5672,7 +5672,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !$('req-se
|
|
|
5672
5672
|
<ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
|
|
5673
5673
|
<p id="apv-snoozed" class="apv__foot"></p>
|
|
5674
5674
|
|
|
5675
|
-
${
|
|
5675
|
+
${fo}
|
|
5676
5676
|
|
|
5677
5677
|
<details class="apv__settings" id="apv-settings">
|
|
5678
5678
|
<summary>Settings: expiry, later, daily digest</summary>
|
|
@@ -5687,7 +5687,7 @@ ${so}
|
|
|
5687
5687
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5688
5688
|
</form>
|
|
5689
5689
|
</details>
|
|
5690
|
-
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5690
|
+
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ed+ho,scripts:`${e}<script>${Td}</script><script>${go}</script>`})}var Ed=`
|
|
5691
5691
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
5692
5692
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
5693
5693
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -5736,7 +5736,7 @@ ${so}
|
|
|
5736
5736
|
@media (max-width: 560px) {
|
|
5737
5737
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
5738
5738
|
}
|
|
5739
|
-
`,
|
|
5739
|
+
`,Td=`
|
|
5740
5740
|
(function(){
|
|
5741
5741
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
5742
5742
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -5904,7 +5904,199 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
5904
5904
|
load();
|
|
5905
5905
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
5906
5906
|
})();
|
|
5907
|
-
`;var
|
|
5907
|
+
`;var Je="/api/admin/approvals/requests",vo=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function bo(t,e,a,n){try{return await Ad(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Ad(t,e,a,n){if(t==="GET"&&e===Je){let r=oa(n);return{status:200,body:{items:r?r.listOpen():[],settings:ra(n.configPath)}}}if(t==="POST"&&e===`${Je}/close`){let r=typeof a.id=="string"?a.id:"",o=a.action;if(!r||o!=="done"&&o!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let s=oa(n),i=s?.get(r);if(!s||!i||i.state==="candidate")return{status:404,body:{error:`no request "${r}"`}};let l=o==="done"?typeof a.evidence=="string"?a.evidence:"":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return s.close(r,o==="done"?"done":"dropped",l,n.now??Date.now())?{status:200,body:{ok:!0,message:o==="done"?`${r} closed as done`:`${r} dropped`}}:{status:409,body:{error:`${r} is already closed`}}}if(t==="POST"&&e===`${Je}/settings`){let r={},o=i=>{let l=a[i];if(l!==void 0){if(typeof l!="number"||!(l>0))throw new Error(`${i} must be a positive number`);return l}};typeof a.enabled=="boolean"&&(r.enabled=a.enabled),r.from=vo(a.from),r.channels=vo(a.channels),r.staleAfterHours=o("staleAfterHours"),r.retentionDays=o("retentionDays");let s=await Ln(r,{configPath:n.configPath,reload:n.reload});return s.success?{status:200,body:{ok:!0,settings:ra(n.configPath)}}:{status:400,body:{error:s.error}}}return{status:404,body:{error:"Not found"}}}var Cd=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Pt(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 yo(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(xo({peers:e,localToken:a}))}async function wo(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Je)){let i=await bo(o,a,o==="POST"?await Pt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=mt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:_e(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Pt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Cd.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=_e(s.configPath),u=await ft(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(te(e,200,{ok:!0,message:u.message}),!0):(te(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Pt(t),l=Pn(s,typeof i.key=="string"?i.key:"",!!_e(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Pt(t),l={},c=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let f=cr(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await dr(l,{configPath:s.configPath,reload:s.reload});return p.success?(te(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(te(e,400,{error:p.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}mn();function ko(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=be({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates and guests. Open a person to see the machines they paired and what they asked for."})+`
|
|
5908
|
+
<div class="pp">
|
|
5909
|
+
<div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
|
|
5910
|
+
<section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
|
|
5911
|
+
<h2 id="pp-none-title">Nobody has paired a machine yet</h2>
|
|
5912
|
+
<p>A teammate gets one page of their own, <b>My work</b>, on a machine you approve. To invite someone, from the folder that holds <code>agentx.json</code>:</p>
|
|
5913
|
+
<ol>
|
|
5914
|
+
<li>List them, with the identity they write from: <code>agentx people add sara --name "Sara B" --identity gitlab:sara.b</code></li>
|
|
5915
|
+
<li>Make their one-time code: <code>agentx people invite sara</code></li>
|
|
5916
|
+
<li>Send them the address and the code it prints, then say yes to their machine in <a href="/approvals">Approvals</a>.</li>
|
|
5917
|
+
</ol>
|
|
5918
|
+
</section>
|
|
5919
|
+
<ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
|
|
5920
|
+
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Id,scripts:`${e}<script>${Md}</script>`})}var Id=`
|
|
5921
|
+
.pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
|
|
5922
|
+
.pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
|
|
5923
|
+
.pp-msg.is-bad { color: var(--ax-red-ink); }
|
|
5924
|
+
.pp-none { margin: 0 0 16px; padding: 14px 16px; border: var(--ax-border-w) dashed var(--ax-border-2); border-radius: var(--ax-radius); background: var(--ax-surface); font-size: var(--ax-fs-sm); }
|
|
5925
|
+
.pp-none h2 { margin: 0 0 6px; font-size: 15px; }
|
|
5926
|
+
.pp-none p { margin: 0 0 8px; color: var(--ax-text-2); }
|
|
5927
|
+
.pp-none ol { margin: 0; padding-left: 20px; display: grid; gap: 6px; }
|
|
5928
|
+
.pp code { font-family: var(--ax-mono); font-size: 11.5px; background: var(--ax-surface-2); padding: 1px 6px; border-radius: var(--ax-radius-sm); }
|
|
5929
|
+
.pp-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
|
|
5930
|
+
.pp-empty { color: var(--ax-text-2); }
|
|
5931
|
+
.pp-person { border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
5932
|
+
.pp-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; width: 100%; padding: 14px 16px; background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; border-radius: var(--ax-radius); }
|
|
5933
|
+
.pp-head:focus-visible { outline: 2px solid var(--ax-accent); outline-offset: 2px; }
|
|
5934
|
+
.pp-name { font-size: 16px; font-weight: 600; }
|
|
5935
|
+
.pp-id { font-family: var(--ax-mono); font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
5936
|
+
.pp-count { margin-left: auto; font-size: var(--ax-fs-sm); color: var(--ax-text-2); }
|
|
5937
|
+
.pp-count b { color: var(--ax-amber-ink); font-weight: 600; }
|
|
5938
|
+
.pp-caret { color: var(--ax-text-2); transition: transform 0.15s; }
|
|
5939
|
+
.pp-head[aria-expanded="true"] .pp-caret { transform: rotate(90deg); }
|
|
5940
|
+
.pp-ids { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 4px 8px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
5941
|
+
.pp-ids span { font-family: var(--ax-mono); }
|
|
5942
|
+
.pp-body { padding: 0 16px 16px; border-top: var(--ax-border-w) solid var(--ax-border); }
|
|
5943
|
+
.pp-body h3 { margin: 16px 0 8px; font-size: 13px; }
|
|
5944
|
+
.pp-body p.pp-quiet { margin: 0; color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
5945
|
+
.pp-scroll { overflow-x: auto; }
|
|
5946
|
+
.pp-table { width: 100%; border-collapse: collapse; font-size: var(--ax-fs-sm); }
|
|
5947
|
+
.pp-table th { text-align: left; font-weight: 600; color: var(--ax-text-2); font-size: var(--ax-fs-xs); padding: 4px 12px 4px 0; white-space: nowrap; }
|
|
5948
|
+
.pp-table td { padding: 8px 12px 8px 0; border-top: var(--ax-border-w) solid var(--ax-border); vertical-align: top; }
|
|
5949
|
+
.pp-table td small { display: block; color: var(--ax-text-2); }
|
|
5950
|
+
.pp-state { font-weight: 600; white-space: nowrap; }
|
|
5951
|
+
.pp-state.is-ok { color: var(--ax-green-ink, var(--ax-text)); }
|
|
5952
|
+
.pp-state.is-warn { color: var(--ax-amber-ink); }
|
|
5953
|
+
.pp-state.is-bad { color: var(--ax-red-ink); }
|
|
5954
|
+
.pp-state.is-off { color: var(--ax-text-2); font-weight: 400; }
|
|
5955
|
+
.pp-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
|
|
5956
|
+
.pp-items li { padding-top: 8px; border-top: var(--ax-border-w) solid var(--ax-border); }
|
|
5957
|
+
.pp-items p { margin: 0; }
|
|
5958
|
+
.pp-text { overflow-wrap: anywhere; }
|
|
5959
|
+
.pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
5960
|
+
@media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
|
|
5961
|
+
`,Md=`
|
|
5962
|
+
(function () {
|
|
5963
|
+
var list = document.getElementById('pp-list');
|
|
5964
|
+
var msg = document.getElementById('pp-msg');
|
|
5965
|
+
var none = document.getElementById('pp-none');
|
|
5966
|
+
var open = {}; // person id -> the last detail loaded for it
|
|
5967
|
+
var people = [];
|
|
5968
|
+
var ROLE = { owner: 'Owner', member: 'Member', guest: 'Guest' };
|
|
5969
|
+
var REQUEST = {
|
|
5970
|
+
in_progress: ['In progress', 'ok'], waiting_owner: ['Waiting on you', 'warn'], waiting_other: ['Waiting on another agent', 'warn'],
|
|
5971
|
+
needs_attention: ['Needs attention', 'bad'], done: ['Done', 'off'], declined: ['Declined', 'off'], dropped: ['Dropped', 'off']
|
|
5972
|
+
};
|
|
5973
|
+
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }
|
|
5974
|
+
function headers(json) {
|
|
5975
|
+
var h = { 'X-Requested-With': 'agentx-board' };
|
|
5976
|
+
if (json) h['Content-Type'] = 'application/json';
|
|
5977
|
+
if (window.AX_LOCAL_TOKEN) h['Authorization'] = 'Bearer ' + window.AX_LOCAL_TOKEN;
|
|
5978
|
+
return h;
|
|
5979
|
+
}
|
|
5980
|
+
function say(t, bad) { msg.textContent = t || ''; msg.className = 'pp-msg' + (bad ? ' is-bad' : ''); }
|
|
5981
|
+
function when(v) {
|
|
5982
|
+
var d = new Date(v);
|
|
5983
|
+
return v && !isNaN(d) ? d.toISOString().slice(0, 16).replace('T', ' ') + ' UTC' : '';
|
|
5984
|
+
}
|
|
5985
|
+
function flat(s) { return String(s == null ? '' : s).split(/[ \\t\\r\\n]+/).join(' ').trim().slice(0, 200); }
|
|
5986
|
+
function state(label, tone) { return '<span class="pp-state is-' + tone + '">' + esc(label) + '</span>'; }
|
|
5987
|
+
function deviceState(d) {
|
|
5988
|
+
if (d.state === 'active') return state('Active', 'ok');
|
|
5989
|
+
if (d.state === 'pending' && d.answer === 'yes') return state('Approved', 'ok') + '<small>not opened since</small>';
|
|
5990
|
+
if (d.state === 'pending' && d.answer === 'no') return state('Refused', 'off');
|
|
5991
|
+
if (d.state === 'pending') return state('Waiting for your approval', 'warn');
|
|
5992
|
+
return state('Ended', 'off') + (d.removedReason ? '<small>' + esc(d.removedReason) + '</small>' : '');
|
|
5993
|
+
}
|
|
5994
|
+
function machines(id, devices, listed) {
|
|
5995
|
+
if (!devices.length) return '<p class="pp-quiet">No machine paired.' + (listed ? ' Invite them with <code>agentx people invite ' + esc(id) + '</code>.' : '') + '</p>';
|
|
5996
|
+
var rows = devices.map(function (d) {
|
|
5997
|
+
var end = d.state === 'removed' ? '' : '<button type="button" class="ax-btn ax-btn--danger" data-end="' + esc(d.tokenId) + '" data-person="' + esc(id) + '" data-name="' + esc(d.name) + '">End access</button>';
|
|
5998
|
+
return '<tr><td>' + esc(d.name) + '<small>' + esc(d.tokenId) + '</small></td>' +
|
|
5999
|
+
'<td>' + deviceState(d) + '</td>' +
|
|
6000
|
+
'<td>' + esc(d.address || 'not recorded') + (d.network ? '<small>as ' + esc(d.network) + '</small>' : '') + '</td>' +
|
|
6001
|
+
'<td>' + esc(when(d.createdAt)) + '</td>' +
|
|
6002
|
+
'<td>' + (d.lastSeenAt ? esc(when(d.lastSeenAt)) + (d.lastAddress ? '<small>from ' + esc(d.lastAddress) + '</small>' : '') : 'Not used yet') + '</td>' +
|
|
6003
|
+
'<td>' + end + '</td></tr>';
|
|
6004
|
+
}).join('');
|
|
6005
|
+
return '<div class="pp-scroll"><table class="pp-table"><thead><tr><th scope="col">Machine</th><th scope="col">State</th><th scope="col">Paired from</th><th scope="col">First use</th><th scope="col">Last use</th><th scope="col" aria-label="Action"></th></tr></thead><tbody>' + rows + '</tbody></table></div>';
|
|
6006
|
+
}
|
|
6007
|
+
function requests(items) {
|
|
6008
|
+
if (!items.length) return '<p class="pp-quiet">No tracked request. Requests appear here once request tracking is on (<code>agentx requests settings</code>).</p>';
|
|
6009
|
+
return '<ol class="pp-items">' + items.map(function (r) {
|
|
6010
|
+
var s = REQUEST[r.state] || [r.state, 'off'];
|
|
6011
|
+
return '<li><p class="pp-text">' + esc(flat(r.text)) + '</p><p class="pp-meta">' + state(s[0], s[1]) + '<span>' + esc(r.agentId) + '</span><span>' + esc(r.channel) + '</span><span>' + esc(when(r.createdAt)) + '</span></p></li>';
|
|
6012
|
+
}).join('') + '</ol>';
|
|
6013
|
+
}
|
|
6014
|
+
function runs(items) {
|
|
6015
|
+
if (!items.length) return '<p class="pp-quiet">Nothing recorded yet.</p>';
|
|
6016
|
+
return '<ol class="pp-items">' + items.map(function (r) {
|
|
6017
|
+
var s = r.status === 'ok' ? ['Finished', 'off'] : r.status === 'in-flight' ? ['Running', 'ok'] : [r.status, 'bad'];
|
|
6018
|
+
return '<li><p class="pp-text">' + esc(flat(r.messagePreview)) + '</p><p class="pp-meta">' + state(s[0], s[1]) + '<span>' + esc(r.agentId) + '</span><span>' + esc(r.channel || '') + '</span><span>' + esc(when(r.startedAt)) + '</span></p></li>';
|
|
6019
|
+
}).join('') + '</ol>';
|
|
6020
|
+
}
|
|
6021
|
+
function detail(id) {
|
|
6022
|
+
var d = open[id];
|
|
6023
|
+
if (!d || d === true) return '<p class="pp-quiet" style="padding-top:14px">Loading\u2026</p>';
|
|
6024
|
+
return '<h3>Machines</h3>' + machines(id, d.devices || [], !(d.person && d.person.builtIn)) +
|
|
6025
|
+
'<h3>Requests, newest first</h3>' + (d.database ? requests(d.requests || []) : '<p class="pp-quiet">The database could not be opened. Start the dashboard from the folder that holds agentx.json.</p>') +
|
|
6026
|
+
'<h3>Latest turns they started</h3>' + runs(d.runs || []);
|
|
6027
|
+
}
|
|
6028
|
+
function person(p) {
|
|
6029
|
+
var isOpen = !!open[p.id];
|
|
6030
|
+
var n = p.machines.active + p.machines.pending;
|
|
6031
|
+
var count = (n ? n + (n === 1 ? ' machine' : ' machines') : 'No machine') + (p.machines.pending ? ', <b>' + p.machines.pending + ' waiting for approval</b>' : '');
|
|
6032
|
+
var ids = p.identities.length ? p.identities.map(function (i) { return '<span>' + esc(i) + '</span>'; }).join('')
|
|
6033
|
+
: (p.builtIn ? 'What you do on this machine (voice, app, dashboard) is recorded here.' : 'No channel identity yet');
|
|
6034
|
+
var limit = p.agents.length ? '<span class="ax-badge ax-badge--ghost">Agents: ' + esc(p.agents.join(', ')) + '</span>' : '';
|
|
6035
|
+
return '<li class="pp-person" data-person="' + esc(p.id) + '">' +
|
|
6036
|
+
'<button type="button" class="pp-head" aria-expanded="' + isOpen + '" aria-controls="pp-body-' + esc(p.id) + '" data-open="' + esc(p.id) + '">' +
|
|
6037
|
+
'<span class="pp-caret" aria-hidden="true">▸</span>' +
|
|
6038
|
+
'<span class="pp-name">' + esc(p.name) + '</span>' +
|
|
6039
|
+
'<span class="ax-badge' + (p.role === 'owner' ? ' ax-badge--accent' : '') + '">' + esc(ROLE[p.role] || p.role) + '</span>' +
|
|
6040
|
+
'<span class="pp-id">' + esc(p.id) + '</span>' + limit +
|
|
6041
|
+
'<span class="pp-count">' + count + '</span>' +
|
|
6042
|
+
'<span class="pp-ids">' + ids + '</span>' +
|
|
6043
|
+
'</button>' +
|
|
6044
|
+
'<div class="pp-body" id="pp-body-' + esc(p.id) + '"' + (isOpen ? '' : ' hidden') + '>' + (isOpen ? detail(p.id) : '') + '</div>' +
|
|
6045
|
+
'</li>';
|
|
6046
|
+
}
|
|
6047
|
+
function draw() {
|
|
6048
|
+
// Redrawing would drop the keyboard focus: put it back on the same control.
|
|
6049
|
+
var a = document.activeElement, key = a && list.contains(a) ? (a.getAttribute('data-open') ? 'open:' + a.getAttribute('data-open') : a.getAttribute('data-end') ? 'end:' + a.getAttribute('data-end') : '') : '';
|
|
6050
|
+
list.innerHTML = people.length ? people.map(person).join('') : '<li class="pp-empty">Nobody is listed.</li>';
|
|
6051
|
+
if (key) {
|
|
6052
|
+
var again = list.querySelector(key.indexOf('open:') === 0 ? '[data-open="' + key.slice(5) + '"]' : '[data-end="' + key.slice(4) + '"]') || list.querySelector('[data-open]');
|
|
6053
|
+
if (again) again.focus();
|
|
6054
|
+
}
|
|
6055
|
+
}
|
|
6056
|
+
function get(path) {
|
|
6057
|
+
return fetch(path, { credentials: 'same-origin', cache: 'no-store', headers: headers(false) }).then(function (r) {
|
|
6058
|
+
return r.json().then(function (d) { if (!r.ok) throw new Error(d.error || ('HTTP ' + r.status)); return d; });
|
|
6059
|
+
});
|
|
6060
|
+
}
|
|
6061
|
+
function loadOne(id) {
|
|
6062
|
+
return get('/api/admin/people/' + encodeURIComponent(id)).then(function (d) { if (open[id]) { open[id] = d; draw(); } })
|
|
6063
|
+
.catch(function (e) { say('Could not read ' + id + ': ' + e.message, true); });
|
|
6064
|
+
}
|
|
6065
|
+
function load() {
|
|
6066
|
+
return get('/api/admin/people').then(function (d) {
|
|
6067
|
+
people = d.people || [];
|
|
6068
|
+
none.hidden = d.paired > 0;
|
|
6069
|
+
Object.keys(open).forEach(function (id) { if (!people.some(function (p) { return p.id === id; })) delete open[id]; });
|
|
6070
|
+
draw();
|
|
6071
|
+
Object.keys(open).forEach(loadOne);
|
|
6072
|
+
}).catch(function (e) { say('Could not read the people list: ' + e.message, true); });
|
|
6073
|
+
}
|
|
6074
|
+
list.addEventListener('click', function (ev) {
|
|
6075
|
+
var end = ev.target.closest('button[data-end]');
|
|
6076
|
+
if (end) {
|
|
6077
|
+
var id = end.getAttribute('data-person'), token = end.getAttribute('data-end'), name = end.getAttribute('data-name');
|
|
6078
|
+
if (!confirm('End access for "' + name + '"? This machine stops at once. To use it again, the person needs a new invite.')) return;
|
|
6079
|
+
end.disabled = true;
|
|
6080
|
+
fetch('/api/admin/people/' + encodeURIComponent(id) + '/devices/' + encodeURIComponent(token) + '/end', { method: 'POST', credentials: 'same-origin', headers: headers(true), body: '{}' })
|
|
6081
|
+
.then(function (r) { return r.json().then(function (d) { if (!r.ok) throw new Error(d.error || ('HTTP ' + r.status)); return d; }); })
|
|
6082
|
+
.then(function () { say('Access ended for "' + name + '".', false); return load(); })
|
|
6083
|
+
// The button is gone with the machine's access: keep the keyboard on this person.
|
|
6084
|
+
.then(function () { var h = list.querySelector('[data-open="' + id + '"]'); if (h) h.focus(); })
|
|
6085
|
+
.catch(function (e) { say('Could not end access: ' + e.message, true); end.disabled = false; });
|
|
6086
|
+
return;
|
|
6087
|
+
}
|
|
6088
|
+
var head = ev.target.closest('button[data-open]');
|
|
6089
|
+
if (!head) return;
|
|
6090
|
+
var pid = head.getAttribute('data-open');
|
|
6091
|
+
if (open[pid]) { delete open[pid]; draw(); return; }
|
|
6092
|
+
open[pid] = true;
|
|
6093
|
+
draw();
|
|
6094
|
+
loadOne(pid);
|
|
6095
|
+
});
|
|
6096
|
+
load();
|
|
6097
|
+
setInterval(load, 30000);
|
|
6098
|
+
})();
|
|
6099
|
+
`;var ba="/api/admin/people";function Ld(t,e){let a=fr(t,e);return a?{...e,answer:a}:e}function Rd(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function $d(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&Rd(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:cn,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Pd=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function _o(t,e,a,n){if(a!=="/people"&&a!==ba&&!a.startsWith(`${ba}/`))return!1;let r=(t.method||"GET").toUpperCase();if((t.url||"").split(/[?#]/)[0]!==a)return pe(e,404,{error:"not found"}),!0;if(a==="/people")return r!=="GET"?(pe(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(ko({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return pe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(p=>Ld(n.root,p)),s=()=>$d(n.people(),o());if(r==="GET"&&a===ba){let c=s();return pe(e,200,{people:c,paired:c.reduce((p,u)=>p+u.machines.active+u.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(h=>h.id===i[1]);if(!c)return pe(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),u=[],f=[];try{p&&(u=pr(p,c.id))}catch{}try{p&&(f=Et(p,c.id,20))}catch{}return pe(e,200,{person:c,devices:o(c.id).sort(Pd),requests:u,runs:f,database:!!p}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,c,p]=l,u=n.members.byToken(p);if(!u||u.personId!==c)return pe(e,404,{error:"no such machine for this person"}),!0;if(u.state==="removed")return pe(e,409,{error:"this machine's access has already ended"}),!0;let f=gr({tokens:n.tokens??new F,members:n.members,now:n.now},p,"removed by the owner (dashboard)");return pe(e,200,{ok:!0,device:f}),!0}return pe(e,404,{error:"not found"}),!0}import{resolve as Nd}from"path";import{existsSync as Dd}from"fs";import Hd from"better-sqlite3";function So(t={}){let e=`<div class="ax-obs">
|
|
5908
6100
|
<header class="ax-obs__head">
|
|
5909
6101
|
<h1>Health</h1>
|
|
5910
6102
|
<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>
|
|
@@ -6026,7 +6218,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6026
6218
|
</div>
|
|
6027
6219
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
6028
6220
|
</section>
|
|
6029
|
-
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6221
|
+
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:jd,scripts:`<script>${Od}</script>`})}var jd=`
|
|
6030
6222
|
.ax-obs { padding: 16px 24px; }
|
|
6031
6223
|
.ax-obs__head { margin-bottom: 16px; }
|
|
6032
6224
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -6143,7 +6335,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6143
6335
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
6144
6336
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
6145
6337
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
6146
|
-
`,
|
|
6338
|
+
`,Od=`
|
|
6147
6339
|
(function(){
|
|
6148
6340
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
6149
6341
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -6527,23 +6719,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6527
6719
|
|
|
6528
6720
|
load(current);
|
|
6529
6721
|
})();
|
|
6530
|
-
`;var
|
|
6722
|
+
`;var Ao={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 Co(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function ya(t){let e=Ao[Co(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 Bd(){let t=Nd(process.cwd(),".agentx/db.sqlite");if(!Dd(t))return null;try{let e=new Hd(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Io(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(So({peers:a}))}function zd(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 Mo(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Bd();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=zd(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6531
6723
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
6532
6724
|
FROM route_traces
|
|
6533
6725
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6534
6726
|
ORDER BY at DESC LIMIT @limit
|
|
6535
|
-
`,p=r.db.prepare(c).all(l);return
|
|
6727
|
+
`,p=r.db.prepare(c).all(l);return fe(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6536
6728
|
SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
|
|
6537
6729
|
FROM rotations
|
|
6538
6730
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6539
6731
|
ORDER BY rotated_at DESC LIMIT @limit
|
|
6540
|
-
`,p=r.db.prepare(c).all(l);return
|
|
6732
|
+
`,p=r.db.prepare(c).all(l);return fe(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6541
6733
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
6542
6734
|
FROM task_history
|
|
6543
6735
|
WHERE ${i.join(" AND ")}
|
|
6544
6736
|
ORDER BY started_at DESC LIMIT @limit
|
|
6545
|
-
`,u=r.db.prepare(c).all(l).map(f=>({...f,plain:
|
|
6546
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6737
|
+
`,u=r.db.prepare(c).all(l).map(f=>({...f,plain:Lo(f.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,qd(r.db)),!0;if(n==="activity")return fe(e,200,Fd(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Eo(i.searchParams.get("range"));return fe(e,200,To(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Eo(i.searchParams.get("range")),c=To(r.db,l),p=Ud(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 Lo(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(`
|
|
6738
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function qd(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=y=>p.length?p[Math.min(p.length-1,Math.floor(p.length*y))].duration_ms:0,f=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((y,I)=>y+ya(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((y,I)=>y+ya(I),0),g=t.prepare(`
|
|
6547
6739
|
SELECT agent_id,
|
|
6548
6740
|
COUNT(*) AS tasks,
|
|
6549
6741
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -6566,7 +6758,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6566
6758
|
FROM task_history
|
|
6567
6759
|
WHERE status='error' AND started_at >= ?
|
|
6568
6760
|
ORDER BY started_at DESC LIMIT 5
|
|
6569
|
-
`).all(o).map(y=>({...y,plain:
|
|
6761
|
+
`).all(o).map(y=>({...y,plain:Lo(y.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:f,p95DurationMs:h,spendToday:_,spendDelta:_-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:T}}function Fd(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(`
|
|
6570
6762
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
6571
6763
|
COUNT(*) AS tasks,
|
|
6572
6764
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -6593,7 +6785,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6593
6785
|
WHERE started_at >= @since
|
|
6594
6786
|
GROUP BY agent_id
|
|
6595
6787
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
6596
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
6788
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Eo(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 To(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
6597
6789
|
SELECT day, agent_id, model,
|
|
6598
6790
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
6599
6791
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -6601,20 +6793,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6601
6793
|
FROM usage_daily
|
|
6602
6794
|
${a}
|
|
6603
6795
|
ORDER BY day
|
|
6604
|
-
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,u=0,f=0,h=0,k=0,_=0,
|
|
6796
|
+
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,u=0,f=0,h=0,k=0,_=0,S=0,g={},d={};for(let E of n){let $=ya(E),L=Co(E.model),j=Ao[L],W=(E.tier2_input_tokens||0)/1e6*j.input*.5+(E.tier2_output_tokens||0)/1e6*j.output*.5+(E.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,q=(E.input_tokens||0)+(E.tier2_input_tokens||0),G=(E.output_tokens||0)+(E.tier2_output_tokens||0),ie=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),je=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=$,E.day>=s&&(p+=$,k+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,_+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(f+=W),E.day>=s&&(h+=W);let Z=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=E.tasks||0,Z.input+=q,Z.output+=G,Z.cacheRead+=ie,Z.cacheCreate+=je,Z.cost+=$,Z.tier2+=W;let B=Z.agents[E.agent_id]||(Z.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});B.tasks+=E.tasks||0,B.cost+=$,B.tier2+=W,B.input+=q,B.output+=G,B.cacheRead+=ie,B.cacheCreate+=je,E.model&&(B.model=E.model);let O=d[E.agent_id]||(d[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});O.tasks+=E.tasks||0,O.cost+=$,O.tier2+=W,O.input+=q,O.output+=G,O.cacheRead+=ie,O.cacheCreate+=je,E.model&&(O.model=E.model)}let m=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,v=0,w=0,T=0,y=0,I=0;for(let E of m)x+=E.tasks,v+=E.input,w+=E.output,T+=E.cacheRead,y+=E.cacheCreate,I+=E.cost;let C=Object.entries(d).map(([E,$])=>({agent_id:E,...$,tokens:$.input+$.output+$.cacheRead+$.cacheCreate})).sort((E,$)=>$.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:h,tier2PctToday:l>0?f/l:0,spendRange:I,avgDailyRange:m.length?I/m.length:0,tasksRange:x,tokensRange:v+w+T+y,cacheHitRange:T+v>0?T/(T+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(k-_)/_:0},days:m,perAgent:C}}function Ud(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+`
|
|
6605
6797
|
`+a.join(`
|
|
6606
6798
|
`)+`
|
|
6607
|
-
`}import{resolve as
|
|
6799
|
+
`}import{resolve as Wd}from"path";import{existsSync as Gd}from"fs";import Xd from"better-sqlite3";function Kd(){let t=Wd(process.cwd(),".agentx/intent/ledger.sqlite");if(!Gd(t))return null;try{let e=new Xd(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ro>6e4&&(Ro=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Ro=0;function Ae(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Jd(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 $o(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Kd();if(!r)return Ae(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=Jd(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
|
|
6608
6800
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
6609
6801
|
LEFT JOIN intent_resolutions r
|
|
6610
6802
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6611
6803
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
6612
|
-
`).get().n;return
|
|
6804
|
+
`).get().n;return Ae(e,200,{since:s??null,eventsBySource:h,totalDecisions:k,decisionsByOutcome:_,totalDivergences:S,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let h=`
|
|
6613
6805
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
6614
6806
|
FROM intent_events
|
|
6615
6807
|
${u.length?"WHERE "+u.join(" AND "):""}
|
|
6616
6808
|
ORDER BY ts DESC LIMIT @limit
|
|
6617
|
-
`;return
|
|
6809
|
+
`;return Ae(e,200,{rows:r.db.prepare(h).all(f)}),!0}if(n==="divergences"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i);let h=`
|
|
6618
6810
|
SELECT ts, source, decided_by,
|
|
6619
6811
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
6620
6812
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
@@ -6622,7 +6814,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6622
6814
|
FROM intent_divergences
|
|
6623
6815
|
${u.length?"WHERE "+u.join(" AND "):""}
|
|
6624
6816
|
ORDER BY ts DESC LIMIT @limit
|
|
6625
|
-
`;return
|
|
6817
|
+
`;return Ae(e,200,{rows:r.db.prepare(h).all(f)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],f={limit:p};i&&(u.push("e.source = @source"),f.source=i);let h=`
|
|
6626
6818
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
6627
6819
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
6628
6820
|
FROM intent_decisions d
|
|
@@ -6631,7 +6823,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6631
6823
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6632
6824
|
WHERE ${u.join(" AND ")}
|
|
6633
6825
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
6634
|
-
`;return
|
|
6826
|
+
`;return Ae(e,200,{rows:r.db.prepare(h).all(f)}),!0}return Ae(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ae(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Po(t={}){return M({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
6635
6827
|
<header class="ax-led__head">
|
|
6636
6828
|
<h1>Intent ledger</h1>
|
|
6637
6829
|
<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>
|
|
@@ -6836,7 +7028,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6836
7028
|
}
|
|
6837
7029
|
load();
|
|
6838
7030
|
})();
|
|
6839
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7031
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function jo(t={}){return M({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
6840
7032
|
<header class="ax-cost__head">
|
|
6841
7033
|
<div>
|
|
6842
7034
|
<h1>Cost</h1>
|
|
@@ -7409,7 +7601,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7409
7601
|
load();
|
|
7410
7602
|
setInterval(load, 30000);
|
|
7411
7603
|
})();
|
|
7412
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7604
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Oo(t={}){let e=`<div class="ax-pj__root">
|
|
7413
7605
|
<aside class="ax-pj__list">
|
|
7414
7606
|
<header>
|
|
7415
7607
|
<h2>Projects</h2>
|
|
@@ -7436,7 +7628,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7436
7628
|
</header>
|
|
7437
7629
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
7438
7630
|
</section>
|
|
7439
|
-
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
7631
|
+
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Vd,scripts:`<script>${Yd}</script>`})}var Vd=`
|
|
7440
7632
|
.ax-pj__root {
|
|
7441
7633
|
display: grid;
|
|
7442
7634
|
grid-template-columns: 360px 1fr;
|
|
@@ -7623,7 +7815,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7623
7815
|
}
|
|
7624
7816
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
7625
7817
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
7626
|
-
`,
|
|
7818
|
+
`,Yd=`
|
|
7627
7819
|
(function(){
|
|
7628
7820
|
const $ = (sel) => document.querySelector(sel);
|
|
7629
7821
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -8273,22 +8465,22 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8273
8465
|
load();
|
|
8274
8466
|
});
|
|
8275
8467
|
})();
|
|
8276
|
-
`;import{resolve as ka,join as Gd}from"path";import{existsSync as _a,readdirSync as Xd,readFileSync as Kd}from"fs";import Jd from"better-sqlite3";var Io=String.raw`[\w.-]+(?:/[\w.-]+)+`,Ld=new RegExp(`^(?:chat:)?(${Io}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Rd=new RegExp(`^\\[(?:GitLab|GitHub) (${Io}) `);function Co(t){if(!t)return null;let e=t.match(Ld);return e?e[1]:null}function va(t){if(!t)return null;let e=t.trimStart().match(Rd);return e?e[1]:null}function $t(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Co(typeof n?.chatId=="string"?n.chatId:null)??Co(e)??va(a)}function $d(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Pt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Pd=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,jd=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Od=t=>/^issue/i.test(t)?"issue":"mr";function Nd(t){let e=t.subject.match(Pd)??t.inputPreview.trimStart().match(jd);return e?{kind:Od(e[1]),n:Number(e[2])}:null}function Dd(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 Mo(t){if(!$d(t.projectId))return[];let e=Nd(t);return e?[e]:Dd(t.inputPreview)}var Hd=6e4,Bd=5*6e4,zd=40,Lo=6,Ro=new Map;function $o(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 Mo(n)){let s=Pt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=zd)return[...e.values()]}}return[...e.values()]}async function Po(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Pt(s.project,s.ref),l=Ro.get(i);l&&n-l.at<(s.github?Bd:Hd)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Lo)await Promise.all(o.slice(s,s+Lo).map(async i=>{let l=Pt(i.project,i.ref),c=null;try{c=i.github?await Fd(i,e,a):await qd(i,e,a)}catch{}Ro.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function jo(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 qd(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 jo(`${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 Fd(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 jo(`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}an();var ba=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Oo(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=nt(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=ba(o.from,80);if(s){a.callback={from:s,status:ba(o.status,20)??"done"};let i=ba(o.peer,80);i&&(a.callback.peer=i)}}return a}an();al();var No={kind:"agentx",id:"agentx",name:"AgentX"},ya={kind:"person",id:"unknown",name:"Unknown"},Ud=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Do=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Te=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Wd(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Te(o?.id)??(e==="whatsapp"?Te(n?.from):void 0),i=Te(o?.username)??Te(o?.login);return s||i?{id:s,username:i,name:Te(o?.name)}:null}function Ho(t){let e=s=>({kind:"person",id:`person:${s}`,name:on(t.people,s)}),a=(s,i)=>i||Ud.has(s)?No:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Te(n.person)??ln(t.people,s)?.id;if(i)return e(i);let l=nt(s),c=l?.channel??t.channel;if(tn(s)==="human")return Do(s?.senderUsername)?a(c,!1):ya;let p=!!Te(n.senderAgentId)||Jt(l?l.sender:s?.sender);return c==="desktop"&&!p?ya:a(c,p)}let r=Wd(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=sn(t.people,t.channel,r);return o?e(o.id):Jt(r.name)?No:en.has(t.channel)&&!Do(r.username)?ya:a(t.channel,!1)}function Ea(){let t=ka(process.cwd(),".agentx/intent/ledger.sqlite");if(!_a(t))return null;try{let e=new Jd(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Bo>6e4&&(Bo=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Bo=0;function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Ae={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 Vd(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Ae)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Ae)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Ae)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 Ae)return s}return"workflow"}return t}function Fo(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 Yd(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 Uo(t,e,a){return bn(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 Qd(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:J(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!wa(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!wa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:ep(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&&!wa(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=zo(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:zo(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:J(o),kind:"whatsapp"}}}return null}var Zd={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function ep(t,e){let a=Zd[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function zo(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function wa(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function Wo(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}
|
|
8468
|
+
`;import{resolve as Ea,join as mp}from"path";import{existsSync as Ta,readdirSync as fp,readFileSync as hp}from"fs";import gp from"better-sqlite3";var Do=String.raw`[\w.-]+(?:/[\w.-]+)+`,Qd=new RegExp(`^(?:chat:)?(${Do}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Zd=new RegExp(`^\\[(?:GitLab|GitHub) (${Do}) `);function No(t){if(!t)return null;let e=t.match(Qd);return e?e[1]:null}function wa(t){if(!t)return null;let e=t.trimStart().match(Zd);return e?e[1]:null}function jt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():No(typeof n?.chatId=="string"?n.chatId:null)??No(e)??wa(a)}function ep(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Ot(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var tp=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,ap=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,np=t=>/^issue/i.test(t)?"issue":"mr";function rp(t){let e=t.subject.match(tp)??t.inputPreview.trimStart().match(ap);return e?{kind:np(e[1]),n:Number(e[2])}:null}function op(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 Ho(t){if(!ep(t.projectId))return[];let e=rp(t);return e?[e]:op(t.inputPreview)}var sp=6e4,ip=5*6e4,lp=40,Bo=6,zo=new Map;function qo(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of Ho(n)){let s=Ot(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=lp)return[...e.values()]}}return[...e.values()]}async function Fo(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Ot(s.project,s.ref),l=zo.get(i);l&&n-l.at<(s.github?ip:sp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Bo)await Promise.all(o.slice(s,s+Bo).map(async i=>{let l=Ot(i.project,i.ref),c=null;try{c=i.github?await dp(i,e,a):await cp(i,e,a)}catch{}zo.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Uo(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 cp(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 Uo(`${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 dp(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 Uo(`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}on();var ka=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Wo(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=ot(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=ka(o.from,80);if(s){a.callback={from:s,status:ka(o.status,20)??"done"};let i=ka(o.peer,80);i&&(a.callback.peer=i)}}return a}on();mn();var Go={kind:"agentx",id:"agentx",name:"AgentX"},_a={kind:"person",id:"unknown",name:"Unknown"},pp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Xo=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ce=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function up(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ce(o?.id)??(e==="whatsapp"?Ce(n?.from):void 0),i=Ce(o?.username)??Ce(o?.login);return s||i?{id:s,username:i,name:Ce(o?.name)}:null}function Ko(t){let e=s=>({kind:"person",id:`person:${s}`,name:dn(t.people,s)}),a=(s,i)=>i||pp.has(s)?Go:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ce(n.person)??un(t.people,s)?.id;if(i)return e(i);let l=ot(s),c=l?.channel??t.channel;if(rn(s)==="human")return Xo(s?.senderUsername)?a(c,!1):_a;let p=!!Ce(n.senderAgentId)||Yt(l?l.sender:s?.sender);return c==="desktop"&&!p?_a:a(c,p)}let r=up(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=pn(t.people,t.channel,r);return o?e(o.id):Yt(r.name)?Go:nn.has(t.channel)&&!Xo(r.username)?_a:a(t.channel,!1)}function Aa(){let t=Ea(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ta(t))return null;try{let e=new gp(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Jo>6e4&&(Jo=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Jo=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Ie={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 xp(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Ie)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Ie)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Ie)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 Ie)return s}return"workflow"}return t}function Qo(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 vp(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 Zo(t,e,a){return Sn(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 bp(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:J(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!Sa(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Sa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:wp(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!Sa(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Vo(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:Vo(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:J(o),kind:"whatsapp"}}}return null}var yp={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function wp(t,e){let a=yp[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Vo(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Sa(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function es(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}
|
|
8277
8469
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
8278
|
-
${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
|
|
8470
|
+
${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function kp(t){if(!t)return"(no subject)";let e;return(e=t.match(/^merge_request:(\d+)(?::note:(\d+))?/))?e[2]?`MR #${e[1]} \xB7 note ${e[2]}`:`MR #${e[1]}`:(e=t.match(/^issue:(\d+)(?::note:(\d+))?/))?e[2]?`Issue #${e[1]} \xB7 note ${e[2]}`:`Issue #${e[1]}`:(e=t.match(/^chat:(.+?):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,40)}`:(e=t.match(/^mesh:agent:(.+)$/))?`\u2192 ${e[1]}`:(e=t.match(/^workflow:([^:]+):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,30)}`:t.length>60?t.slice(0,57)+"\u2026":t}function ts(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
8279
8471
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
8280
8472
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
8281
|
-
`).all(r),s=new Map,i=new Map;if(o.length>0){let y=o.map(L=>L.id),I=y.map((L,j)=>`@id${j}`).join(","),C=Object.fromEntries(y.map((L,j)=>[`id${j}`,L])),
|
|
8473
|
+
`).all(r),s=new Map,i=new Map;if(o.length>0){let y=o.map(L=>L.id),I=y.map((L,j)=>`@id${j}`).join(","),C=Object.fromEntries(y.map((L,j)=>[`id${j}`,L])),E=t.prepare(`
|
|
8282
8474
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
8283
8475
|
FROM intent_decisions WHERE event_id IN (${I}) ORDER BY decided_at ASC
|
|
8284
|
-
`).all(C);for(let L of
|
|
8476
|
+
`).all(C);for(let L of E)s.has(L.event_id)||s.set(L.event_id,[]),s.get(L.event_id).push(L);let $=t.prepare(`
|
|
8285
8477
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
8286
8478
|
FROM intent_resolutions WHERE decision_event_id IN (${I})
|
|
8287
|
-
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],_=
|
|
8479
|
+
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],_=aa(e?.business??{}),S=e?.people??[];for(let y of o){let I=null;try{I=JSON.parse(y.raw_json)}catch{}let C=Zo(y.source,I,k),E=es(y.source,I),$=Wo(I),L=y.project??jt(I,y.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=dt(L,h),W=L);let q=xp(y.source,y.intent||"",I),G=Ie[q]||{label:q,color:"#6b7280"};p.has(q)||p.set(q,{id:q,label:G.label,color:G.color});let ie=Ko({source:y.source,channel:q,raw:I,people:S,channelLabel:O=>Ie[O]?.label??O}),je="__system",Z,B=bp(y.source,y.intent||"",I);if(B){je=B.id,Z=B.kind;let O=C?.displayName||B.name;(!u.has(B.id)||C?.displayName)&&u.set(B.id,{id:B.id,name:O,avatar:J(O),kind:B.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let O of s.get(y.id)??[]){if(O.outcome!=="dispatched"||!O.agent_id)continue;let pl=`${y.id}|${O.decided_by}`,nt=i.get(pl),Za=O.decided_at,en=nt?.resolved_at??null,Jt=en===null,ul=nt?.duration_ms??(Jt?n-Za:0),ml=Jt?"active":nt?.status==="error"||nt?.status==="fail"?"error":"completed",ee,Ue;if(j)ee=j,Ue=W;else{let Vt=_.get(O.agent_id);Vt?(ee=Vt,Ue=`${Vt}/_${y.source}`):(ee="unmapped",Ue=`unmapped/_${y.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:Qo(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ue),f.push({id:`${y.id}|${O.decided_by}`,agentId:O.agent_id,clientId:ee,projectId:Ue,channelId:q,initiatorId:je,initiatorKind:Z,subject:kp(y.subject),intent:y.intent||"",startedAt:Za,resolvedAt:en,duration:ul,active:Jt,outcome:ml,tokens:0,inputPreview:E,system:vp(O.agent_id,e),...$,starter:ie})}}let g=[...l.values()].map(y=>({...y,projects:[...c.get(y.id)||[]].sort()})).sort((y,I)=>y.id.localeCompare(I.id)),d=[],m=new Set;if(e){let y=e.business??{},I=C=>{let E=y.orgChart?.[C]?.role,$=E?y.roles?.[E]?.title:void 0;return typeof $=="string"&&$.trim()?$.trim():void 0};for(let[C,E]of Object.entries(e.agents||{})){let $={id:C,name:E.name||C,tier:E.tier==="claude-code"?"lead":"worker",model:E.model||"",role:E.systemPrompt?E.systemPrompt.split(/[.\n]/)[0].slice(0,60):E.tier||"",title:I(C)};d.push($),m.add(C)}}for(let y of f)m.has(y.agentId)||(d.push({id:y.agentId,name:y.agentId,tier:"worker",model:"",role:""}),m.add(y.agentId));d.sort((y,I)=>y.id.localeCompare(I.id));let x=[],v=new Set;for(let[y,I]of Object.entries(Ie))x.push({id:y,label:I.label,color:I.color}),v.add(y);for(let y of p.values())v.has(y.id)||x.push(y);let w=[...u.values()];w.find(y=>y.id==="__system")||w.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:d,channels:x,initiators:w,dispatches:f,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function Ca(t){let e=Aa();if(!e)return null;try{return ts(e.db,ns(),t)}finally{e.close()}}function as(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:h})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=_p(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Qo(f.clientId),projects:[]}),f.projectId!==u.projectId){let h=e.get(f.clientId);h.projects.includes(f.projectId)||e.set(f.clientId,{...h,projects:[...h.projects,f.projectId].sort()})}o.push({...f,nodeId:c,id:`${c}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function _p(t){if(t.clientId!=="unmapped")return t;let e=wa(t.inputPreview);if(!e)return t;let a=ge?.business?.projects??[];return{...t,projectId:e,clientId:dt(e,a)}}async function Nt(t){let e=ge?.channels?.gitlab,a=await Fo(qo(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ge=null;function ns(){return ge&&{...ge,people:Ge(ge.people)}}function rs(t){ge=t}async function os(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=ss(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await Nt(ts(n.db,ns(),o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Sp=5e3;async function Ia(t,e,a,n=Ca){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
|
|
8288
8480
|
|
|
8289
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
8481
|
+
`);let r=new URL(t.url||"/","http://_"),o=ss(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
|
|
8290
8482
|
|
|
8291
|
-
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await
|
|
8483
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await Nt(p);if(s)break;u?(e.write(`event: snapshot
|
|
8292
8484
|
`),e.write(`data: ${JSON.stringify(u)}
|
|
8293
8485
|
|
|
8294
8486
|
`)):e.write(`event: error
|
|
@@ -8297,7 +8489,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
8297
8489
|
`)}catch(p){e.write(`event: error
|
|
8298
8490
|
data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
8299
8491
|
|
|
8300
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
8492
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<Sp;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function ss(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ep(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)?Yo(s,e,a):null}return Yo(r,e,a)}function Yo(t,e,a){let n=null,r=1/0;for(let o of fp(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(hp(mp(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 is(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),f=null;try{f=JSON.parse(c.raw_json)}catch{}let h=es(c.source,f),k=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||h,_=null,S=null;if(p.agent_id){let w=Ep(p.agent_id,p.decided_at);if(w){typeof w.responseText=="string"&&(_=w.responseText);let T=w.transcript;Array.isArray(T)&&(S=T.length)}}let g=ge?.business?.projects??[],d=ge?.business?.contactMap??[],m=aa(ge?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Zo(c.source,f,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||jt(f,c.subject,h)){let w=c.project||jt(f,c.subject,h);x={client:dt(w,g),project:w,via:c.project?`project namespace prefix (${w})`:`forge path in chat id / message (${w})`}}else if(p.agent_id){let w=m.get(p.agent_id);w&&(x={client:w,project:`${w}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${w})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:k,response:_,transcriptLen:S,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){he(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Ip,readFileSync as Mp}from"fs";import{resolve as cs}from"path";st();function ls(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=Tp.replace(/__AGENT_ID__/g,N(e));return M({title:`AgentX \xB7 ${N(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${N(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Ap,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>${Cp}</script>`})}var Tp=`
|
|
8301
8493
|
<!-- Breadcrumb -->
|
|
8302
8494
|
<div class="ax-crumb">
|
|
8303
8495
|
<a href="/admin">Settings</a>
|
|
@@ -8886,7 +9078,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
|
8886
9078
|
</div>
|
|
8887
9079
|
</div>
|
|
8888
9080
|
</div>
|
|
8889
|
-
`,
|
|
9081
|
+
`,Ap=`
|
|
8890
9082
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
8891
9083
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
8892
9084
|
* primitives live in components.css.ts. */
|
|
@@ -9005,7 +9197,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
9005
9197
|
|
|
9006
9198
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
9007
9199
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
9008
|
-
`,
|
|
9200
|
+
`,Cp=`
|
|
9009
9201
|
const $ = (id) => document.getElementById(id);
|
|
9010
9202
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
9011
9203
|
|
|
@@ -9861,15 +10053,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
9861
10053
|
/* ===== Boot ===== */
|
|
9862
10054
|
initOptsToggles();
|
|
9863
10055
|
loadAgent();
|
|
9864
|
-
`;function
|
|
9865
|
-
`);return
|
|
9866
|
-
`);return
|
|
10056
|
+
`;function ds(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ls({agentId:a,peers:n,localToken:r}))}async function ps(t,e,a){try{let n=t.method==="GET"?void 0:await Qp(t),r=new URL(t.url||"/","http://localhost"),o=Object.fromEntries(r.searchParams),s=a.match(/^\/api\/admin\/agent\/([a-z0-9][a-z0-9_-]*)(?:\/(.+))?$/);if(!s){Dt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Ve(i),"PATCH ":()=>Lp(i,n),"PATCH capability":()=>Pp(i,n),"POST mcp":()=>Rp(i,n),"DELETE mcp":()=>$p(i,n),"GET identity":()=>jp(i),"GET identity/file":()=>Op(i,String(o.path||"")),"PUT identity/file":()=>Np(i,n),"GET skills":()=>Dp(i),"POST skills":()=>Hp(i,n),"DELETE skills":()=>Bp(i,n),"GET skills/tree":()=>zp(i,String(o.slug||"")),"GET skills/file":()=>qp(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Fp(i,n),"GET skills/deps":()=>Up(i,String(o.slug||"")),"POST skills/install":()=>Wp(i,n,t),"POST skills/deps":()=>Gp(i,n,t),"GET channels":()=>Xp(i),"GET activity":()=>Kp(i,t),"GET handovers":()=>Jp(i),"POST handovers":()=>Vp(i,n),"DELETE handovers":()=>Yp(n)}[c];if(!u){Dt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();Dt(e,200,f)}catch(n){Dt(e,400,{error:n?.message||"agent op failed"})}}function us(){let t=cs(process.cwd(),"agentx.json");return Ip(t)?JSON.parse(Mp(t,"utf-8")):null}function V(t){let e=us();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 Ve(t){let{def:e,cfg:a}=V(t),n=e.workspace?Ne(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 Lp(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:Ve(t)}}function Rp(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:Ve(t)}}function $p(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:Ve(t)}}function Pp(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:Ve(t)}}function jp(t){let{def:e}=V(t);return Ne(e.workspace)}function Op(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return xt(a.workspace,e)}function Np(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return vt(n.workspace,a,String(e?.content??""))}function Dp(t){let{def:e}=V(t),a=Ne(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Hp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return bt(n.workspace,a,{title:e?.title,content:e?.content})}function Bp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return yt(n.workspace,a)}function zp(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Xn(a.workspace,e),r=wt(a.workspace,e);return{slug:e,tree:n,deps:r}}function qp(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Kn(n.workspace,e,a)}function Fp(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return Jn(r.workspace,a,n,String(e?.content??""))}function Up(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return wt(a.workspace,e)}async function Wp(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=ms(e?.worker),{def:o}=V(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
|
|
10057
|
+
`);return fs(a,r,s,`install-${n}:${Date.now()}`)}async function Gp(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=ms(e?.worker),{def:o}=V(t),s=wt(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=cs(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(`
|
|
10058
|
+
`);return fs(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function ms(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function fs(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Xp(t){let e=us(),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 Kp(t,e){try{let n=(X().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function Ma(){return new hn}function Jp(t){let e=Ma(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Vp(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=Ma().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 Yp(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:Ma().remove(e,a,n)?"Released":"No active handover for that chat"}}function Dt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Qp(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 Me={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var hs=[{term:"Agent",definition:'An AI worker with its own role, instructions, and channels it responds on. Think of each agent as a job title \u2014 "support", "devops", "sales".'},{term:"Trigger word",alias:"mention",definition:"A word that activates an agent. When the trigger appears in a message (e.g. @support), AgentX routes the message to that agent."},{term:"Channel",definition:"Where messages come from \u2014 Telegram, WhatsApp, Discord, GitLab comments, a scheduled cron, or an HTTP webhook."},{term:"AI engine",alias:"tier",definition:"Which backend answers: Claude Code, Codex CLI, Anthropic Agent SDK, or AgentX's provider-agnostic orchestrator."},{term:"Agent folder",alias:"workspace",definition:"The directory on disk where the agent lives. It holds the agent's personality (CLAUDE.md), its knowledge (wiki), and the tools it can use."},{term:"Team network",alias:"mesh",definition:'When you run AgentX on more than one machine, the machines find each other and share work. Each machine is a "node"; together they are your team network.'},{term:"Status check-in",alias:"heartbeat",definition:"A lightweight ping between machines so each one knows the others are alive and responsive."},{term:"Board",definition:"A Kanban view of tasks (issues, tickets) pulled from GitLab. Drag cards between columns to move work forward \u2014 the labels update upstream automatically."},{term:"Task",definition:"A single conversation or job an agent handles, from trigger message to final reply. Every task is logged and replayable."},{term:"Schedule",alias:"cron",definition:'A recurring job \u2014 e.g. "every Monday at 9am" \u2014 that nudges an agent without a human trigger.'},{term:"Status label",alias:"scopedLabel",definition:"A GitLab label that moves an issue between Kanban columns (e.g. Status::Doing). Labels are mutually exclusive by prefix."}];function La(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Me)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
9867
10059
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
9868
10060
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
9869
10061
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
9870
10062
|
<main id="grid" class="ax-live__body"></main>
|
|
9871
10063
|
</div>
|
|
9872
|
-
`;return M({title:`${
|
|
10064
|
+
`;return M({title:`${Me.brand} \xB7 ${Me.subtitle}`,activeTab:"live",subtitle:Me.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Zp,scripts:e+`<script>${eu}</script>`,headExtras:`<script>
|
|
9873
10065
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
9874
10066
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
9875
10067
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -9880,7 +10072,7 @@ loadAgent();
|
|
|
9880
10072
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
9881
10073
|
right.insertBefore(extras, right.firstChild);
|
|
9882
10074
|
});
|
|
9883
|
-
</script>`})}var
|
|
10075
|
+
</script>`})}var Zp=`
|
|
9884
10076
|
/* --- Page frame --- */
|
|
9885
10077
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
9886
10078
|
|
|
@@ -10087,7 +10279,7 @@ loadAgent();
|
|
|
10087
10279
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
10088
10280
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
10089
10281
|
}
|
|
10090
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }
|
|
10282
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,eu=`
|
|
10091
10283
|
'use strict';
|
|
10092
10284
|
|
|
10093
10285
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -10658,7 +10850,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10658
10850
|
});
|
|
10659
10851
|
}
|
|
10660
10852
|
|
|
10661
|
-
`;var
|
|
10853
|
+
`;var gs=`
|
|
10662
10854
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
10663
10855
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
10664
10856
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -10832,7 +11024,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10832
11024
|
.mx-summary{max-width:56vw}
|
|
10833
11025
|
}
|
|
10834
11026
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
10835
|
-
`;var
|
|
11027
|
+
`;var xs=`<script>
|
|
10836
11028
|
window.MX=(function(){
|
|
10837
11029
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
10838
11030
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -10941,7 +11133,7 @@ window.MX=(function(){
|
|
|
10941
11133
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
10942
11134
|
setHealth:setHealth,get:get};
|
|
10943
11135
|
})();
|
|
10944
|
-
</script>`;var
|
|
11136
|
+
</script>`;var vs=`<script>
|
|
10945
11137
|
window.MXD=(function(){
|
|
10946
11138
|
function el(id){return document.getElementById(id)}
|
|
10947
11139
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -11155,7 +11347,7 @@ window.MXD=(function(){
|
|
|
11155
11347
|
|
|
11156
11348
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
11157
11349
|
})();
|
|
11158
|
-
</script>`;var
|
|
11350
|
+
</script>`;var bs=`<script>
|
|
11159
11351
|
(function(){
|
|
11160
11352
|
var LANES=[
|
|
11161
11353
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -11471,7 +11663,7 @@ window.MXD=(function(){
|
|
|
11471
11663
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
11472
11664
|
load();
|
|
11473
11665
|
})();
|
|
11474
|
-
</script>`;var
|
|
11666
|
+
</script>`;var ys=`<script>
|
|
11475
11667
|
(function(){
|
|
11476
11668
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
11477
11669
|
var esc=MX.esc;
|
|
@@ -11649,7 +11841,7 @@ window.MXD=(function(){
|
|
|
11649
11841
|
}
|
|
11650
11842
|
load();setInterval(load,5000);
|
|
11651
11843
|
})();
|
|
11652
|
-
</script>`;var
|
|
11844
|
+
</script>`;var ws=`
|
|
11653
11845
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
11654
11846
|
.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}
|
|
11655
11847
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -11690,7 +11882,7 @@ window.MXD=(function(){
|
|
|
11690
11882
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
11691
11883
|
.mx-rt-name{max-width:100%}
|
|
11692
11884
|
}
|
|
11693
|
-
`,
|
|
11885
|
+
`,ks=`<script>
|
|
11694
11886
|
(function(){
|
|
11695
11887
|
var root=document.getElementById('mx-routines');
|
|
11696
11888
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -11817,7 +12009,7 @@ window.MXD=(function(){
|
|
|
11817
12009
|
syncBar();
|
|
11818
12010
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
11819
12011
|
})();
|
|
11820
|
-
</script>`;var
|
|
12012
|
+
</script>`;var _s=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Ss=`<script>
|
|
11821
12013
|
(function(){
|
|
11822
12014
|
var root=document.getElementById('mx-feed');
|
|
11823
12015
|
if(!root)return;
|
|
@@ -11892,12 +12084,12 @@ window.MXD=(function(){
|
|
|
11892
12084
|
}
|
|
11893
12085
|
load();setInterval(load,5000);
|
|
11894
12086
|
})();
|
|
11895
|
-
</script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var
|
|
12087
|
+
</script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var tu=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],au=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],nu=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Es(t){let e=be({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+_t([{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">
|
|
11896
12088
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
11897
|
-
${
|
|
12089
|
+
${au.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("")}
|
|
11898
12090
|
</div>
|
|
11899
12091
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
11900
|
-
${
|
|
12092
|
+
${nu.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
11901
12093
|
</div>
|
|
11902
12094
|
</div>
|
|
11903
12095
|
<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">
|
|
@@ -11950,7 +12142,7 @@ window.MXD=(function(){
|
|
|
11950
12142
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
11951
12143
|
${ne(ae.routines,"Routines","Everything that runs on its own: schedules and cron- or event-triggered workflows, per node. Flags mark routines that keep failing, went quiet, never ran, or sat disabled.","mx-routines-title",'<span class="ax-tab-count" id="mx-rt-count">0 routines</span>')}
|
|
11952
12144
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
11953
|
-
${
|
|
12145
|
+
${tu.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11954
12146
|
</div>
|
|
11955
12147
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
11956
12148
|
</section>
|
|
@@ -11958,7 +12150,7 @@ window.MXD=(function(){
|
|
|
11958
12150
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
11959
12151
|
${ne(ae.feed,"Mesh feed","The newest events from this machine and every machine it follows. Unreachable machines and announcements show here too. Select an event for its details.","mx-feed-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-feed-count">0 events</span><button class="ax-btn ax-btn--ghost" id="mx-feed-more" type="button" hidden>Show all</button></div>')}
|
|
11960
12152
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
11961
|
-
${
|
|
12153
|
+
${_s.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11962
12154
|
</div>
|
|
11963
12155
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
11964
12156
|
</section>
|
|
@@ -11991,7 +12183,7 @@ window.MXD=(function(){
|
|
|
11991
12183
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
11992
12184
|
</header>
|
|
11993
12185
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
11994
|
-
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
12186
|
+
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:gs+ws,scripts:xs+ru+vs+bs+ks+ys+Ss})}var ru=`<script>
|
|
11995
12187
|
(function(){
|
|
11996
12188
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
11997
12189
|
var range=document.getElementById('mx-range');
|
|
@@ -12019,10 +12211,10 @@ window.MXD=(function(){
|
|
|
12019
12211
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
12020
12212
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
12021
12213
|
})();
|
|
12022
|
-
</script>`;function
|
|
12214
|
+
</script>`;function Ts(t){let e=be({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
|
|
12023
12215
|
<div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
|
|
12024
12216
|
<ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
|
|
12025
|
-
<p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent <id></code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:
|
|
12217
|
+
<p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent <id></code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:ou,scripts:`<script>${su}</script>`})}var ou=`
|
|
12026
12218
|
.gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
|
|
12027
12219
|
.gm-empty { color: var(--ax-text-2); }
|
|
12028
12220
|
.gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
@@ -12040,7 +12232,7 @@ window.MXD=(function(){
|
|
|
12040
12232
|
.gm-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
12041
12233
|
.gm-msg.is-bad { color: var(--ax-red-ink); }
|
|
12042
12234
|
.gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
12043
|
-
`,
|
|
12235
|
+
`,su=`
|
|
12044
12236
|
(function () {
|
|
12045
12237
|
var list = document.getElementById('gm-list');
|
|
12046
12238
|
var msg = document.getElementById('gm-msg');
|
|
@@ -12087,7 +12279,7 @@ window.MXD=(function(){
|
|
|
12087
12279
|
load();
|
|
12088
12280
|
setInterval(load, 30000);
|
|
12089
12281
|
})();
|
|
12090
|
-
`;async function
|
|
12282
|
+
`;async function As(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 iu(s,e.days)}function iu(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,u=0,f=0,h=0,k=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let m=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])m[x][0]+=d[x]?.[0]||0,m[x][1]+=d[x]?.[1]||0;n.set(d.day,m)}for(let d of g.origins){let m=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};m.runs+=d.runs,m.errors+=d.errors,m.hours+=d.hours,r.set(d.channel,m)}for(let d of g.causes){let m=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};m.count+=d.count;for(let x of d.agents)m.agents.includes(x)||m.agents.push(x);m.example||(m.example=d.example),o.set(d.cause,m)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,f=Math.max(f,g.rotations.maxTokens),h+=g.retention.traces,k+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let _=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:h,tracesWithSteps:k}}}async function Cs(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 Is(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 lu(s,e.day)}function lu(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 Ms(t={}){let e=`
|
|
12091
12283
|
<select id="boardPicker" title="Switch board"></select>
|
|
12092
12284
|
<div class="search">
|
|
12093
12285
|
<span class="icon">\u2315</span>
|
|
@@ -12188,7 +12380,7 @@ window.MXD=(function(){
|
|
|
12188
12380
|
</footer>
|
|
12189
12381
|
</div>
|
|
12190
12382
|
</div>
|
|
12191
|
-
<script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:
|
|
12383
|
+
<script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:cu,scripts:`<script>${du}</script>`,headExtras:`<script>
|
|
12192
12384
|
// The boards page has its own connection dot + wants body height:100%
|
|
12193
12385
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
12194
12386
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -12204,7 +12396,7 @@ window.MXD=(function(){
|
|
|
12204
12396
|
right.insertBefore(dot, right.firstChild);
|
|
12205
12397
|
}
|
|
12206
12398
|
});
|
|
12207
|
-
</script>`})}var
|
|
12399
|
+
</script>`})}var cu=`
|
|
12208
12400
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
12209
12401
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
12210
12402
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -12457,7 +12649,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
12457
12649
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
12458
12650
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
12459
12651
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
12460
|
-
`,
|
|
12652
|
+
`,du=`
|
|
12461
12653
|
'use strict';
|
|
12462
12654
|
const state = {
|
|
12463
12655
|
boards: [], current: null, items: {},
|
|
@@ -13510,9 +13702,9 @@ function appendEvents(events) {
|
|
|
13510
13702
|
}
|
|
13511
13703
|
|
|
13512
13704
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
13513
|
-
`;function
|
|
13705
|
+
`;function Ls(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
13514
13706
|
<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>
|
|
13515
|
-
${
|
|
13707
|
+
${hs.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${N(n.alias)}</span>`:"";return`<article class="term"><h3>${N(n.term)}${r}</h3><p>${N(n.definition)}</p></article>`}).join("")}`;return M({title:`${Me.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:pu})}var pu=`
|
|
13516
13708
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
13517
13709
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
13518
13710
|
.lead {
|
|
@@ -13542,7 +13734,7 @@ article.term .alias {
|
|
|
13542
13734
|
}
|
|
13543
13735
|
article.term p {
|
|
13544
13736
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
13545
|
-
}`;function
|
|
13737
|
+
}`;function Rs(t={}){let e=`<div class="ax-wf__root">
|
|
13546
13738
|
<aside class="ax-wf__list">
|
|
13547
13739
|
<header>
|
|
13548
13740
|
<h2>Workflows</h2>
|
|
@@ -13619,7 +13811,7 @@ article.term p {
|
|
|
13619
13811
|
</aside>
|
|
13620
13812
|
</div>
|
|
13621
13813
|
|
|
13622
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
13814
|
+
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:uu,scripts:`<script>${z({workflowHealth:_n})}${mu}</script>`})}var uu=`
|
|
13623
13815
|
.ax-wf__root {
|
|
13624
13816
|
display: grid;
|
|
13625
13817
|
grid-template-columns: 340px 1fr;
|
|
@@ -14003,7 +14195,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14003
14195
|
font-size: 12px; z-index: 50;
|
|
14004
14196
|
}
|
|
14005
14197
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
14006
|
-
`,
|
|
14198
|
+
`,mu=`
|
|
14007
14199
|
(() => {
|
|
14008
14200
|
const $ = (sel) => document.querySelector(sel)
|
|
14009
14201
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -14792,7 +14984,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14792
14984
|
setInterval(refresh, 15000)
|
|
14793
14985
|
})
|
|
14794
14986
|
})();
|
|
14795
|
-
`;function
|
|
14987
|
+
`;function $s(t={}){let e=`<div class="ax-proc__root">
|
|
14796
14988
|
<header class="ax-proc__header">
|
|
14797
14989
|
<h1>Procedures</h1>
|
|
14798
14990
|
<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>
|
|
@@ -14836,7 +15028,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14836
15028
|
<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>
|
|
14837
15029
|
<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>
|
|
14838
15030
|
</section>
|
|
14839
|
-
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
15031
|
+
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:fu,scripts:`<script>${hu}</script>`})}var fu=`
|
|
14840
15032
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
14841
15033
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14842
15034
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -14862,7 +15054,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14862
15054
|
.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); }
|
|
14863
15055
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
14864
15056
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
14865
|
-
`,
|
|
15057
|
+
`,hu=`
|
|
14866
15058
|
(function(){
|
|
14867
15059
|
function $(sel){ return document.querySelector(sel) }
|
|
14868
15060
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -14962,7 +15154,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14962
15154
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
14963
15155
|
else bootAll()
|
|
14964
15156
|
})();
|
|
14965
|
-
`;function
|
|
15157
|
+
`;function Ps(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
14966
15158
|
data-task-id="${N(t.taskId)}"
|
|
14967
15159
|
data-agent-id="${N(t.agentId)}"
|
|
14968
15160
|
data-node-url="${N(t.nodeUrl)}"
|
|
@@ -15005,7 +15197,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15005
15197
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
15006
15198
|
</div>
|
|
15007
15199
|
</footer>
|
|
15008
|
-
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15200
|
+
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:gu,scripts:`<script>${xu}</script>`})}var gu=`
|
|
15009
15201
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
15010
15202
|
the sticky topbar. Breathe. */
|
|
15011
15203
|
.ax-task-page {
|
|
@@ -15147,7 +15339,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15147
15339
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
15148
15340
|
}
|
|
15149
15341
|
|
|
15150
|
-
`,
|
|
15342
|
+
`,xu=`
|
|
15151
15343
|
(function () {
|
|
15152
15344
|
var root = document.querySelector('.ax-task-page');
|
|
15153
15345
|
if (!root) return;
|
|
@@ -15532,7 +15724,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15532
15724
|
});
|
|
15533
15725
|
|
|
15534
15726
|
})();
|
|
15535
|
-
`;function
|
|
15727
|
+
`;function js(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
15536
15728
|
data-agent-id="${N(t.agentId)}"
|
|
15537
15729
|
data-agent-name="${N(e)}"
|
|
15538
15730
|
data-node-url="${N(t.nodeUrl)}">
|
|
@@ -15561,7 +15753,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15561
15753
|
<div class="ax-history__list" id="hist-list">
|
|
15562
15754
|
<div class="ax-history__empty">loading\u2026</div>
|
|
15563
15755
|
</div>
|
|
15564
|
-
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15756
|
+
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vu,scripts:`<script>${bu}</script>`})}var vu=`
|
|
15565
15757
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
15566
15758
|
flush against the sticky topbar. */
|
|
15567
15759
|
.ax-history {
|
|
@@ -15613,7 +15805,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15613
15805
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
15614
15806
|
}
|
|
15615
15807
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
15616
|
-
`,
|
|
15808
|
+
`,bu=`
|
|
15617
15809
|
(function () {
|
|
15618
15810
|
var root = document.querySelector('.ax-history');
|
|
15619
15811
|
if (!root) return;
|
|
@@ -15713,26 +15905,26 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15713
15905
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
15714
15906
|
});
|
|
15715
15907
|
})();
|
|
15716
|
-
`;function
|
|
15908
|
+
`;function Ns(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 ze(t,e,l=>Os(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:wu(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?ze(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"])?ze(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"])?ze(t,e,l=>{let c=ea.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=ta(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 ze(t,e,p=>Os(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 yu=["mesh"];function Os(t,e,a,n){let r=ea.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=ta(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 yu)!(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 wu(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return R(e,200,{runs:u});let f=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return ze(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 ku(t,e,a,l);let c=a.runs.get(l);return c?R(e,200,{run:c}):R(e,404,{error:"run not found"})}return R(e,404,{error:"unknown runs endpoint"})}function ku(t,e,a,n){let r=a.runs.get(n);if(!r)return R(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
|
|
15717
15909
|
|
|
15718
15910
|
`);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)}
|
|
15719
15911
|
|
|
15720
|
-
`)}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
|
|
15912
|
+
`)}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 ze(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 em}from"fs";import{createRequire as tm}from"module";var _u=2048,Ds=/^[A-Za-z0-9_-]{8,256}$/;async function Hs(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return Y(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):Su()});if(n==="GET"&&a==="/api/app/alerts")return Y(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return Y(e,404,{error:"not found"});if(!s||l)return Y(e,503,{error:l});let c;try{c=await ht(t)}catch(h){return Y(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),k=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return Y(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return Y(e,400,{error:`${k} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),S[ce[g].field]=c[ce[g].field];return Y(e,200,{ok:!0,...S})}let p=Eu(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return Y(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return Y(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Ds.test(u)||typeof f!="string"||!Ds.test(f)?Y(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?Y(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function Su(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Eu(t,e){if(typeof t!="string"||t.length>_u)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}sn();var zs=50,Tu=280;async function qs(t,e,a,n,r,o){if(a!=="/api/app/announcements")return!1;if(n==="GET"){let s=o.prefs(),i=[],l=null;try{i=Au(await o.recent(zs))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Bs(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Bs(e,404,{error:"not found"})}function Fs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=ve();return r?new Qn(r):null}}}function Au(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:Ra(typeof n.summary=="string"?n.summary:"",Tu),by:typeof n.agentId=="string"?Ra(n.agentId,100):null,node:Ra(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,zs)}function Ra(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Bs(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Cu="operator",Iu=50,Us=4,Ws=500;function Mu(t){let e={channel:"app",chatId:t.chatId,sender:Cu,...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 Gs(t,e,a,n){let{path:r,body:o}=Mu(e),s="",i=!1,l=[],c=new Map,p=(u,f,h)=>{let k=u!=="done",_=i?{text:ct(f,k),artifacts:[]}:lt(f,le.perMessage,k),{cleanText:S,ui:g}=u==="done"?pt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:$a(g);return{status:u,text:S,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let f=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,f||`AgentX answered HTTP ${u.status}.`)}for await(let f of Ru(u.body)){n(f.event,f.data);let h=f.data??{};if(f.event==="start")i=h.rich===!1;else if(f.event==="text"&&typeof h.text=="string")s+=h.text;else if(f.event==="tool"&&h.status==="start"&&l.length<Iu){let k={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(k),h.id&&c.set(String(h.id),k)}else if(f.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(f.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(f.event==="error")return p("error",s,Lu(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 Lu(t){let e=String(t||"The agent could not answer.");return gn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function $a(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,Us).map(s=>s.slice(0,Ws));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Us).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Ws)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Ru(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,`
|
|
15721
15913
|
`);let s;for(;(s=n.indexOf(`
|
|
15722
15914
|
|
|
15723
15915
|
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
|
|
15724
15916
|
`))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&c.push(p.slice(5).replace(/^ /,""));if(c.length)try{yield{event:l,data:JSON.parse(c.join(`
|
|
15725
|
-
`))}}catch{}}}}finally{e.releaseLock()}}var
|
|
15917
|
+
`))}}catch{}}}}finally{e.releaseLock()}}var Ht=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];plain=!1;orphaned=!1;startedAt=Date.now();listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="start"&&(this.plain=a?.rich===!1),e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}watched(){return this.listeners.size>0}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
|
|
15726
15918
|
data: ${JSON.stringify(s)}
|
|
15727
15919
|
|
|
15728
15920
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
15729
15921
|
|
|
15730
|
-
`)},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
|
|
15731
|
-
`)){let n=
|
|
15732
|
-
`).map(
|
|
15922
|
+
`)},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 Ks(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=$u(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(`
|
|
15923
|
+
`)){let n=Js(a);if(n)return ja(n,e)}return""}function $u(t,e=120){let a=t.split(`
|
|
15924
|
+
`).map(Js).filter(Boolean);return a.length?ja(a[a.length-1],e):""}function Js(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ja(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Bt=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 zt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Xs=140;function qt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Pa(r||"",Xs-18)||"something went wrong."}`:Pa(n,Xs)||"Answered.";return{deviceId:t,title:ja(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var Ys=8e3,ju=/^[A-Za-z0-9_.:-]{1,64}$/,Le=new Map,Oa=new Map,Ha=new Bt;function Qs(){return Ha}async function Zs(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 H(e,200,{nodes:await ei(o)});let i=o.store();if(!i)return H(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),H(e,200,{conversations:Ks(r.id,Du(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Le.get(p.id);return H(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Le.get(p.id);if(!p||!u)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),ti(e);let{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g}=p;return e.write(Na("conversation",{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g})),e.write(Na("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await ht(t,64*1024)}catch(p){return H(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return H(e,404,{error:"no such conversation"});let u=Le.get(p.id);return u?(u.ac.abort(),Da(p,o,r.name),H(e,200,{stopped:!0})):await Da(p,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await Nu(e,c,r,i,o),!0}function Ou(t,e,a){let n=qe(e.url),r=new Set,o=[];for(let s of t){let i=qe(s.url),l=a.find(u=>qe(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function ei(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Ou(e.nodes,t.daemon,a)}async function Nu(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Ys){H(t,400,{error:`message must be 1\u2013${Ys} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let k=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!ju.test(_)){H(t,400,{error:"pick an agent"});return}let S=(await ei(r)).find(d=>d.target===k);if(!S){H(t,400,{error:`unknown node "${k}"`});return}if(!S.online){H(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===_);if(!g){H(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Le.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new Ht(r.orphanLimitMs??18e5);Le.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h}=s;Oa.set(l,{id:l,deviceId:a.id,title:c,agent:f,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),ti(t),t.write(Na("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h})),i.attach(t);try{let k=e.spoken===!0,_=await Gs(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(m,x)=>i.broadcast(m,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Da(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&&zt(d)&&r.notifyFinish(qt(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Le.delete(l),Oa.delete(l),i.finish()}}function Du(){let t=[];for(let[e,a]of Oa){let n=Le.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function ti(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Na(t,e){return`event: ${t}
|
|
15733
15925
|
data: ${JSON.stringify(e)}
|
|
15734
15926
|
|
|
15735
|
-
`}async function ja(t,e,a){try{let n=ze(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=ze(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>ze(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 ze(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 vu}from"stream";var bu=/^\/api\/app\/files\/([^/]+)$/,yu=15e3;async function Ks(t,e,a,n,r,o){let s=bu.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Me(e,405,{error:"GET only"});let i=o.store();if(!i)return Me(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 Me(e,404,{error:"no such file"});let p=await wu(c.node,o);if(!p)return Me(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let f=setTimeout(()=>u.abort(),yu),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Mn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Me(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return Me(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),Me(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...Ln(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let E=0,g=vu.fromWeb(h.body);return g.on("data",d=>{E+=d.length,E>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function wu(t,e){if(t==="local")return{url:Xs(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Xs(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Xs(t){return t.replace(/\/+$/,"")}function Me(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 Vs=8e3;async function Ys(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Hn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Dn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let _=await Pe(t,Nn.bytes);if(!_)return Q(e,413,{error:Bn()});if(!_.length)return Q(e,400,{error:"The recording is empty."});let E={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Js(e,o.daemon,"/voice/transcribe",_,E,18e4)}let s,i=await Pe(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Vs):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!_u(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,f={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return Js(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function Js(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(ku(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function ku(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function _u(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Vs&&a.content.startsWith(e)))}var Eu=new Set(["ring","offer","answer","ice","hangup"]),zt=/^[A-Za-z0-9_-]{4,64}$/,Su=128*1024;async function Qs(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=Ue(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Ue(String(h?.name??""))!==p),f=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:f,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Pe(t,Su);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=Tu(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=Zs(p.to);if(u&&p.kind==="ring"){let f=await Je(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return P(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return zt.test(l)?Au(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Pe(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!zt.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",f=await Je(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Je(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Je(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!zt.test(l))return P(e,400,{error:"callId is required"});let c=await Je(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function Zs(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Je(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 Tu(t,e){let a=String(t?.kind??"");if(!Eu.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!zt.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:")&&!Zs(r))return"to must be bot:<agent id> for an agent";if(Ue(r)===Ue(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 Au(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var ei=`
|
|
15927
|
+
`}async function Da(t,e,a){try{let n=qe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=qe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>qe(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 qe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Hu}from"stream";var Bu=/^\/api\/app\/files\/([^/]+)$/,zu=15e3;async function ni(t,e,a,n,r,o){let s=Bu.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Re(e,405,{error:"GET only"});let i=o.store();if(!i)return Re(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 Re(e,404,{error:"no such file"});let p=await qu(c.node,o);if(!p)return Re(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let f=setTimeout(()=>u.abort(),zu),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${jn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Re(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return Re(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),Re(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...On(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Hu.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 qu(t,e){if(t==="local")return{url:ai(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ai(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ai(t){return t.replace(/\/+$/,"")}function Re(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 oi=8e3;async function si(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Un(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Fn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let _=await Oe(t,qn.bytes);if(!_)return Q(e,413,{error:Wn()});if(!_.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return ri(e,o.daemon,"/voice/transcribe",_,S,18e4)}let s,i=await Oe(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,oi):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!Uu(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,f={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return ri(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function ri(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(Fu(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function Fu(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Uu(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===oi&&a.content.startsWith(e)))}var Wu=new Set(["ring","offer","answer","ice","hangup"]),Ft=/^[A-Za-z0-9_-]{4,64}$/,Gu=128*1024;async function ii(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=We(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>We(String(h?.name??""))!==p),f=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:f,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Oe(t,Gu);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=Xu(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=li(p.to);if(u&&p.kind==="ring"){let f=await Ye(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return P(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Ft.test(l)?Ku(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Oe(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!Ft.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",f=await Ye(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Ye(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ye(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Ft.test(l))return P(e,400,{error:"callId is required"});let c=await Ye(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function li(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Ye(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 Xu(t,e){let a=String(t?.kind??"");if(!Wu.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Ft.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:")&&!li(r))return"to must be bot:<agent id> for an agent";if(We(r)===We(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 Ku(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var ci=`
|
|
15736
15928
|
(function () {
|
|
15737
15929
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
15738
15930
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -15976,7 +16168,7 @@ data: ${JSON.stringify(e)}
|
|
|
15976
16168
|
setInterval(refresh, 15000);
|
|
15977
16169
|
refresh();
|
|
15978
16170
|
})();
|
|
15979
|
-
`;var
|
|
16171
|
+
`;var di=`
|
|
15980
16172
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
15981
16173
|
.fx-head h2 { margin: 4px 0 0; }
|
|
15982
16174
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -16033,7 +16225,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16033
16225
|
}
|
|
16034
16226
|
.fx-error:empty { display: none; }
|
|
16035
16227
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
16036
|
-
`;var
|
|
16228
|
+
`;var pi=`
|
|
16037
16229
|
(function () {
|
|
16038
16230
|
var panel = document.getElementById('panel-alerts');
|
|
16039
16231
|
if (!panel) return;
|
|
@@ -16214,7 +16406,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16214
16406
|
refresh();
|
|
16215
16407
|
loadRecent();
|
|
16216
16408
|
})();
|
|
16217
|
-
`;var
|
|
16409
|
+
`;var ui=`
|
|
16218
16410
|
(function () {
|
|
16219
16411
|
var panel = document.getElementById('panel-alerts');
|
|
16220
16412
|
if (!panel) return;
|
|
@@ -16327,7 +16519,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16327
16519
|
}
|
|
16328
16520
|
load();
|
|
16329
16521
|
})();
|
|
16330
|
-
`;var
|
|
16522
|
+
`;var mi=`
|
|
16331
16523
|
(function () {
|
|
16332
16524
|
var panel = document.getElementById('panel-chat');
|
|
16333
16525
|
var V = window.AXChatView;
|
|
@@ -16599,7 +16791,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16599
16791
|
var last = recall('ax-chat-conv');
|
|
16600
16792
|
if (!fromHash() && last) openConversation(last);
|
|
16601
16793
|
})();
|
|
16602
|
-
`;var
|
|
16794
|
+
`;var fi=`
|
|
16603
16795
|
window.AXChatView = (function () {
|
|
16604
16796
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
16605
16797
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -16880,7 +17072,7 @@ window.AXChatView = (function () {
|
|
|
16880
17072
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
16881
17073
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
16882
17074
|
})();
|
|
16883
|
-
`;var
|
|
17075
|
+
`;var hi=`
|
|
16884
17076
|
window.AXChatSheets = function (o) {
|
|
16885
17077
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
16886
17078
|
function loadPicker() {
|
|
@@ -16926,7 +17118,7 @@ window.AXChatSheets = function (o) {
|
|
|
16926
17118
|
});
|
|
16927
17119
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
16928
17120
|
};
|
|
16929
|
-
`;var
|
|
17121
|
+
`;var gi=`
|
|
16930
17122
|
window.AXChatLog = function (o) {
|
|
16931
17123
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
16932
17124
|
function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
|
|
@@ -16989,7 +17181,7 @@ window.AXChatLog = function (o) {
|
|
|
16989
17181
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
16990
17182
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
16991
17183
|
};
|
|
16992
|
-
`;var
|
|
17184
|
+
`;var xi=`
|
|
16993
17185
|
(function () {
|
|
16994
17186
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
16995
17187
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -17139,7 +17331,7 @@ window.AXChatLog = function (o) {
|
|
|
17139
17331
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
17140
17332
|
poll();
|
|
17141
17333
|
})();
|
|
17142
|
-
`;var
|
|
17334
|
+
`;var vi=`
|
|
17143
17335
|
.cs { margin: 0 -2px; }
|
|
17144
17336
|
.cs[hidden] { display: none; }
|
|
17145
17337
|
.cs-list {
|
|
@@ -17195,7 +17387,7 @@ window.AXChatLog = function (o) {
|
|
|
17195
17387
|
@media (prefers-reduced-motion: reduce) {
|
|
17196
17388
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
17197
17389
|
}
|
|
17198
|
-
`;function
|
|
17390
|
+
`;function bi(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 yi(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var wi=`
|
|
17199
17391
|
body { height: 100dvh; }
|
|
17200
17392
|
main { min-height: 0; }
|
|
17201
17393
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -17305,7 +17497,7 @@ main { min-height: 0; }
|
|
|
17305
17497
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
17306
17498
|
}
|
|
17307
17499
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
17308
|
-
`;var
|
|
17500
|
+
`;var ki=`
|
|
17309
17501
|
window.AXOrb = (function () {
|
|
17310
17502
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
17311
17503
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -17436,7 +17628,7 @@ window.AXOrb = (function () {
|
|
|
17436
17628
|
}
|
|
17437
17629
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
17438
17630
|
})();
|
|
17439
|
-
`;var
|
|
17631
|
+
`;var _i=`
|
|
17440
17632
|
window.AXVoiceIO = (function () {
|
|
17441
17633
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
17442
17634
|
var ac = null, playing = null;
|
|
@@ -17554,7 +17746,7 @@ window.AXVoiceIO = (function () {
|
|
|
17554
17746
|
|
|
17555
17747
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
17556
17748
|
})();
|
|
17557
|
-
`;var
|
|
17749
|
+
`;var Si=`
|
|
17558
17750
|
(function () {
|
|
17559
17751
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
17560
17752
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -17762,7 +17954,7 @@ window.AXVoiceIO = (function () {
|
|
|
17762
17954
|
idle();
|
|
17763
17955
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
17764
17956
|
})();
|
|
17765
|
-
`;var
|
|
17957
|
+
`;var Ei=`
|
|
17766
17958
|
.vx {
|
|
17767
17959
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
17768
17960
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -17798,7 +17990,7 @@ window.AXVoiceIO = (function () {
|
|
|
17798
17990
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
17799
17991
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
17800
17992
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
17801
|
-
`;var
|
|
17993
|
+
`;var Ti=`
|
|
17802
17994
|
<main class="card">
|
|
17803
17995
|
<h1>This phone isn't paired</h1>
|
|
17804
17996
|
<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>
|
|
@@ -17812,7 +18004,7 @@ window.AXVoiceIO = (function () {
|
|
|
17812
18004
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
17813
18005
|
</form>
|
|
17814
18006
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
17815
|
-
</main>`,
|
|
18007
|
+
</main>`,Ai=`
|
|
17816
18008
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
17817
18009
|
.pair-form label { font-weight: 600; }
|
|
17818
18010
|
.pair-form input {
|
|
@@ -17834,7 +18026,7 @@ window.AXVoiceIO = (function () {
|
|
|
17834
18026
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
17835
18027
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
17836
18028
|
}
|
|
17837
|
-
`,
|
|
18029
|
+
`,Ci=`
|
|
17838
18030
|
(function () {
|
|
17839
18031
|
var form = document.getElementById('pair-form');
|
|
17840
18032
|
var input = document.getElementById('pair-code');
|
|
@@ -17926,7 +18118,7 @@ window.AXVoiceIO = (function () {
|
|
|
17926
18118
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
17927
18119
|
}
|
|
17928
18120
|
})();
|
|
17929
|
-
`;var
|
|
18121
|
+
`;var Ii=`
|
|
17930
18122
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
17931
18123
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
17932
18124
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -17935,7 +18127,7 @@ window.AXVoiceIO = (function () {
|
|
|
17935
18127
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
17936
18128
|
</div>
|
|
17937
18129
|
<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>
|
|
17938
|
-
</div>`,
|
|
18130
|
+
</div>`,Mi=`
|
|
17939
18131
|
.pair-form .scan-btn {
|
|
17940
18132
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
17941
18133
|
}
|
|
@@ -17964,7 +18156,7 @@ window.AXVoiceIO = (function () {
|
|
|
17964
18156
|
}
|
|
17965
18157
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
17966
18158
|
body.scanning { overflow: hidden; }
|
|
17967
|
-
`,
|
|
18159
|
+
`,Li=`
|
|
17968
18160
|
(function () {
|
|
17969
18161
|
var openBtn = document.getElementById('scan-btn');
|
|
17970
18162
|
var box = document.getElementById('scan');
|
|
@@ -18130,7 +18322,7 @@ body.scanning { overflow: hidden; }
|
|
|
18130
18322
|
document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
|
|
18131
18323
|
window.addEventListener('pagehide', close);
|
|
18132
18324
|
})();
|
|
18133
|
-
`;var
|
|
18325
|
+
`;var Ba=`
|
|
18134
18326
|
.cam { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; background: var(--ax-bg); }
|
|
18135
18327
|
.cam[hidden] { display: none; }
|
|
18136
18328
|
.cam-live {
|
|
@@ -18172,7 +18364,7 @@ body.scanning { overflow: hidden; }
|
|
|
18172
18364
|
border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
|
|
18173
18365
|
}
|
|
18174
18366
|
.cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
|
|
18175
|
-
`;var
|
|
18367
|
+
`;var Ri='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',$i=`
|
|
18176
18368
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
18177
18369
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
18178
18370
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -18197,7 +18389,7 @@ body.scanning { overflow: hidden; }
|
|
|
18197
18389
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
18198
18390
|
</div>
|
|
18199
18391
|
</div>
|
|
18200
|
-
</div>`,
|
|
18392
|
+
</div>`,Pi=`
|
|
18201
18393
|
(function () {
|
|
18202
18394
|
var btn = document.getElementById('cam-btn');
|
|
18203
18395
|
var sheet = document.getElementById('cam');
|
|
@@ -18466,7 +18658,7 @@ body.scanning { overflow: hidden; }
|
|
|
18466
18658
|
});
|
|
18467
18659
|
window.addEventListener('pagehide', function () { stop(); });
|
|
18468
18660
|
})();
|
|
18469
|
-
`;var
|
|
18661
|
+
`;var ji=`
|
|
18470
18662
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
18471
18663
|
<div class="cam-askbar-text">
|
|
18472
18664
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -18476,7 +18668,7 @@ body.scanning { overflow: hidden; }
|
|
|
18476
18668
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
18477
18669
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
18478
18670
|
</div>
|
|
18479
|
-
</div>`,
|
|
18671
|
+
</div>`,Oi=`
|
|
18480
18672
|
.cam-askbar[hidden] { display: none; }
|
|
18481
18673
|
.cam-askbar {
|
|
18482
18674
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -18491,7 +18683,7 @@ body.scanning { overflow: hidden; }
|
|
|
18491
18683
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
18492
18684
|
}
|
|
18493
18685
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
18494
|
-
`,
|
|
18686
|
+
`,Ni=`
|
|
18495
18687
|
(function () {
|
|
18496
18688
|
var bar = document.getElementById('cam-ask-bar');
|
|
18497
18689
|
if (!bar) return;
|
|
@@ -18561,8 +18753,128 @@ body.scanning { overflow: hidden; }
|
|
|
18561
18753
|
setInterval(poll, 5000);
|
|
18562
18754
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
18563
18755
|
})();
|
|
18564
|
-
`;function
|
|
18565
|
-
|
|
18756
|
+
`;function Di(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 Hi(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 Bi=`
|
|
18757
|
+
(function () {
|
|
18758
|
+
var main = document.querySelector('main');
|
|
18759
|
+
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
18760
|
+
if (!main || tabs.length < 2) return;
|
|
18761
|
+
var reduce = window.matchMedia ? matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
18762
|
+
var SLIDE_MS = 220;
|
|
18763
|
+
var g = null; // the touch being followed
|
|
18764
|
+
var sliding = false; // the landing slide is running
|
|
18765
|
+
|
|
18766
|
+
function still() { return !!(reduce && reduce.matches); }
|
|
18767
|
+
function panelOf(i) { return document.getElementById(tabs[i].getAttribute('aria-controls')); }
|
|
18768
|
+
function current() {
|
|
18769
|
+
for (var i = 0; i < tabs.length; i++) if (tabs[i].getAttribute('aria-selected') === 'true') return i;
|
|
18770
|
+
return 0;
|
|
18771
|
+
}
|
|
18772
|
+
function pathFrom(el) {
|
|
18773
|
+
var path = [];
|
|
18774
|
+
for (; el && el !== main; el = el.parentElement) {
|
|
18775
|
+
var cs = getComputedStyle(el);
|
|
18776
|
+
path.push({
|
|
18777
|
+
tag: el.tagName, touchAction: cs.touchAction, editable: el.isContentEditable,
|
|
18778
|
+
scrollsX: (cs.overflowX === 'auto' || cs.overflowX === 'scroll') && el.scrollWidth > el.clientWidth + 1,
|
|
18779
|
+
});
|
|
18780
|
+
}
|
|
18781
|
+
return path;
|
|
18782
|
+
}
|
|
18783
|
+
|
|
18784
|
+
function unpeek() {
|
|
18785
|
+
if (!g.peek) return;
|
|
18786
|
+
g.peek.classList.remove('sw-peek');
|
|
18787
|
+
g.peek.style.top = '';
|
|
18788
|
+
g.peek.style.transform = '';
|
|
18789
|
+
g.peek = null;
|
|
18790
|
+
}
|
|
18791
|
+
// Show the tab on the side the finger is pulling from, beside this one.
|
|
18792
|
+
function peek(side) {
|
|
18793
|
+
if (g.side === side) return;
|
|
18794
|
+
unpeek();
|
|
18795
|
+
g.side = side;
|
|
18796
|
+
var i = g.index + side;
|
|
18797
|
+
if (i < 0 || i >= tabs.length) return;
|
|
18798
|
+
g.peek = panelOf(i);
|
|
18799
|
+
g.peek.style.top = main.scrollTop + 'px';
|
|
18800
|
+
g.peek.classList.add('sw-peek');
|
|
18801
|
+
}
|
|
18802
|
+
function place(x) {
|
|
18803
|
+
g.from.style.transform = 'translateX(' + x + 'px)';
|
|
18804
|
+
if (g.peek) g.peek.style.transform = 'translateX(' + (x + g.side * g.width) + 'px)';
|
|
18805
|
+
}
|
|
18806
|
+
// px per ms over the last moment of the touch, so a finger that rests
|
|
18807
|
+
// before it lifts is not a flick.
|
|
18808
|
+
function speed() {
|
|
18809
|
+
var now = Date.now();
|
|
18810
|
+
while (g.trail.length && now - g.trail[0].t > 120) g.trail.shift();
|
|
18811
|
+
var a = g.trail[0];
|
|
18812
|
+
return a && now > a.t ? (g.dx - a.dx) / (now - a.t) : 0;
|
|
18813
|
+
}
|
|
18814
|
+
function finish(to) {
|
|
18815
|
+
var s = g;
|
|
18816
|
+
main.classList.remove('sw-on', 'sw-slide');
|
|
18817
|
+
s.from.style.transform = '';
|
|
18818
|
+
unpeek();
|
|
18819
|
+
g = null;
|
|
18820
|
+
sliding = false;
|
|
18821
|
+
if (to === s.index) return;
|
|
18822
|
+
tabs[to].click();
|
|
18823
|
+
main.scrollTop = 0;
|
|
18824
|
+
}
|
|
18825
|
+
function end(cancelled) {
|
|
18826
|
+
if (!g || sliding) return;
|
|
18827
|
+
if (g.axis !== 'x') { g = null; return; }
|
|
18828
|
+
var to = cancelled ? g.index : swipeLanding(g.index, tabs.length, g.dx, g.width, speed());
|
|
18829
|
+
if (still()) { finish(to); return; }
|
|
18830
|
+
sliding = true;
|
|
18831
|
+
main.classList.add('sw-slide');
|
|
18832
|
+
place(to === g.index ? 0 : (to > g.index ? -g.width : g.width));
|
|
18833
|
+
setTimeout(function () { finish(to); }, SLIDE_MS + 30);
|
|
18834
|
+
}
|
|
18835
|
+
|
|
18836
|
+
main.addEventListener('touchstart', function (ev) {
|
|
18837
|
+
if (sliding) return;
|
|
18838
|
+
if (g) { end(true); return; } // a second finger: let go
|
|
18839
|
+
if (ev.touches.length !== 1 || !swipeMayStart(pathFrom(ev.target))) return;
|
|
18840
|
+
var t = ev.touches[0];
|
|
18841
|
+
g = { x: t.clientX, y: t.clientY, trail: [{ dx: 0, t: Date.now() }], axis: '', dx: 0, side: 0, peek: null, index: current() };
|
|
18842
|
+
}, { passive: true });
|
|
18843
|
+
main.addEventListener('touchmove', function (ev) {
|
|
18844
|
+
if (!g || sliding) return;
|
|
18845
|
+
var t = ev.touches[0], dx = t.clientX - g.x;
|
|
18846
|
+
if (!g.axis) {
|
|
18847
|
+
g.axis = swipeAxis(dx, t.clientY - g.y);
|
|
18848
|
+
if (g.axis === 'y') { g = null; return; }
|
|
18849
|
+
if (!g.axis) return;
|
|
18850
|
+
g.width = main.clientWidth;
|
|
18851
|
+
g.from = panelOf(g.index);
|
|
18852
|
+
main.classList.add('sw-on');
|
|
18853
|
+
}
|
|
18854
|
+
if (ev.cancelable) ev.preventDefault();
|
|
18855
|
+
g.dx = dx;
|
|
18856
|
+
g.trail.push({ dx: dx, t: Date.now() });
|
|
18857
|
+
if (g.trail.length > 8) g.trail.shift();
|
|
18858
|
+
if (still()) return;
|
|
18859
|
+
peek(dx < 0 ? 1 : -1);
|
|
18860
|
+
place(swipeOffset(g.index, tabs.length, dx));
|
|
18861
|
+
}, { passive: false });
|
|
18862
|
+
main.addEventListener('touchend', function () { end(false); });
|
|
18863
|
+
main.addEventListener('touchcancel', function () { end(true); });
|
|
18864
|
+
})();
|
|
18865
|
+
`,zi=`
|
|
18866
|
+
main { position: relative; }
|
|
18867
|
+
main.sw-on { overflow: hidden; }
|
|
18868
|
+
.sw-on > [role=tabpanel] { will-change: transform; }
|
|
18869
|
+
.sw-slide > [role=tabpanel] { transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1); }
|
|
18870
|
+
main > .sw-peek {
|
|
18871
|
+
display: block; position: absolute; left: 0; right: 0; box-sizing: border-box; min-height: 100%;
|
|
18872
|
+
padding: 16px calc(16px + env(safe-area-inset-right)) 16px calc(16px + env(safe-area-inset-left));
|
|
18873
|
+
}
|
|
18874
|
+
main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
|
|
18875
|
+
@media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
|
|
18876
|
+
`;function qi(t){let e=["INPUT","TEXTAREA","SELECT","DIALOG"];return!t.some(a=>a.scrollsX||a.editable||a.touchAction==="none"||a.touchAction==="pan-x"||e.indexOf(a.tag)>=0)}function Fi(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Ui(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Wi(t,e,a,n,r){if(!(Math.abs(r)>.5?r*a>0&&Math.abs(a)>30:Math.abs(a)>n/3))return t;let i=t+(a<0?1:-1);return i<0||i>=e?t:i}var za=`
|
|
18877
|
+
${z({afterUnauthorized:Pr})}
|
|
18566
18878
|
var CACHE = 'agentx-app-v3';
|
|
18567
18879
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
18568
18880
|
self.addEventListener('install', function (e) {
|
|
@@ -18653,7 +18965,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
18653
18965
|
return self.clients.openWindow(target);
|
|
18654
18966
|
}));
|
|
18655
18967
|
});
|
|
18656
|
-
`;var
|
|
18968
|
+
`;var Ju="<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 qa(t){return`<meta charset="utf-8">
|
|
18657
18969
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
18658
18970
|
<meta name="theme-color" content="#2979FF">
|
|
18659
18971
|
<meta name="referrer" content="no-referrer">
|
|
@@ -18664,55 +18976,56 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
18664
18976
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
18665
18977
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
18666
18978
|
<title>${t}</title>
|
|
18667
|
-
${
|
|
18668
|
-
<style>${
|
|
18979
|
+
${Ju}
|
|
18980
|
+
<style>${kt}${Qu}</style>`}var Gi=[{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 Xi(){let t=Gi.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=Gi.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
18669
18981
|
<h2>${a.label}</h2>
|
|
18670
18982
|
<p class="soon">${a.soon}</p>
|
|
18671
18983
|
</section>`).join("");return`<!doctype html>
|
|
18672
18984
|
<html lang="en">
|
|
18673
|
-
<head>${
|
|
18985
|
+
<head>${qa("AgentX")}<style>${Zu}${di}${wi}${vi}${Ei}${Ba}${Oi}${zi}</style></head>
|
|
18674
18986
|
<body>
|
|
18675
18987
|
<header class="bar">
|
|
18676
18988
|
<div>
|
|
18677
18989
|
<h1>AgentX</h1>
|
|
18678
18990
|
<p id="who" class="who">Connecting\u2026</p>
|
|
18679
18991
|
</div>
|
|
18680
|
-
<div class="bar-btns">${
|
|
18992
|
+
<div class="bar-btns">${Ri}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
|
|
18681
18993
|
</header>
|
|
18682
18994
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
18683
|
-
${
|
|
18995
|
+
${ji}
|
|
18684
18996
|
<main>${e}</main>
|
|
18685
18997
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
18686
|
-
${
|
|
18687
|
-
<script>${
|
|
18688
|
-
<script>${
|
|
18689
|
-
<script>${
|
|
18690
|
-
<script>${
|
|
18691
|
-
<script>${
|
|
18692
|
-
<script>${z({
|
|
18693
|
-
<script>${
|
|
18694
|
-
<script>${
|
|
18695
|
-
<script>${
|
|
18998
|
+
${$i}
|
|
18999
|
+
<script>${Vu}</script>
|
|
19000
|
+
<script>${z({swipeMayStart:qi,swipeAxis:Fi,swipeOffset:Ui,swipeLanding:Wi})}${Bi}</script>
|
|
19001
|
+
<script>${ci}</script>
|
|
19002
|
+
<script>${pi}</script>
|
|
19003
|
+
<script>${ui}</script>
|
|
19004
|
+
<script>${z({markdownToHtml:er})}${fi}${gi}${hi}${mi}</script>
|
|
19005
|
+
<script>${z({queueSpeech:bi,nextSpeech:yi})}${ki}${_i}${Si}</script>
|
|
19006
|
+
<script>${xi}</script>
|
|
19007
|
+
<script>${z({cameraConstraints:Di,shareClock:Hi})}${Pi}</script>
|
|
19008
|
+
<script>${Ni}</script>
|
|
18696
19009
|
</body>
|
|
18697
|
-
</html>`}function
|
|
19010
|
+
</html>`}function Ki(){return`<!doctype html>
|
|
18698
19011
|
<html lang="en">
|
|
18699
|
-
<head>${
|
|
19012
|
+
<head>${qa("Pair \xB7 AgentX")}</head>
|
|
18700
19013
|
<body>
|
|
18701
19014
|
<main class="card">
|
|
18702
19015
|
<h1>Pairing this phone\u2026</h1>
|
|
18703
19016
|
<p id="msg" role="status">One moment.</p>
|
|
18704
19017
|
</main>
|
|
18705
|
-
<script>${
|
|
19018
|
+
<script>${Yu}</script>
|
|
18706
19019
|
</body>
|
|
18707
|
-
</html>`}function
|
|
19020
|
+
</html>`}function Ji(){return`<!doctype html>
|
|
18708
19021
|
<html lang="en">
|
|
18709
|
-
<head>${
|
|
18710
|
-
<body>${
|
|
18711
|
-
<script>${z({mayBounce:
|
|
18712
|
-
<script>${
|
|
18713
|
-
<script>${
|
|
19022
|
+
<head>${qa("Not paired \xB7 AgentX")}<style>${Ai}${Mi}</style></head>
|
|
19023
|
+
<body>${Ti}${Ii}
|
|
19024
|
+
<script>${z({mayBounce:jr,formatPairInput:Mt,parsePairScan:Or})}</script>
|
|
19025
|
+
<script>${Ci}</script>
|
|
19026
|
+
<script>${Li}</script>
|
|
18714
19027
|
</body>
|
|
18715
|
-
</html>`}function
|
|
19028
|
+
</html>`}function Vi(){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 Vu=`
|
|
18716
19029
|
(function () {
|
|
18717
19030
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
18718
19031
|
function select(tab, focus, keepHash) {
|
|
@@ -18782,7 +19095,7 @@ ${Ei}
|
|
|
18782
19095
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
18783
19096
|
}
|
|
18784
19097
|
})();
|
|
18785
|
-
`,
|
|
19098
|
+
`,Yu=`
|
|
18786
19099
|
(function () {
|
|
18787
19100
|
var msg = document.getElementById('msg');
|
|
18788
19101
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -18799,7 +19112,7 @@ ${Ei}
|
|
|
18799
19112
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
18800
19113
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
18801
19114
|
})();
|
|
18802
|
-
`,
|
|
19115
|
+
`,Qu=`
|
|
18803
19116
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
18804
19117
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
18805
19118
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -18811,7 +19124,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
18811
19124
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
18812
19125
|
.muted { color: var(--ax-text-2); }
|
|
18813
19126
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
18814
|
-
`,
|
|
19127
|
+
`,Zu=`
|
|
18815
19128
|
body { display: flex; flex-direction: column; }
|
|
18816
19129
|
.bar {
|
|
18817
19130
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -18849,8 +19162,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
18849
19162
|
}
|
|
18850
19163
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
18851
19164
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
18852
|
-
`;var
|
|
18853
|
-
`;
|
|
19165
|
+
`;var Ut="agentx_app",am=400*86400,nm=new gt,rm=new Ee;async function Yi(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new F;if(n==="GET"){if(a==="/app/manifest.webmanifest")return xe(e,200,"application/manifest+json",Vi());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),xe(e,200,"text/javascript; charset=utf-8",za);if(a==="/app/icon-192.png")return xe(e,200,"image/png",He(192),"public, max-age=86400");if(a==="/app/icon-512.png")return xe(e,200,"image/png",He(512),"public, max-age=86400");if(a==="/app/pair")return xe(e,200,"text/html; charset=utf-8",Ki());if(a==="/app/qr.js"){let i=om();return i?xe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):$e(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Fa(Ze(t),o);return i?(e.setHeader("Set-Cookie",Ua(Ze(t))),$e(e,200,{device:i.name})):$e(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await $n(t,{codes:r.pairCodes??new ut,limiter:r.pairLimiter??nm,verify:l=>Fa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ua(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),$e(e,i.status,i.body)}let s=Fa(sm(t),o);if(!s){let i=Ze(t);return(r.rejectLog??rm).record(a.slice(0,120),It(t,De(Wa(t,Ut),o),i?De(i,o):null)),a==="/app"?xe(e,401,"text/html; charset=utf-8",Ji()):$e(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Wa(t,Ut);return i&&!Ze(t)&&e.setHeader("Set-Cookie",Ua(i)),xe(e,200,"text/html; charset=utf-8",Xi())}return n==="GET"&&a==="/api/app/me"?$e(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Rn(t,e,a,n,s.name,r.fleet)||r.push&&await Hs(t,e,a,n,s,r.push)||r.announce&&await qs(t,e,a,n,s,r.announce)||r.chat&&await Zs(t,e,a,n,s,r.chat)||r.chat&&await ni(t,e,a,n,s,r.chat)||r.voice&&await si(t,e,a,n,s,r.voice)||r.camera&&await ii(t,e,a,n,r.camera)?!0:$e(e,404,{error:"not found"})}var Qe;function om(){if(Qe!==void 0)return Qe;try{let t=tm(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
19166
|
+
`;Qe=Buffer.concat([Buffer.from(a),em(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Qe=null}return Qe}function Fa(t,e){if(!t)return null;let a=e.verify(t);return a&&ke(a,"app")?a:null}function Ua(t){return`${Ut}=${t}; Path=/; Max-Age=${am}; HttpOnly; Secure; SameSite=Lax`}function sm(t){return Ze(t)??Wa(t,Ut)}function Ze(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Wa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function xe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function $e(t,e,a){return xe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Qi}from"crypto";var Pe={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},im=/^[a-f0-9]{32}$/,lm=/^c[a-z0-9]{8,32}$/,cm=/^#[0-9a-fA-F]{6}$/;function Ga(t){return lm.test(t)}var et=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
18854
19167
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
18855
19168
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
18856
19169
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -18863,39 +19176,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
18863
19176
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
18864
19177
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
18865
19178
|
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 (
|
|
18866
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return
|
|
18867
|
-
(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(!
|
|
19179
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Ga(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)}${Qi(4).toString("hex")}`,{color:s,...i}=a,l=s&&cm.test(s)?s:void 0,c={id:o,title:pm(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
19180
|
+
(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(!Ga(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(dm);return{...Zi(n),messages:r}}list(e,a=Pe.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
18868
19181
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
18869
19182
|
(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
|
|
18870
|
-
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{...
|
|
19183
|
+
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{...Zi(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Ga(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,
|
|
18871
19184
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
18872
19185
|
FROM app_chat_conversations c
|
|
18873
19186
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
18874
19187
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
18875
|
-
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>
|
|
19188
|
+
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>Pe.content?n.content.slice(0,Pe.content)+`
|
|
18876
19189
|
|
|
18877
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,
|
|
19190
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Pe.toolsPerMessage),l=[];for(let f of r){if(l.length>=Pe.filesPerMessage)break;let h=f.filename.trim(),k=yn(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Qi(16).toString("hex"),name:_,mime:k.mime,kind:k.kind,path:h})}let c=l.map(f=>({id:f.id,name:f.name,mime:f.mime,kind:f.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
18878
19191
|
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)
|
|
18879
19192
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let f of l)u.run(f.id,a,Number(p.lastInsertRowid),f.path,f.name,f.mime,f.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
18880
|
-
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,
|
|
18881
|
-
(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(!
|
|
19193
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Pe.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
|
|
19194
|
+
(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(!im.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
18882
19195
|
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 = ?
|
|
18883
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,
|
|
19196
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Pe.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 Zi(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 dm(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 pm(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var um=4e3,Xa=100,mm=15,el=t=>t.replace(/\/+$/,""),Wt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=um){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,Xa);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??mm)-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>=Xa&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Xa}); 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||el(l)!==el(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=fm(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,f=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:f};return this.deps.notifyFinish&&zt(h)&&this.deps.notifyFinish(qt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function fm(t,e){let a=t.plain?{text:ct(t.text,!1),artifacts:[]}:lt(t.text,le.perMessage,!1),{cleanText:n,ui:r}=pt(a.text),o=t.plain?void 0:$a(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:hm(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function hm(t){return t.replace(/\s+/g," ").trim().slice(0,300)}sn();function Ty(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,Am(h,t))}catch(k){console.error(` Board "${h.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?tt(process.cwd(),t.workflows.dir):void 0,c=new xn(l?{baseDir:l}:void 0),p=new vn(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new bn(l?{baseDir:l}:void 0);rs(t),Hn({business:t.business?.enabled===!0});let f=gm(async(h,k)=>{try{await _m(h,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){b(k,500,{error:_.message||"internal error"})}});Um(t).start(),f.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
18884
19197
|
Live dashboard: http://${h}:${n}
|
|
18885
19198
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
18886
19199
|
Kanban dashboard: http://${h}:${n}
|
|
18887
|
-
`),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var tm=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 am(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(Rn(t.headers)==="foreign"&&$n(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Hr(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>It(a.config.people),members:km(a.config.members.logRetentionDays),db:()=>be(),linkFor:(d,m)=>Sr(d,m,{gitlab:a.config.channels.gitlab?.host})})||await Oi(t,e,r,o,{nodeName:a.config.node?.name,fleet:Wi(a.config),push:Ui(a.config),announce:Ps(a.config),chat:Gi(a.config),voice:Sm(a.config),camera:Tm(a.config)}))return;if(o==="GET"&&tm.has(r)&&ur("page",r),o==="GET"&&r==="/"){let d=er();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(Ca({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ws({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ca({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ve(a.config);if(!d){b(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",T=>w+=T),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){b(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await ve(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await pe(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){b(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(w.url+r+T,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});b(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){b(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await pe(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ve(a.config);if(!d){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wr({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(xr({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=xn(await ve(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 S=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!S.ok)throw new Error(`HTTP ${S.status}`);return{name:C.name,url:C.url,ok:!0,data:await S.json()}}catch(S){return{name:C.name,url:C.url,ok:!1,error:S.message}}}));b(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){b(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){b(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await gn(t)):void 0,y=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});b(e,y.status,await y.json())}catch(x){b(e,502,{error:x.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gs({peers:H(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xs({peers:H(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await pe(t).catch(()=>({})):void 0,v=await fetch(`${m}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});b(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ks({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_s({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Es({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zn({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ss({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers: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(Ts({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"){tr(t,e);return}if(o==="POST"&&r==="/api/setup"){await ar(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await nr(t,e);return}if(o==="GET"&&r==="/admin"){Vr(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){mo(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){no(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}yo(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 Rm(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Ta(t,e,r,x=>Ki(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),T=x.slice(v+2),y=a.config.node?.id||a.config.node?.name||"local";if(w===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=et(I.url.replace(/\/+$/,""),a.config);if(C){await zi(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}b(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=et(d,a.config);if(!m){b(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await zi(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await wo(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await $m(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-COAIIKLV.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});b(e,200,v)}catch(d){b(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(So({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Eo(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(To({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ao({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 cm(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 Vo(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Ta(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Qo(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){ts(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new X,v=m?x.verify(m):null;if(!v||!ye(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Yr(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){b(e,200,On()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await fo(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await ro(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await as(t,e,r);return}if(r.startsWith("/api/admin/")){await Qr(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(Br);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){b(e,400,{error:"invalid asset name"});return}let m=Mm("web/"+d);try{let x=await Lm(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await qe(a.config);b(e,200,d)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await qe(a.config,{date:d,timezone:m});b(e,200,x)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let T=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(T)?Math.max(v,Math.min(w,T)):x};try{let m=await ve(a.config);b(e,200,await vs(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,T)=>{let y=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(y)?Math.max(w,Math.min(T,y)):v};try{let x=await ve(a.config);b(e,200,await ys(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){b(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){b(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await bs(e,await ve(a.config),d,x)}catch(v){b(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){gm(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){b(e,400,{error:"node, agent, task query params required"});return}await xm(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){b(e,400,{error:"node and agent query params required"});return}await ym(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await wm(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await Ja(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();b(e,200,x)}catch(d){b(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(d){b(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await pe(t);try{let m=await Cm(a.config,d);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!vm(t,e,[`agent:${d}`]))return;await bm(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new X,v=m?x.verify(m):null;if(!v||!ye(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await dm(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await Ja(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({name:y.name,url:y.url,token:y.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let y of w)try{y.abort()}catch{}});let T=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
19200
|
+
`),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var km=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function _m(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(Nn(t.headers)==="foreign"&&Dn(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Gr(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ge(a.config.people),members:tl(a.config.members.logRetentionDays),db:()=>ve(),linkFor:(d,m)=>Rr(d,m,{gitlab:a.config.channels.gitlab?.host})})||await Yi(t,e,r,o,{nodeName:a.config.node?.name,fleet:il(a.config),push:sl(a.config),announce:Fs(a.config),chat:ll(a.config),voice:Wm(a.config),camera:Gm(a.config)}))return;if(o==="GET"&&km.has(r)&&br("page",r),o==="GET"&&r==="/"){let d=or();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(La({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ms({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(La({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await we(a.config);if(!d){b(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",T=>w+=T),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){b(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await we(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await ue(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){b(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(w.url+r+T,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});b(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){b(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await we(a.config);if(!d){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ir({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Cr({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Sr({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=kn(await we(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));b(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){b(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){b(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await wn(t)):void 0,y=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});b(e,y.status,await y.json())}catch(x){b(e,502,{error:x.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Es({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ts({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await ue(t).catch(()=>({})):void 0,v=await fetch(`${m}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});b(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ls({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rs({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($s({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rr({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ps({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers:D(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(js({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){sr(t,e);return}if(o==="POST"&&r==="/api/setup"){await ir(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await lr(t,e);return}if(o==="GET"&&r==="/admin"){no(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){yo(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){po(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Io(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Qm(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Ia(t,e,r,x=>dl(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),T=x.slice(v+2),y=a.config.node?.id||a.config.node?.name||"local";if(w===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=at(I.url.replace(/\/+$/,""),a.config);if(C){await nl(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}b(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=at(d,a.config);if(!m){b(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await nl(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Mo(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Zm(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-COAIIKLV.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});b(e,200,v)}catch(d){b(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Po({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await $o(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(jo({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oo({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await Mm(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 os(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Ia(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await is(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){ds(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ro(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){b(e,200,zn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await wo(t,e,r,n);return}if(await _o(t,e,r,{people:()=>Ge(a.config.people),members:tl(a.config.members.logRetentionDays),root:process.cwd(),db:()=>ve(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await uo(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await ps(t,e,r);return}if(r.startsWith("/api/admin/")){await oo(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(Xr);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){b(e,400,{error:"invalid asset name"});return}let m=Vm("web/"+d);try{let x=await Ym(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Fe(a.config);b(e,200,d)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await Fe(a.config,{date:d,timezone:m});b(e,200,x)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let T=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(T)?Math.max(v,Math.min(w,T)):x};try{let m=await we(a.config);b(e,200,await As(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,T)=>{let y=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(y)?Math.max(w,Math.min(T,y)):v};try{let x=await we(a.config);b(e,200,await Is(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){b(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){b(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await Cs(e,await we(a.config),d,x)}catch(v){b(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Nm(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){b(e,400,{error:"node, agent, task query params required"});return}await Dm(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){b(e,400,{error:"node and agent query params required"});return}await zm(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await qm(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await Qa(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();b(e,200,x)}catch(d){b(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(d){b(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ue(t);try{let m=await Km(a.config,d);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!Hm(t,e,[`agent:${d}`]))return;await Bm(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Lm(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await Qa(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({name:y.name,url:y.url,token:y.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let y of w)try{y.abort()}catch{}});let T=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
18888
19201
|
|
|
18889
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let y of x)(async()=>{let I={Accept:"text/event-stream"};y.token&&(I.Authorization=`Bearer ${y.token}`);let C=new AbortController;w.push(C);try{let
|
|
19202
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let y of x)(async()=>{let I={Accept:"text/event-stream"};y.token&&(I.Authorization=`Bearer ${y.token}`);let C=new AbortController;w.push(C);try{let E=await fetch(`${y.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:I,signal:C.signal});if(!E.ok||!E.body)return;let $=E.body.getReader(),L=new TextDecoder,j="";for(;!v.flag;){let{done:W,value:q}=await $.read();if(W)break;j+=L.decode(q,{stream:!0});let G;for(;(G=j.indexOf(`
|
|
18890
19203
|
|
|
18891
|
-
`))>=0;){let ie=j.slice(0,
|
|
19204
|
+
`))>=0;){let ie=j.slice(0,G);if(j=j.slice(G+2),v.flag)break;try{e.write(ie+`
|
|
18892
19205
|
|
|
18893
|
-
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),T=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,y=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(y.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let
|
|
18894
|
-
`;
|
|
19206
|
+
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),T=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,y=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(y.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let W=new AbortController,q=setTimeout(()=>W.abort(),5e3);try{let G=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${T}`,{headers:j,signal:W.signal});if(!G.ok)return[];let ie=await G.json();return Array.isArray(ie.runs)?ie.runs:[]}finally{clearTimeout(q)}}catch{return[]}})),C=new Map;for(let L of w)C.set(L.id,L);for(let L of I)for(let j of L)C.set(j.id,j);let E=Array.from(C.values()).sort((L,j)=>L.updatedAt<j.updatedAt?1:-1).slice(0,m),$=v?E.map(L=>Tm(L)):E;b(e,200,{runs:$})}catch(d){b(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let d=decodeURIComponent(f[1]),m=a.workflowRuns.get(d);if(m){b(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let w={};v.token&&(w.Authorization=`Bearer ${v.token}`);let T=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:w});if(T.ok){b(e,200,await T.json());return}}catch{}b(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${m}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,v)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await ue(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Ns(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let w=na(m);if(!w)return!0;let T=new F().verify(w);if(!T)return b(x,401,{error:"invalid or revoked token"}),!1;for(let y of v)if(!ke(T,y))return b(x,403,{error:`token missing scope: ${y}`,scopes:T.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let d=a.sources.get(k[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,m]=S,x=decodeURIComponent(m),v=a.boards.find(C=>C.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}let T=await ue(t),y=v.columns.find(C=>C.id===T.to),I=v.columns.find(C=>C.id===T.from);if(!y){b(e,400,{error:`unknown 'to' column: ${T.to}`});return}try{await Em(w,x,I,y),Ka({actor:Ja(t),action:"move",boardId:d,itemId:x,payload:{from:T.from,to:T.to}}),b(e,200,{ok:!0})}catch(C){b(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,v=a.boards.find(T=>T.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:T,totals:y}=await Sm(v,w,n.searchParams);b(e,200,{columns:T,totals:y});return}if(o==="GET"&&x){try{let T=typeof w.getItem=="function"?await w.getItem(x):null;if(!T){b(e,404,{error:"not found"});return}b(e,200,T)}catch(T){b(e,502,{error:T.message})}return}if(o==="PATCH"&&x){let T=await ue(t);try{let y=typeof w.updateItem=="function"?await w.updateItem(x,T):null;if(!y){b(e,501,{error:"update unsupported"});return}Ka({actor:Ja(t),action:"update",boardId:d,itemId:x,payload:T}),b(e,200,y)}catch(y){b(e,502,{error:y.message})}return}if(o==="POST"&&!x){let T=await ue(t);if(!T.title){b(e,400,{error:"title required"});return}if(!w.capabilities.create||!w.create){b(e,400,{error:`source ${w.type} does not support create`});return}try{let y=await w.create({title:T.title,description:T.description,labels:T.labels,assigneeUsernames:T.assigneeUsernames,milestoneTitle:T.milestoneTitle,projectHint:T.projectHint});Ka({actor:Ja(t),action:"create",boardId:d,itemId:y.id,payload:{title:T.title}}),b(e,201,y)}catch(y){b(e,502,{error:y.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}b(e,404,{error:"not found",path:r})}async function Sm(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let m of t.columns)d[m.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let d of t.columns)k[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&k[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=tn(d,S);if(!m)continue;let x=k[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(k))k[d]=k[d].filter(m=>m.assignee===i);for(let d of Object.keys(k))k[d].sort((m,x)=>{let v=(m.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let g=Object.fromEntries(Object.entries(k).map(([d,m])=>[d,m.length]));return{columns:k,totals:g}}async function Em(t,e,a,n){let r=an(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 Tm(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 Am(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 Gn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ka(t){try{let e=tt(process.cwd(),".agentx");rl(e)||vm(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
19207
|
+
`;xm(tt(e,"board-audit.jsonl"),a)}catch{}}function Ja(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Cm=2e3;async function Im(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",i=g=>{let d=new AbortController,m=setTimeout(()=>d.abort(),Cm),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let w=v.ok?await v.json().catch(()=>{}):void 0;return{ok:w!==void 0,json:async()=>w}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,p,u,f,h,k,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(f&&f.ok){let g=await f.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(k&&k.ok){let g=await k.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,En.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)&&Om(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 Gt=null;function Mm(t){if(Gt)return Gt;let e=tt(process.cwd(),".agentx/wiki");return Gt=kr({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Gt}async function Kt(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 Lm(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function we(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await Kt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var Rm=3e3,$m=6e3,Pm=5*6e4,Ya=new Map,Xt=new Map;function Fe(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Xt.get(a);if(n)return n;let r=(async()=>{let o=await we(t,AbortSignal.timeout(Rm)),s=await Promise.all(o.map(async i=>{let l=await Im(i.url,i.token,AbortSignal.timeout($m),e);return e?l:jm(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Xt.delete(a));return Xt.set(a,r),r}function jm(t,e,a=Date.now()){if(e.reachable&&!e.error)return Ya.set(t,{node:e,at:a}),e;let n=Ya.get(t);return!n||a-n.at>Pm?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Ay(){Ya.clear(),Xt.clear()}function Om(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 Nm(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}
|
|
18895
19208
|
data: ${JSON.stringify(c)}
|
|
18896
19209
|
|
|
18897
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await
|
|
18898
|
-
${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
|
|
19210
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Fe(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 Dm(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await Kt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of k)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(k){b(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:_}=await f.read();if(_)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Hm(t,e,a){let n=na(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new F().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ke(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Bm(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ue(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){b(e,502,{error:c.message||"upstream call failed"})}}async function zm(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 Kt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:c}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){b(t,502,{error:u.message||"upstream fetch failed"})}}async function qm(t,e,a,n,r,o){await Qa(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Qa(t,e,a,n,r){let o={};try{o=await ue(t)??{}}catch{}let s=await ol(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function ol(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 Kt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function sl(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=In(e.keysFile);return{store:()=>{let r=ve();return r?new Zn(r):null},publicKey:()=>Mn(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function il(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Fe(t,n),async nodePost(n,r,o){let s=await ol(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=mt({root:process.cwd()}).items.map(al)}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=at(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(al)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=_e(),p=await ft({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=at(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}var Va=null;function tl(t){return Va?.days!==t&&(Va={days:t,store:new it(process.cwd(),Date.now,t)}),Va.store}function ll(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=il(t);return{store:()=>{let r=ve();return r?new et(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:ln(process.cwd())??void 0},snapshot:()=>Fe(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s),tokenFor:r=>U(t.dashboard,r.replace(/\/+$/,"")),...Fm(t,e,a)}}function Fm(t,e,a){let n=sl(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}
|
|
19211
|
+
${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 Um(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=ll(t);return new Wt({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 Fe(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:Qs(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Wm(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=ve();return a?new et(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Gm(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function al(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 Xm=`
|
|
18899
19212
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
18900
19213
|
|
|
18901
19214
|
Title pattern:
|
|
@@ -18927,10 +19240,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
18927
19240
|
Shape:
|
|
18928
19241
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
18929
19242
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
18930
|
-
`;async function
|
|
19243
|
+
`;async function Km(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):
|
|
18931
19244
|
- ${r.knownLabels.slice(0,60).join(`
|
|
18932
19245
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
18933
|
-
`),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:
|
|
19246
|
+
`),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:Xm}})});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=Jm(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function Jm(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 Vm(t){let e=wm(ym(import.meta.url));return tt(e,t)}async function Ym(t){return bm(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ue(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function cl(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:cl(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 Qm(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await Nt(await dl(r,a.config)))}async function dl(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ca(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=at(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 as(n)}async function Zm(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=f.find(k=>rl(k));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:f}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
|
|
18934
19247
|
|
|
18935
19248
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
|
|
18936
19249
|
`))>=0;){let h=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
|
|
@@ -18938,5 +19251,5 @@ data: ${h.replace(/\n/g," ")}
|
|
|
18938
19251
|
|
|
18939
19252
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
18940
19253
|
|
|
18941
|
-
`)}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
|
|
18942
|
-
//# sourceMappingURL=board-dashboard-
|
|
19254
|
+
`)}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 nl(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function at(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:cl(n),token:n.dashboardToken||n.token}:null}export{Om as applyAttachSessions,Im as fetchDaemonAgents,_m as handleBoardRequest,Ay as resetLiveCaches,we as resolveNodeTargets,Ty as startBoardDashboard,jm as withLastGood};
|
|
19255
|
+
//# sourceMappingURL=board-dashboard-GL6GQ32D.js.map
|