agentix-cli 0.114.0 → 0.114.1
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/{agent-5F4EKGQN.js → agent-NGCPRTBH.js} +2 -2
- package/dist/{board-dashboard-GGW5ZZLT.js → board-dashboard-7B2B564A.js} +244 -244
- package/dist/{board-dashboard-GGW5ZZLT.js.map → board-dashboard-7B2B564A.js.map} +1 -1
- package/dist/{chunk-O2RVUM2B.js → chunk-CSLVHAYV.js} +2 -2
- package/dist/{chunk-QQIWLN3H.js → chunk-DOQ6Y7GZ.js} +5 -5
- package/dist/chunk-DOQ6Y7GZ.js.map +1 -0
- package/dist/{chunk-4COYYJJY.js → chunk-EVB23EHN.js} +2 -2
- package/dist/chunk-JVSTKXMI.js +6 -0
- package/dist/chunk-JVSTKXMI.js.map +1 -0
- package/dist/{chunk-XTO4GRGN.js → chunk-QBWJGDKE.js} +3 -3
- package/dist/{chunk-XX7NXI3Y.js → chunk-TZIPWZY6.js} +2 -2
- package/dist/{chunk-HPY54DU6.js → chunk-UMFFIUU6.js} +2 -2
- package/dist/{chunk-YU5NDKPA.js → chunk-UZB5UO35.js} +2 -2
- package/dist/{chunk-VQM77L54.js → chunk-Z6OPM7EH.js} +2 -2
- package/dist/{chunk-6WNQY6K2.js → chunk-ZXQYOSHP.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-IEMICVO3.js → program-4IMJEMDM.js} +7 -7
- package/dist/{promote-S7SKOKX2.js → promote-4VTXBVUC.js} +2 -2
- package/dist/{query-GOBQ3GL5.js → query-B32UDQJS.js} +2 -2
- package/dist/{registry-HUJEORRW.js → registry-GY4X2GZX.js} +2 -2
- package/dist/{wiki-FZHSX4K3.js → wiki-LVYHDK2R.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-ILGLEA3I.js +0 -6
- package/dist/chunk-ILGLEA3I.js.map +0 -1
- package/dist/chunk-QQIWLN3H.js.map +0 -1
- /package/dist/{agent-5F4EKGQN.js.map → agent-NGCPRTBH.js.map} +0 -0
- /package/dist/{chunk-O2RVUM2B.js.map → chunk-CSLVHAYV.js.map} +0 -0
- /package/dist/{chunk-4COYYJJY.js.map → chunk-EVB23EHN.js.map} +0 -0
- /package/dist/{chunk-XTO4GRGN.js.map → chunk-QBWJGDKE.js.map} +0 -0
- /package/dist/{chunk-XX7NXI3Y.js.map → chunk-TZIPWZY6.js.map} +0 -0
- /package/dist/{chunk-HPY54DU6.js.map → chunk-UMFFIUU6.js.map} +0 -0
- /package/dist/{chunk-YU5NDKPA.js.map → chunk-UZB5UO35.js.map} +0 -0
- /package/dist/{chunk-VQM77L54.js.map → chunk-Z6OPM7EH.js.map} +0 -0
- /package/dist/{chunk-6WNQY6K2.js.map → chunk-ZXQYOSHP.js.map} +0 -0
- /package/dist/{program-IEMICVO3.js.map → program-4IMJEMDM.js.map} +0 -0
- /package/dist/{promote-S7SKOKX2.js.map → promote-4VTXBVUC.js.map} +0 -0
- /package/dist/{query-GOBQ3GL5.js.map → query-B32UDQJS.js.map} +0 -0
- /package/dist/{registry-HUJEORRW.js.map → registry-GY4X2GZX.js.map} +0 -0
- /package/dist/{wiki-FZHSX4K3.js.map → wiki-LVYHDK2R.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{A as
|
|
1
|
+
import{A as Vr,B as Yr,C as Qr,a as C,b as jr,c as Or,d as Nr,e as Dr,f as Ie,g as Hr,h as Br,i as Ot,k as zr,q as qr,r as Fr,s as Ur,t as Wr,u as Gr,y as Xr,z as Kr}from"./chunk-UMFFIUU6.js";import{a as Jr}from"./chunk-4FU4BFCH.js";import{a as $r}from"./chunk-4VDA4UM7.js";import{a as Ue,b as q,c as I,h as ue,i as $t,j as se,k as K,l as jt,m as Lr,n as Rr,o as Pr}from"./chunk-SCJ5ZXEN.js";import{a as Mr}from"./chunk-2NYP4OQU.js";import{a as pe,b as Ir}from"./chunk-JWDJMFU6.js";import{A as At,Aa as yr,B as sr,Ba as wr,C as qe,D as Ct,E as ir,F as cr,I as dr,J as pr,Ja as kr,K as ur,La as Ce,Qa as _r,R as W,S as mr,Sa as Fe,T as fr,Ta as It,Ua as Mt,Va as Lt,Wa as Rt,Xa as Sr,Ya as Er,Za as Tr,_a as Pt,a as Yn,ab as Ar,c as wt,d as wa,db as Cr,e as Qn,i as kt,l as tt,n as Zn,w as St,x as or,xa as br,y as Et,z as Tt,za as vr}from"./chunk-ZXQYOSHP.js";import{g as Jn,h as Vn}from"./chunk-VTWSW4KB.js";import{p as er,t as tr}from"./chunk-S2GAEH2F.js";import"./chunk-GTJIKXDB.js";import{a as lr,b as H,c as hr,d as gr,h as xr}from"./chunk-BGG3ZSMW.js";import"./chunk-EVB23EHN.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ae,d as ar,e as ka}from"./chunk-ACFQBLPX.js";import{g as _t}from"./chunk-LQE73AZR.js";import{b as nr,c as rr}from"./chunk-2D3RYIDU.js";import"./chunk-JIT5GPTX.js";import{a as qn,f as Fn,g as va,h as ya,l as Un,m as Wn,n as Gn,u as bt,v as vt,w as yt,x as de,y as Kn}from"./chunk-J3GXZQXY.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import"./chunk-SHEUCITK.js";import"./chunk-Y4CYQV7G.js";import"./chunk-YLKCFW2R.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-VGI4EZTP.js";import{a as Xn}from"./chunk-CYKPDILL.js";import"./chunk-Z6OPM7EH.js";import"./chunk-TZIPWZY6.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as zn}from"./chunk-JVSTKXMI.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import{A as Kc,H as On,K as xa,N as Nn,P as gt,Q as Dn,S as Hn,U as Bn,Y as ba,a as In,b as Mn,c as Wc,ja as X,ma as xt,u as mt,v as Gc,w as ha,x as ga}from"./chunk-Y5HBYSJW.js";import{d as $n,e as Xc,f as ht,n as jn}from"./chunk-UIBUZ2N3.js";import{a as Ln,b as ft,c as fa,d as Rn,h as Pn}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function _a(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 Zr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:_a(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ie={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',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"/>'},Me=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Nt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Me(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function eo(t={}){return I({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>
|
|
@@ -21,22 +21,22 @@ import{A as Jr,B as Vr,C as Yr,a as C,b as $r,c as jr,d as Or,e as Nr,f as Ie,g
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${Nt(ie.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
|
+
${Nt(ie.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
|
+
${Nt(ie.pulse,"In motion","run-count")}
|
|
35
35
|
<div id="running" class="bf-col"></div>
|
|
36
36
|
</aside>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
${
|
|
39
|
+
${Nt(ie.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
41
|
<div class="bf-search">${Me(ie.search)}
|
|
42
42
|
<input id="search" type="search" placeholder="Search sessions…" aria-label="Search sessions">
|
|
@@ -85,7 +85,7 @@ ${Ot(ie.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:Jc,scripts:`<script>${q({decayOf:_a,rankByDecay:Zr})}const ICON = ${JSON.stringify(ie)};${Vc}</script>`})}var Jc=`
|
|
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
|
+
}`,Vc=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 Sa(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),d=r[r.length-1];d&&l.startedAt-d.to<=e?(d.to=Math.max(d.to,c),d.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let d=1;d<r.length;d++){let p=r[d].from-r[d-1].to;p<c&&(c=p,l=d)}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 Ea(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 to(t,e=[],a){let{bands:n,gaps:r}=Sa(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(b=>l.startedAt>=b.from&&l.startedAt<=b.to);if(c===-1)continue;let d=n[c],p=d.to-d.from||1,m=(l.startedAt-d.from)/p*100,f=Math.min(Math.max((l.durationMs||0)/p*100,1.2),100-m),_=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};_.runs.push({...l,band:c,track:0,left:m,width:f,marks:o.get(l.id)??[]}),s.set(l.laneKey,_)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,d)=>Ea(l.runs.filter(p=>p.band===d))),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 Yc}from"crypto";import{readFileSync as Qc,statSync as Zc}from"fs";import{resolve as ed,dirname as td}from"path";import{fileURLToPath as ad}from"url";var ao=new Map;function Dt(t){let e=ao.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=td(ad(import.meta.url)),r=ed(n,"web",t),o=Zc(r),s=o.size<8e6?Yc("sha1").update(Qc(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return ao.set(t,a),a}var le={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"/>'},Ht=(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>",nd=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],no={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 ro(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return I({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">${no[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",le.timeline],["map","Map",le.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",le.timeline],["map","Map",le.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Ht(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":""}>${Ht(le.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
|
+
${nd.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ht(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">${Ht(le.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="${Dt("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:rd,scripts:`<script>${q({computeBands:Sa,packTracks:Ea,buildTimeline:to})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(no)};${od}</script>`})}var rd=`
|
|
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
|
+
`,od=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 oo(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return I({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:sd,scripts:`<script src="${Dt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var sd=`
|
|
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,11 +1045,11 @@ 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,...
|
|
1050
|
-
WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${d.map(()=>"?").join(",")})`).all(e,...d.map(
|
|
1048
|
+
`;import{createServer as xh}from"http";import{appendFileSync as bh,existsSync as Oc,mkdirSync as vh}from"fs";import{readFile as yh}from"fs/promises";import{fileURLToPath as wh}from"url";import{dirname as kh,resolve as dt}from"path";Nn();function We(t,e){if(!t)return"absent";let a=ar(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Le=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 Bt(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=so(t.headers["sec-fetch-mode"]),n.site=so(t.headers["sec-fetch-site"]),n}function so(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as cd}from"zlib";var id=[[[441,393],[600,393],[614,396],[625,401],[634,410],[1028,940],[846,940],[833,937],[823,931],[818,925],[440,414],[435,406],[436,398]],[[893,393],[1079,393],[861,653],[771,535]],[[413,439],[510,574],[282,874],[100,874]],[[451,709],[610,709],[615,712],[698,824],[599,939],[447,719],[446,713]]],ke={x:100,y:393,width:979,height:547},Ta="#1a1a18",Aa="#ffffff",io=Math.hypot(ke.width,ke.height)/2/ke.width,zt={full:.74,safe:.37/io,android:.29/io,mac:.6};function Ca(t,e){let a=t*e/ke.width,n=t/2-(ke.x+ke.width/2)*a,r=t/2-(ke.y+ke.height/2)*a;return id.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function ld(t,e){let a=n=>String(Math.round(n*100)/100);return Ca(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function lo(t=64,e=zt.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${Aa}"/><path fill="${Ta}" d="${ld(t,e)}"/></svg>`}var dd=xo(Ta),co=xo(Aa),po=new Map;function Ge(t){let e=po.get(t);return e||(e=go({size:t,width:zt.safe,background:"square"}),po.set(t,e)),e}var pd=lo();function ho(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:pd}:t==="/favicon.ico"?{type:"image/png",body:mo(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:mo(180)}:null}var uo=new Map;function mo(t){let e=uo.get(t);return e||(e=go({size:t,width:zt.full,background:"square"}),uo.set(t,e)),e}function go(t){let{size:e}=t,a=t.background==="mac"?fo(e,[ud(e)]):null,n=fo(e,Ca(e,t.width)),r=1+e*4,o=Buffer.alloc(r*e);for(let s=0;s<e;s++)for(let i=0;i<e;i++){let l=s*e+i,c=n[l],d=s*r+1+i*4;for(let p=0;p<3;p++)o[d+p]=Math.round(co[p]+(dd[p]-co[p])*c);o[d+3]=Math.round(255*(a?a[l]:1))}return md(e,o)}function ud(t){let e=t/1024,a=100*e,n=924*e,r=185*e,o=[],s=[[n-r,a+r,-90],[n-r,n-r,0],[a+r,n-r,90],[a+r,a+r,180]];for(let[i,l,c]of s)for(let d=0;d<=12;d++){let p=(c+90*d/12)*Math.PI/180;o.push([i+r*Math.cos(p),l+r*Math.sin(p)])}return o}var Ia=8;function fo(t,e){let a=new Float32Array(t*t),n=[];for(let o of e)for(let s=0;s<o.length;s++){let[i,l]=o[s],[c,d]=o[(s+1)%o.length];l!==d&&n.push([i,l,c,d])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Ia;s++){let i=o+(s+.5)/Ia;r.length=0;for(let[l,c,d,p]of n)(i>=c&&i<p||i>=p&&i<c)&&r.push(l+(i-c)*(d-l)/(p-c));r.sort((l,c)=>l-c);for(let l=0;l+1<r.length;l+=2){let c=Math.max(0,r[l]),d=Math.min(t,r[l+1]);for(let p=Math.floor(c);p<d;p++){let m=Math.min(p+1,d)-Math.max(p,c);m>0&&(a[o*t+p]+=m/Ia)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function xo(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function md(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=6,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Ma("IHDR",a),Ma("IDAT",cd(e)),Ma("IEND",Buffer.alloc(0))])}function Ma(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(hd(n)),Buffer.concat([a,n,r])}var fd=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 hd(t){let e=4294967295;for(let a of t)e=fd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}xt();Kc();var qt=7,gd=["waiting_owner","needs_attention"],xd={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Xe(t,e){let a=t.toLowerCase().split("@")[0],n=xd[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 bo(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 vo(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(b=>b.name==="person"),i=b=>({id:b.id,state:b.state,agentId:b.agent_id,text:b.text,channel:b.channel,chatId:b.chat_id,createdAt:b.created_at,updatedAt:b.updated_at,closedAt:b.closed_at??null,question:b.question??null,attentionReason:b.attention_reason??null,evidence:b.evidence??null,where:{label:Xe(b.channel,b.chat_id),url:a.linkFor?.(b.channel,b.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ha.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...ha).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ga.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1049
|
+
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...ga,n-qt*864e5).map(i):[],d=[];try{d=Ot(t,e,50).filter(b=>b.startedAt>=n-qt*864e5)}catch{}let p=new Map;if(s&&d.length){let b=t.prepare(`SELECT l.ref, r.id, r.state, r.evidence FROM request_links l JOIN requests r ON r.id = l.request_id
|
|
1050
|
+
WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${d.map(()=>"?").join(",")})`).all(e,...d.map(S=>S.taskId));for(let S of b)p.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=d.map(b=>({...b,where:b.channel?{label:Xe(b.channel,b.chatId??""),url:a.linkFor?.(b.channel,b.chatId??"")??null}:null,request:p.get(b.taskId)??null})),f=new Set(m.map(b=>b.request?.id).filter(Boolean)),_=[...l.filter(b=>!gd.includes(b.state)),...c].filter(b=>!f.has(b.id));return{open:l,recent:c,runs:m,other:_}}ba();Xc();var yo={waiting:0,yours:0,ahead:null};function wo(t,e,a={}){let n=$n(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,c=s.get(l)??0;s.set(l,c+1);let d=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};d.waiting++,i.person===e&&(d.yours++,d.ahead===null&&(d.ahead=c),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Xe(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:c})),r.set(i.agentId,d)}return{byAgent:r,mine:o}}var bd=4e3;function ko(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
|
|
1051
1051
|
WHERE person = ? AND started_at >= ? AND (channel IS NULL OR channel != 'a2a')
|
|
1052
|
-
GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-
|
|
1052
|
+
GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-qt*864e5).map(r=>r.agent_id)}function _o(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(gt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let c=n.queue?.get(l)??yo,d=s.get(l),p=d??i.get(l);if(!p)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:c};let m=o(p.person??null),f=p.status==="error"||p.status==="timeout",_=d?"working":f&&m==="you"?"blocked":"free",b=m==="you"&&p.channel!=="a2a",S=b&&p.channel;return{agentId:l,state:_,by:m,at:d?p.started_at:p.finished_at??p.started_at,text:d||b?p.message_preview??null:null,fullText:b&&d&&String(p.original_message??p.message_preview??"").slice(0,bd)||null,where:S?{label:Xe(p.channel,p.chat_id??""),url:n.linkFor?.(p.channel,p.chat_id??"")??null}:null,queue:c}})}function So(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Eo(t,e){return!t||e-t>=3e4||t>e}function Ft(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 To(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}function Ut(t,e,a,n){return t?e?{text:"Can't reach the server. "+(n?"Showing what was last loaded. ":"")+"Trying again every "+a+" seconds.",retry:!0}:{text:"Offline. Showing what was last loaded; live state needs a connection.",retry:!1}:null}function Wt(t){return String(t??"").replace(/```[\w-]*|`/g,"").replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^[ \t]*(?:#{1,6}|>+|[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm,"").replace(/\*\*|~~/g,"").replace(/(^|[\s(])\*(\S(?:[^*\n]*\S)?)\*(?=[\s).,;:!?]|$)/gm,"$1$2").replace(/\s+/g," ").trim()}function Ao(t){let e=t.by==="you"?"you":t.by==="owner"?"the owner":t.by?"someone else":null;if(t.state==="working"){let a=t.queue||{waiting:0,yours:0,ahead:null},n=a.ahead||0,r;return a.yours>0?r=(a.yours===1?"Your message is in line":a.yours+" messages of yours are in line")+(n===0?a.yours===1?": it runs when this ends.":": the first runs when this ends.":", "+n+(n===1?" message":" messages")+" ahead of "+(a.yours===1?"it.":"the first.")):a.waiting>0?r=a.waiting+(a.waiting===1?" message waits":" messages wait")+" in line. A new one from you waits behind "+(a.waiting===1?"it.":"them."):r=t.by==="you"?"Busy. A new message waits in line until this ends.":"A message you send now waits in line until this ends.",t.by==="you"?{label:"Working",tone:"work",what:t.text,by:e,hint:r}:{label:"Working",tone:"work",what:t.text||"Busy with someone else's task",by:e,hint:r}}return t.state==="blocked"?{label:"Blocked",tone:"stuck",what:t.text?"Stopped on: "+t.text:null,by:e,hint:"It stopped before finishing. It needs a person."}:{label:"Free",tone:"free",what:t.by==="you"&&t.text?"Finished: "+t.text:null,by:t.by==="you"?e:null,hint:"Free. Ready for your next message."}}function Co(t){let e=t.request?t.request.state:"";return e==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:e==="needs_attention"?{label:"Stuck",tone:"stuck"}:t.status==="queued"?{label:"In line",tone:"wait"}:t.status==="in-flight"?{label:"Running",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function Io(t){return t==="in_progress"?{label:"In progress",tone:"work"}:t==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:t==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:t==="needs_attention"?{label:"Stuck",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Declined",tone:"off"}:t==="dropped"?{label:"Dropped",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function Mo(t,e){if(!t.length&&!e)return"Nothing sent yet.";let a=t.slice(0,4).map(function(n){return n.state==="working"?n.agentId+(n.by==="you"?" is working on your task.":" is busy with someone else's task."):n.state==="blocked"?n.agentId+" stopped on your task.":n.agentId+" is free."});return t.length>4&&a.push(t.length-4+" more below."),a.join(" ")||"Nothing running now."}function Lo(t,e){if(!t)return[];let a={};return t.forEach(function(n){a[n.agentId]=n.state}),e.filter(function(n){return n.state==="free"&&a[n.agentId]==="working"}).map(function(n){return n.agentId})}var Ro=`
|
|
1053
1053
|
(function () {
|
|
1054
1054
|
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1055
1055
|
var who = document.getElementById('who');
|
|
@@ -1235,7 +1235,7 @@ body { margin: 0; overflow: hidden; }
|
|
|
1235
1235
|
showConn();
|
|
1236
1236
|
load();
|
|
1237
1237
|
})();
|
|
1238
|
-
`;var
|
|
1238
|
+
`;var Gt=`
|
|
1239
1239
|
:root { --link: var(--ax-blue-d); --ring: var(--ax-blue); --tick: var(--ax-green-d); }
|
|
1240
1240
|
[data-theme="dark"] { --link: var(--ax-blue); --tick: var(--ax-green); }
|
|
1241
1241
|
* { box-sizing: border-box; }
|
|
@@ -1263,7 +1263,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1263
1263
|
.card h2 { font-size: 24px; font-weight: 700; line-height: 1.2; margin-bottom: 8px; }
|
|
1264
1264
|
.card p { color: var(--ax-text-2); }
|
|
1265
1265
|
.help { margin-top: 20px; font-size: 14px; color: var(--ax-text-2); }
|
|
1266
|
-
`,
|
|
1266
|
+
`,Xt=`
|
|
1267
1267
|
.icon-btn { min-width: 44px; min-height: 44px; font-size: 20px; line-height: 1; border: var(--ax-border-w) solid var(--ax-border-2); border-radius: var(--ax-radius-pill); background: var(--ax-surface); color: var(--ax-text); cursor: pointer; }
|
|
1268
1268
|
.strip, .install { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 10px 20px; font-size: 14px; background: var(--ax-amber-t); color: var(--ax-amber-ink); border-bottom: var(--ax-border-w) solid var(--ax-amber-e); }
|
|
1269
1269
|
.strip[hidden], .install[hidden] { display: none; }
|
|
@@ -1338,7 +1338,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1338
1338
|
.blank { padding: 28px 24px; border: var(--ax-border-w) dashed var(--ax-border-2); border-radius: var(--ax-radius-lg); }
|
|
1339
1339
|
.blank p + p { margin-top: 8px; color: var(--ax-text-2); }
|
|
1340
1340
|
.foot { margin-top: 28px; font-size: 14px; color: var(--ax-text-2); }
|
|
1341
|
-
`,
|
|
1341
|
+
`,Po=`
|
|
1342
1342
|
.pair-form { display: grid; gap: 8px; margin-top: 20px; }
|
|
1343
1343
|
.pair-form label { font-weight: 600; margin-top: 8px; }
|
|
1344
1344
|
.pair-form input { width: 100%; min-height: 52px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: var(--ax-border-w) solid var(--ax-text-2); border-radius: var(--ax-radius-sm); }
|
|
@@ -1350,11 +1350,11 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1350
1350
|
.card .pair-msg.bad { color: var(--ax-red-ink); }
|
|
1351
1351
|
[data-theme="dark"] .card .pair-msg.bad { color: var(--ax-red); }
|
|
1352
1352
|
.card .pair-offline { padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: 14px; background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
|
|
1353
|
-
|
|
1353
|
+
`,$o=`
|
|
1354
1354
|
.pulse { display: inline-block; width: 12px; height: 12px; margin-right: 10px; border-radius: 50%; border: 3px solid var(--ax-amber-ink); box-sizing: border-box; animation: breathe 2.4s ease-in-out infinite; }
|
|
1355
1355
|
@keyframes breathe { 50% { opacity: 0.35; } }
|
|
1356
1356
|
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }
|
|
1357
|
-
`;var
|
|
1357
|
+
`;var vd="<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 La(t,e={}){return`<meta charset="utf-8">
|
|
1358
1358
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1359
1359
|
<meta name="theme-color" content="#2979FF">
|
|
1360
1360
|
<meta name="referrer" content="no-referrer">
|
|
@@ -1364,8 +1364,8 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1364
1364
|
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1365
1365
|
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1366
1366
|
<title>${t}</title>
|
|
1367
|
-
${
|
|
1368
|
-
<style>${
|
|
1367
|
+
${vd}
|
|
1368
|
+
<style>${Ue}${Gt}</style>`}function jo(){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:"#FFFFFF",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 Oo=`
|
|
1369
1369
|
var CACHE = 'agentx-member-v1';
|
|
1370
1370
|
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
1371
1371
|
self.addEventListener('install', function (e) {
|
|
@@ -1395,14 +1395,14 @@ self.addEventListener('fetch', function (e) {
|
|
|
1395
1395
|
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
1396
1396
|
}
|
|
1397
1397
|
});
|
|
1398
|
-
`;function
|
|
1398
|
+
`;function Ra(t,e="",a="My work"){return`<header class="bar">
|
|
1399
1399
|
<img class="mark" src="/member/icon-192.png" alt="" width="36" height="36">
|
|
1400
1400
|
<div class="grow"><h1>${a}</h1><p id="who" class="who">${t}</p></div>${e}
|
|
1401
|
-
</header>`}var
|
|
1401
|
+
</header>`}var Pa=La,$a=Ra;function No(t){return`<ol class="steps" aria-label="Steps">${["Type the code","The owner says yes","Your work opens"].map((a,n)=>n<t?`<li class="done"><span class="sr">Done: </span>${a}</li>`:n===t?`<li class="now" aria-current="step">${a}</li>`:`<li>${a}</li>`).join("")}</ol>`}function Do(){return`<!doctype html>
|
|
1402
1402
|
<html lang="en">
|
|
1403
|
-
<head>${
|
|
1403
|
+
<head>${Pa("My work \xB7 AgentX")}<style>${Xt}</style></head>
|
|
1404
1404
|
<body>
|
|
1405
|
-
${
|
|
1405
|
+
${$a("Connecting\u2026",`
|
|
1406
1406
|
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`)}
|
|
1407
1407
|
<p id="offline" class="strip" role="status" hidden><span id="offline-text"></span><button type="button" id="retry" hidden>Try now</button></p>
|
|
1408
1408
|
<p id="install" class="install" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</p>
|
|
@@ -1413,15 +1413,15 @@ ${Pa("Connecting\u2026",`
|
|
|
1413
1413
|
<section aria-labelledby="h-sent"><h2 id="h-sent">What you sent <span class="n">(last 7 days)</span></h2><ul id="sent" class="rows"></ul></section>
|
|
1414
1414
|
<p id="updated" class="foot"></p>
|
|
1415
1415
|
</main>
|
|
1416
|
-
<script>${q({workState:
|
|
1416
|
+
<script>${q({workState:yd,ageText:ja,connectionNote:Ut,plainPreview:Wt,agentLine:Ao,sentState:Co,requestState:Io,summaryLine:Mo,freedAgents:Lo})}${Ro}</script>
|
|
1417
1417
|
</body>
|
|
1418
|
-
</html>`}function
|
|
1418
|
+
</html>`}function Ho(){return`<!doctype html>
|
|
1419
1419
|
<html lang="en">
|
|
1420
|
-
<head>${
|
|
1420
|
+
<head>${Pa("Pair this machine \xB7 AgentX")}<style>${Po}</style></head>
|
|
1421
1421
|
<body>
|
|
1422
|
-
${
|
|
1422
|
+
${$a("This machine is not paired yet")}
|
|
1423
1423
|
<main class="narrow">
|
|
1424
|
-
${
|
|
1424
|
+
${No(0)}
|
|
1425
1425
|
<div class="card">
|
|
1426
1426
|
<h2>Pair this machine</h2>
|
|
1427
1427
|
<p>The owner sent you a pairing code. Type it with a name for this machine. The owner then approves the machine, and your work page opens.</p>
|
|
@@ -1438,24 +1438,24 @@ ${Pa("This machine is not paired yet")}
|
|
|
1438
1438
|
<p class="help">No code? Ask the person who invited you for one. A code works once, for 10 minutes.</p>
|
|
1439
1439
|
</div>
|
|
1440
1440
|
</main>
|
|
1441
|
-
<script>${q({formatPairInput:
|
|
1441
|
+
<script>${q({formatPairInput:Ft})}${wd}</script>
|
|
1442
1442
|
</body>
|
|
1443
|
-
</html>`}function
|
|
1443
|
+
</html>`}function Bo(){return`<!doctype html>
|
|
1444
1444
|
<html lang="en">
|
|
1445
|
-
<head>${
|
|
1445
|
+
<head>${Pa("Waiting for the owner \xB7 AgentX")}<style>${$o}</style></head>
|
|
1446
1446
|
<body>
|
|
1447
|
-
${
|
|
1447
|
+
${$a("This machine is paired")}
|
|
1448
1448
|
<main class="narrow">
|
|
1449
|
-
${
|
|
1449
|
+
${No(1)}
|
|
1450
1450
|
<div class="card">
|
|
1451
1451
|
<h2><span class="pulse" aria-hidden="true"></span>Waiting for the owner</h2>
|
|
1452
1452
|
<p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens your work by itself when they do.</p>
|
|
1453
1453
|
<p class="help">If they say no, this page asks for a new code.</p>
|
|
1454
1454
|
</div>
|
|
1455
1455
|
</main>
|
|
1456
|
-
<script>${
|
|
1456
|
+
<script>${kd}</script>
|
|
1457
1457
|
</body>
|
|
1458
|
-
</html>`}function
|
|
1458
|
+
</html>`}function yd(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 ja(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 wd=`
|
|
1459
1459
|
(function () {
|
|
1460
1460
|
var form = document.getElementById('pair-form');
|
|
1461
1461
|
var machine = document.getElementById('machine');
|
|
@@ -1499,7 +1499,7 @@ ${Pa("This machine is paired")}
|
|
|
1499
1499
|
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1500
1500
|
});
|
|
1501
1501
|
})();
|
|
1502
|
-
`,
|
|
1502
|
+
`,kd=`
|
|
1503
1503
|
(function () {
|
|
1504
1504
|
var msg = document.getElementById('msg');
|
|
1505
1505
|
function check() {
|
|
@@ -1510,16 +1510,16 @@ ${Pa("This machine is paired")}
|
|
|
1510
1510
|
}
|
|
1511
1511
|
setInterval(check, 5000);
|
|
1512
1512
|
})();
|
|
1513
|
-
`;function
|
|
1513
|
+
`;function zo(t){let e=t.request?t.request.state:"";return e==="waiting_owner"||e==="waiting_other"?{label:"Waiting on us",tone:"wait"}:e==="needs_attention"?{label:"Needs a look from us",tone:"stuck"}:t.status==="in-flight"?{label:"Being worked on",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped, we will look at it",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function qo(t){return t==="in_progress"?{label:"Being worked on",tone:"work"}:t==="waiting_owner"||t==="waiting_other"?{label:"Waiting on us",tone:"wait"}:t==="needs_attention"?{label:"Needs a look from us",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Not taken on",tone:"off"}:t==="dropped"?{label:"Set aside",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function Fo(t){if(!t.length)return"Nothing asked for yet.";let e=0,a=0,n=0,r=0;for(let s=0;s<t.length;s++)t[s]==="work"?e++:t[s]==="wait"?a++:t[s]==="stuck"?n++:t[s]==="done"&&r++;let o=[];return e&&o.push(e===1?"1 request is being worked on for you.":e+" requests are being worked on for you."),a&&o.push(a===1?"1 is waiting on us.":a+" are waiting on us."),n&&o.push(n===1?"1 needs a look from us.":n+" need a look from us."),o.length?o.join(" "):r?"Nothing in progress right now. "+(r===1?"1 request finished":r+" requests finished")+" this week.":"Nothing in progress right now."}var Oa="/member/client.webmanifest",at="Your project";function Uo(){return JSON.stringify({id:"/member?client",name:`${at} \xB7 AgentX`,short_name:at,description:"What you asked 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 _d=`
|
|
1514
1514
|
.about { margin-top: 32px; padding: 16px 20px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-lg); background: var(--ax-surface); font-size: 15px; color: var(--ax-text-2); }
|
|
1515
1515
|
.wrap .about h2 { margin: 0 0 6px; }
|
|
1516
1516
|
.about p + p { margin-top: 6px; }
|
|
1517
|
-
`;function
|
|
1517
|
+
`;function Wo(){return`<!doctype html>
|
|
1518
1518
|
<html lang="en">
|
|
1519
|
-
<head>${
|
|
1519
|
+
<head>${La(`${at} \xB7 AgentX`,{manifest:Oa,appTitle:at})}<style>${Ue}${Gt}${Xt}${_d}</style></head>
|
|
1520
1520
|
<body>
|
|
1521
|
-
${
|
|
1522
|
-
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,
|
|
1521
|
+
${Ra("Connecting\u2026",`
|
|
1522
|
+
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,at)}
|
|
1523
1523
|
<p id="offline" class="strip" role="status" hidden><span id="offline-text"></span><button type="button" id="retry" hidden>Try now</button></p>
|
|
1524
1524
|
<p id="install" class="install" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</p>
|
|
1525
1525
|
<main class="wrap">
|
|
@@ -1531,9 +1531,9 @@ ${La("Connecting\u2026",`
|
|
|
1531
1531
|
</section>
|
|
1532
1532
|
<p id="updated" class="foot"></p>
|
|
1533
1533
|
</main>
|
|
1534
|
-
<script>${q({ageText
|
|
1534
|
+
<script>${q({ageText:ja,connectionNote:Ut,plainPreview:Wt,clientSentState:zo,clientRequestState:qo,clientSummary:Fo})}${Sd}</script>
|
|
1535
1535
|
</body>
|
|
1536
|
-
</html>`}var
|
|
1536
|
+
</html>`}var Sd=`
|
|
1537
1537
|
(function () {
|
|
1538
1538
|
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1539
1539
|
var who = document.getElementById('who');
|
|
@@ -1640,10 +1640,10 @@ ${La("Connecting\u2026",`
|
|
|
1640
1640
|
showConn();
|
|
1641
1641
|
load();
|
|
1642
1642
|
})();
|
|
1643
|
-
`;var Xt="agentx_member",_d=90*86400,Sd=new At,Ko=t=>t.replace(/^\[app\]/,"[member]"),Ed=new Le(t=>console.log(Ko(t))),Wo=new WeakMap;function Td(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Ed;let e=Wo.get(t.log);return e||Wo.set(t.log,e=new Le(a=>t.log(Ko(a)))),e}var Go=null;function at(t,e=X){try{return Go=e().people}catch{return Go??t}}async function Jo(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new G(r.root),s=r.members??new xt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new kt(r.root),limiter:r.pairLimiter??Sd,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return ge(e,200,"application/manifest+json",$o());if(a===ja)return ge(e,200,"application/manifest+json",Fo());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),ge(e,200,"text/javascript; charset=utf-8",jo);if(a==="/member/icon-192.png")return ge(e,200,"image/png",We(192),"public, max-age=86400");if(a==="/member/icon-512.png")return ge(e,200,"image/png",We(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await qr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Xo(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),_e(e,p.status,p.body)}let l=Ur(Cd(t),i,zr(t));if(!l.ok){if(l.status===401){let p=Oa(t);return Td(r).record(a.slice(0,120),Ht(t,Ue(Na(t,Xt),o),p?Ue(p,o):null)),a==="/member"?ge(e,401,"text/html; charset=utf-8",Do()):_e(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?ge(e,202,"text/html; charset=utf-8",Ho()):_e(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId),d=c?.role==="client";if(n==="GET"&&a==="/member"){let p=Na(t,Xt);return p&&!Oa(t)&&e.setHeader("Set-Cookie",Xo(p)),ge(e,200,"text/html; charset=utf-8",d?Uo():No())}if(n==="GET"&&a==="/api/member/me")return _e(e,200,{person:l.personId,name:c?.name??l.personId,role:c?.role??"member",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;if(!p)return _e(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),f=bo(p,l.personId,{now:m,linkFor:r.linkFor}),S=(g,x)=>{let u=x instanceof Error?x.message:String(x);/no such table/i.test(u)||r.log?.(`[member] ${g} failed: ${u}`)},b={byAgent:new Map,mine:[]};try{b=yo(p,l.personId,{linkFor:r.linkFor})}catch(g){S("the line",g)}let E=[];if(d)return _e(e,200,{...Ad(f),agents:E});try{let g=wo(p,c??{id:l.personId},m);E=ko(p,l.personId,g,{people:r.people(),linkFor:r.linkFor,queue:b.byAgent})}catch(g){S("agent cards",g)}return _e(e,200,{...f,agents:E,queued:b.mine})}return _e(e,404,{error:"not found"})}function Ad(t){let e=a=>a.map(({agentId:n,...r})=>r);return{...t,open:e(t.open),recent:e(t.recent),runs:e(t.runs),other:e(t.other)}}function Xo(t){return`${Xt}=${t}; Path=/; Max-Age=${_d}; HttpOnly; Secure; SameSite=Lax`}function Cd(t){return Oa(t)??Na(t,Xt)}function Oa(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Na(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function ge(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function _e(t,e,a){return ge(t,e,"application/json",JSON.stringify(a))}Fc();var Vo='/*! 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 Jt,readFileSync as rs,writeFileSync as os,rmSync as vx,mkdirSync as $d,copyFileSync as jd,readdirSync as Od}from"fs";import{resolve as Xe}from"path";Uc();function Qo(t){let e=ut.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ut.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 Kt(t){return C(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=ut.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 Yo=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Zo(t){return Kt(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 es(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Kt((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:Yo(t?.chats),senders:Yo(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 ts(t){let e=String(t?.id??"");return Kt(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 as(t){let e=String(t?.id??"");return Kt(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}"`})}gt();var me={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 ns(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ue({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.`})+Pt([{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 I({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Md()+Mr,css:Rd,scripts:`${e}<script>${Lr}
|
|
1644
|
-
${
|
|
1645
|
-
${
|
|
1646
|
-
${
|
|
1643
|
+
`;var Kt="agentx_member",Ed=90*86400,Td=new Ct,Jo=t=>t.replace(/^\[app\]/,"[member]"),Ad=new Le(t=>console.log(Jo(t))),Go=new WeakMap;function Cd(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Ad;let e=Go.get(t.log);return e||Go.set(t.log,e=new Le(a=>t.log(Jo(a)))),e}var Xo=null;function nt(t,e=X){try{return Xo=e().people}catch{return Xo??t}}async function Vo(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new G(r.root),s=r.members??new bt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new _t(r.root),limiter:r.pairLimiter??Td,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return ge(e,200,"application/manifest+json",jo());if(a===Oa)return ge(e,200,"application/manifest+json",Uo());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),ge(e,200,"text/javascript; charset=utf-8",Oo);if(a==="/member/icon-192.png")return ge(e,200,"image/png",Ge(192),"public, max-age=86400");if(a==="/member/icon-512.png")return ge(e,200,"image/png",Ge(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Fr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Ko(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),_e(e,p.status,p.body)}let l=Wr(Md(t),i,qr(t));if(!l.ok){if(l.status===401){let p=Na(t);return Cd(r).record(a.slice(0,120),Bt(t,We(Da(t,Kt),o),p?We(p,o):null)),a==="/member"?ge(e,401,"text/html; charset=utf-8",Ho()):_e(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?ge(e,202,"text/html; charset=utf-8",Bo()):_e(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId),d=c?.role==="client";if(n==="GET"&&a==="/member"){let p=Da(t,Kt);return p&&!Na(t)&&e.setHeader("Set-Cookie",Ko(p)),ge(e,200,"text/html; charset=utf-8",d?Wo():Do())}if(n==="GET"&&a==="/api/member/me")return _e(e,200,{person:l.personId,name:c?.name??l.personId,role:c?.role??"member",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;if(!p)return _e(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),f=vo(p,l.personId,{now:m,linkFor:r.linkFor}),_=(g,x)=>{let u=x instanceof Error?x.message:String(x);/no such table/i.test(u)||r.log?.(`[member] ${g} failed: ${u}`)},b={byAgent:new Map,mine:[]};try{b=wo(p,l.personId,{linkFor:r.linkFor})}catch(g){_("the line",g)}let S=[];if(d)return _e(e,200,{...Id(f),agents:S});try{let g=ko(p,c??{id:l.personId},m);S=_o(p,l.personId,g,{people:r.people(),linkFor:r.linkFor,queue:b.byAgent})}catch(g){_("agent cards",g)}return _e(e,200,{...f,agents:S,queued:b.mine})}return _e(e,404,{error:"not found"})}function Id(t){let e=a=>a.map(({agentId:n,...r})=>r);return{...t,open:e(t.open),recent:e(t.recent),runs:e(t.runs),other:e(t.other)}}function Ko(t){return`${Kt}=${t}; Path=/; Max-Age=${Ed}; HttpOnly; Secure; SameSite=Lax`}function Md(t){return Na(t)??Da(t,Kt)}function Na(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 ge(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 ge(t,e,"application/json",JSON.stringify(a))}Wc();var Yo='/*! 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 Vt,readFileSync as os,writeFileSync as ss,rmSync as _x,mkdirSync as Od,copyFileSync as Nd,readdirSync as Dd}from"fs";import{resolve as Ke}from"path";Gc();function Zo(t){let e=mt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:mt.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 Jt(t){return C(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=mt.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 Qo=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function es(t){return Jt(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 ts(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Jt((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:Qo(t?.chats),senders:Qo(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 as(t){let e=String(t?.id??"");return Jt(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 ns(t){let e=String(t?.id??"");return Jt(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}"`})}xt();var me={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 rs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ue({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 I({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Rd()+Lr,css:$d,scripts:`${e}<script>${Rr}
|
|
1644
|
+
${Pr}
|
|
1645
|
+
${Ld}
|
|
1646
|
+
${jd}</script>`})}var Ld=`
|
|
1647
1647
|
(function(){
|
|
1648
1648
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1649
1649
|
async function voiceMissing() {
|
|
@@ -1737,8 +1737,8 @@ ${Pd}</script>`})}var Id=`
|
|
|
1737
1737
|
refresh();
|
|
1738
1738
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1739
1739
|
document.addEventListener('ax-config-saved', refresh);
|
|
1740
|
-
})();`;function
|
|
1741
|
-
`:"";return
|
|
1740
|
+
})();`;function Rd(){let t=gr().business?`<button data-tab="business">Business</button>
|
|
1741
|
+
`:"";return Pd.replace("__BUSINESS_TABS__",t)}var Pd=`
|
|
1742
1742
|
<div id="peer-banner" class="peer-banner">
|
|
1743
1743
|
<span class="label">Managing</span>
|
|
1744
1744
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -1990,10 +1990,10 @@ ${Pd}</script>`})}var Id=`
|
|
|
1990
1990
|
</div>
|
|
1991
1991
|
</details>
|
|
1992
1992
|
|
|
1993
|
-
<div id="ch-chatapps-label">${
|
|
1993
|
+
<div id="ch-chatapps-label">${jt({label:"Chat apps"})}</div>
|
|
1994
1994
|
<div class="ax-connectors" id="ch-chatapps"></div>
|
|
1995
1995
|
|
|
1996
|
-
<div id="ch-devtools-label">${
|
|
1996
|
+
<div id="ch-devtools-label">${jt({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
|
|
1997
1997
|
<div class="ax-connectors" id="ch-devtools"></div>
|
|
1998
1998
|
|
|
1999
1999
|
<!-- Active-channel configuration panes. One shows at a time; clicking
|
|
@@ -2154,7 +2154,7 @@ ${Pd}</script>`})}var Id=`
|
|
|
2154
2154
|
${K({icon:me.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."})}
|
|
2155
2155
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
2156
2156
|
${se({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."})}
|
|
2157
|
-
${
|
|
2157
|
+
${jt({label:"Connected peers"})}
|
|
2158
2158
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
2159
2159
|
<div class="add-form">
|
|
2160
2160
|
<h3>Add a peer</h3>
|
|
@@ -2397,7 +2397,7 @@ ${Pd}</script>`})}var Id=`
|
|
|
2397
2397
|
<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>
|
|
2398
2398
|
</section>
|
|
2399
2399
|
</main>
|
|
2400
|
-
|
|
2400
|
+
`,$d=`
|
|
2401
2401
|
|
|
2402
2402
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
2403
2403
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2605,7 +2605,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2605
2605
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2606
2606
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2607
2607
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2608
|
-
`,
|
|
2608
|
+
`,jd=`
|
|
2609
2609
|
const $ = (id) => document.getElementById(id);
|
|
2610
2610
|
let state = null;
|
|
2611
2611
|
|
|
@@ -5489,11 +5489,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
5489
5489
|
})();
|
|
5490
5490
|
|
|
5491
5491
|
refresh();
|
|
5492
|
-
`;function ss(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ns({peers:a,localToken:n}))}async function is(t,e){let a=Ba();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function ls(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Vd(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Nd(t),r={"GET /api/admin/state":()=>Hd(),"POST /api/admin/agents":()=>Wd(n),"PATCH /api/admin/agents":()=>Gd(n),"DELETE /api/admin/agents":()=>Xd(n),"POST /api/admin/agents/access":()=>Bd(n),"POST /api/admin/channels/telegram":()=>Kd(n),"DELETE /api/admin/channels/telegram":()=>bp(n),"POST /api/admin/channels/telegram/toggle":()=>vp(n),"POST /api/admin/crons":()=>yp(n),"DELETE /api/admin/crons":()=>wp(n),"POST /api/admin/config/raw":()=>kp(n),"GET /api/admin/tokens":()=>zd(),"POST /api/admin/tokens":()=>qd(n),"DELETE /api/admin/tokens":()=>Fd(n),"POST /api/admin/agents/test":()=>Ud(n),"POST /api/admin/agents/integrations":()=>ap(n),"DELETE /api/admin/agents/integrations":()=>np(n),"PATCH /api/admin/agents/integrations":()=>rp(n),"PATCH /api/admin/channels/telegram":()=>Jd(n),"POST /api/admin/channels/slack":()=>pp(n),"POST /api/admin/channels/slack/toggle":()=>up(n),"POST /api/admin/channels/discord":()=>mp(n),"POST /api/admin/channels/discord/toggle":()=>fp(n),"POST /api/admin/channels/gitlab":()=>hp(n),"POST /api/admin/channels/gitlab/toggle":()=>gp(n),"POST /api/admin/channels/request-status":()=>Xr(n),"GET /api/admin/channels/whatsapp/state":()=>nt("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>nt("/webrtc/history"),"POST /api/admin/actions":()=>jp(n),"DELETE /api/admin/actions":()=>Op(n),"POST /api/admin/actions/run":()=>Np(n),"GET /api/admin/channels/whatsapp/chats":()=>nt("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>nt("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>xe("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>xp(n),"POST /api/admin/webhooks":()=>op(n),"PATCH /api/admin/webhooks":()=>sp(n),"DELETE /api/admin/webhooks":()=>dp(n),"POST /api/admin/whatsapp-triage":()=>Zo(n),"POST /api/admin/whatsapp-triage/rules":()=>es(n),"PATCH /api/admin/whatsapp-triage/rules":()=>ts(n),"DELETE /api/admin/whatsapp-triage/rules":()=>as(n),"POST /api/admin/mesh/peers":()=>ip(n),"DELETE /api/admin/mesh/peers":()=>lp(n),"POST /api/admin/mesh/toggle":()=>cp(n),"GET /api/admin/files":()=>Yd(t),"GET /api/admin/files/read":()=>Qd(t),"PUT /api/admin/files":()=>Zd(n),"POST /api/admin/files/skill":()=>ep(n),"DELETE /api/admin/files/skill":()=>tp(n),"POST /api/admin/business/orgchart":()=>_p(n),"DELETE /api/admin/business/orgchart":()=>Sp(n),"POST /api/admin/business/project":()=>Ep(n),"DELETE /api/admin/business/project":()=>Cp(n),"POST /api/admin/business/client":()=>Tp(n),"DELETE /api/admin/business/client":()=>Ap(n),"POST /api/admin/business/contact":()=>Ip(n),"DELETE /api/admin/business/contact":()=>Mp(n),"POST /api/admin/boards":()=>Lp(n),"DELETE /api/admin/boards":()=>Rp(n),"POST /api/admin/boards/columns":()=>Pp(n),"DELETE /api/admin/boards/columns":()=>$p(n),"POST /api/admin/notifications":()=>Hp(n),"POST /api/admin/screen":()=>Bp(n),"POST /api/admin/webhooks/triggers":()=>zp(n),"POST /api/admin/mesh/health":()=>Dp(n),"GET /api/admin/projects":()=>nt("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>xe("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>xe("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>xe("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>xe("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>xe("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>xe("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>xe("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>xe("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Da(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Da(e,200,i)}catch(n){Da(e,400,{error:n.message||"admin op failed"})}}function Da(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Nd(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 Dd(t){let e=Xe(process.cwd(),t);if(!Jt(e))return[];let a=[];for(let n of Od(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(rs(Xe(e,n.name),"utf-8")))}catch{}return a}function Ba(){let t=Xe(process.cwd(),"agentx.json");return Jt(t)?JSON.parse(rs(t,"utf-8")):null}function Hd(){let t=Ba();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([x,u])=>({id:x,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(h=>{let w=h.credentials||{},y={};for(let[T,v]of Object.entries(w))typeof v=="string"&&/^[A-Z][A-Z0-9_]*$/.test(v)?y[T]=process.env[v]?"set":"unset":typeof v=="string"&&(y[T]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:w,credStatus:y,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([x,u])=>({id:x,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.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(([x,u])=>({id:x,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(x=>({id:x.id,source:x.source,agentId:x.agentId,secretEnv:x.secretEnv||"",description:x.description||"",enabled:x.enabled!==!1,triggers:x.triggers&&typeof x.triggers=="object"?x.triggers:{},defaultWorkflow:x.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(x=>({url:x.url,name:x.name,hasToken:!!x.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},f={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},S=t.notifications||{},b={longTaskThreshold:S.longTaskThreshold??30,destination:S.destination||null,on:{taskComplete:S.on?.taskComplete!==!1,taskError:S.on?.taskError!==!1,taskQueued:!!S.on?.taskQueued},local:Zn(S.local),ntfy:Jr(t.channels?.ntfy)},E=[];try{E=Dd(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,h)=>u.id.localeCompare(h.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(x=>({id:x.id,name:x.name,source:x.source||{type:"gitlab",projects:[]},primaryToolLabel:x.primaryToolLabel||"",timeRangeDays:x.timeRangeDays??30,closedWindowDays:x.closedWindowDays??30,columns:Array.isArray(x.columns)?x.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Gr(t),whatsappTriage:Qo(t),crons:l,webhooks:c,mesh:d,daemonUrl:p,nodeName:t.node?.name,business:f,boards:g,notifications:b,screen:Tr(t.screen),actions:E}}function Bd(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}=C(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 zd(){return new G().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 qd(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 G().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Fd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new G().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ud(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 d=X();r=d.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=d.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 Wd(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=ds(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=Xe(process.cwd(),"agents",e),{summary:l}=C(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let p={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(p.model=o),s&&(p.systemPrompt=s.slice(0,400)),d.agents[e]=p,`added agent "${e}"`}),c=Xe(i,"CLAUDE.md");if(!Jt(c))try{$d(i,{recursive:!0}),os(c,`# ${a}
|
|
5492
|
+
`;function is(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rs({peers:a,localToken:n}))}async function ls(t,e){let a=za();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function cs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Qd(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Hd(t),r={"GET /api/admin/state":()=>zd(),"POST /api/admin/agents":()=>Xd(n),"PATCH /api/admin/agents":()=>Kd(n),"DELETE /api/admin/agents":()=>Jd(n),"POST /api/admin/agents/access":()=>qd(n),"POST /api/admin/channels/telegram":()=>Vd(n),"DELETE /api/admin/channels/telegram":()=>yp(n),"POST /api/admin/channels/telegram/toggle":()=>wp(n),"POST /api/admin/crons":()=>kp(n),"DELETE /api/admin/crons":()=>_p(n),"POST /api/admin/config/raw":()=>Sp(n),"GET /api/admin/tokens":()=>Fd(),"POST /api/admin/tokens":()=>Ud(n),"DELETE /api/admin/tokens":()=>Wd(n),"POST /api/admin/agents/test":()=>Gd(n),"POST /api/admin/agents/integrations":()=>rp(n),"DELETE /api/admin/agents/integrations":()=>op(n),"PATCH /api/admin/agents/integrations":()=>sp(n),"PATCH /api/admin/channels/telegram":()=>Yd(n),"POST /api/admin/channels/slack":()=>mp(n),"POST /api/admin/channels/slack/toggle":()=>fp(n),"POST /api/admin/channels/discord":()=>hp(n),"POST /api/admin/channels/discord/toggle":()=>gp(n),"POST /api/admin/channels/gitlab":()=>xp(n),"POST /api/admin/channels/gitlab/toggle":()=>bp(n),"POST /api/admin/channels/request-status":()=>Kr(n),"GET /api/admin/channels/whatsapp/state":()=>rt("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>rt("/webrtc/history"),"POST /api/admin/actions":()=>Np(n),"DELETE /api/admin/actions":()=>Dp(n),"POST /api/admin/actions/run":()=>Hp(n),"GET /api/admin/channels/whatsapp/chats":()=>rt("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>rt("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>xe("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>vp(n),"POST /api/admin/webhooks":()=>ip(n),"PATCH /api/admin/webhooks":()=>lp(n),"DELETE /api/admin/webhooks":()=>up(n),"POST /api/admin/whatsapp-triage":()=>es(n),"POST /api/admin/whatsapp-triage/rules":()=>ts(n),"PATCH /api/admin/whatsapp-triage/rules":()=>as(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ns(n),"POST /api/admin/mesh/peers":()=>cp(n),"DELETE /api/admin/mesh/peers":()=>dp(n),"POST /api/admin/mesh/toggle":()=>pp(n),"GET /api/admin/files":()=>Zd(t),"GET /api/admin/files/read":()=>ep(t),"PUT /api/admin/files":()=>tp(n),"POST /api/admin/files/skill":()=>ap(n),"DELETE /api/admin/files/skill":()=>np(n),"POST /api/admin/business/orgchart":()=>Ep(n),"DELETE /api/admin/business/orgchart":()=>Tp(n),"POST /api/admin/business/project":()=>Ap(n),"DELETE /api/admin/business/project":()=>Mp(n),"POST /api/admin/business/client":()=>Cp(n),"DELETE /api/admin/business/client":()=>Ip(n),"POST /api/admin/business/contact":()=>Lp(n),"DELETE /api/admin/business/contact":()=>Rp(n),"POST /api/admin/boards":()=>Pp(n),"DELETE /api/admin/boards":()=>$p(n),"POST /api/admin/boards/columns":()=>jp(n),"DELETE /api/admin/boards/columns":()=>Op(n),"POST /api/admin/notifications":()=>zp(n),"POST /api/admin/screen":()=>qp(n),"POST /api/admin/webhooks/triggers":()=>Fp(n),"POST /api/admin/mesh/health":()=>Bp(n),"GET /api/admin/projects":()=>rt("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>xe("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>xe("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>xe("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>xe("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>xe("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>xe("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>xe("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>xe("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Ha(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Ha(e,200,i)}catch(n){Ha(e,400,{error:n.message||"admin op failed"})}}function Ha(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Hd(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 Bd(t){let e=Ke(process.cwd(),t);if(!Vt(e))return[];let a=[];for(let n of Dd(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(os(Ke(e,n.name),"utf-8")))}catch{}return a}function za(){let t=Ke(process.cwd(),"agentx.json");return Vt(t)?JSON.parse(os(t,"utf-8")):null}function zd(){let t=za();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([x,u])=>({id:x,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(h=>{let w=h.credentials||{},y={};for(let[T,v]of Object.entries(w))typeof v=="string"&&/^[A-Z][A-Z0-9_]*$/.test(v)?y[T]=process.env[v]?"set":"unset":typeof v=="string"&&(y[T]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:w,credStatus:y,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([x,u])=>({id:x,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.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(([x,u])=>({id:x,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(x=>({id:x.id,source:x.source,agentId:x.agentId,secretEnv:x.secretEnv||"",description:x.description||"",enabled:x.enabled!==!1,triggers:x.triggers&&typeof x.triggers=="object"?x.triggers:{},defaultWorkflow:x.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(x=>({url:x.url,name:x.name,hasToken:!!x.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},f={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},_=t.notifications||{},b={longTaskThreshold:_.longTaskThreshold??30,destination:_.destination||null,on:{taskComplete:_.on?.taskComplete!==!1,taskError:_.on?.taskError!==!1,taskQueued:!!_.on?.taskQueued},local:er(_.local),ntfy:Vr(t.channels?.ntfy)},S=[];try{S=Bd(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,h)=>u.id.localeCompare(h.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(x=>({id:x.id,name:x.name,source:x.source||{type:"gitlab",projects:[]},primaryToolLabel:x.primaryToolLabel||"",timeRangeDays:x.timeRangeDays??30,closedWindowDays:x.closedWindowDays??30,columns:Array.isArray(x.columns)?x.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Xr(t),whatsappTriage:Zo(t),crons:l,webhooks:c,mesh:d,daemonUrl:p,nodeName:t.node?.name,business:f,boards:g,notifications:b,screen:Ar(t.screen),actions:S}}function qd(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}=C(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 Fd(){return new G().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 Ud(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 G().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Wd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new G().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Gd(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 d=X();r=d.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=d.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 Xd(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=ps(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=Ke(process.cwd(),"agents",e),{summary:l}=C(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let p={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(p.model=o),s&&(p.systemPrompt=s.slice(0,400)),d.agents[e]=p,`added agent "${e}"`}),c=Ke(i,"CLAUDE.md");if(!Vt(c))try{Od(i,{recursive:!0}),ss(c,`# ${a}
|
|
5493
5493
|
|
|
5494
5494
|
${s||"You are "+a+"."}
|
|
5495
|
-
`)}catch{}return{summary:l}}function Gd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=C(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=ds(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 Xd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(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 Kd(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}=C(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 Jd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(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 nt(t){let{url:e,headers:a}=za(),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 xe(t,e){let{url:a,headers:n}=za(),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 Vd(t,e){try{let{url:a,headers:n}=za(),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 za(){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 rt(t){let a=Ba()?.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 Ha(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Yd(t){let e=Ha(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=qe(rt(e));return{agentId:e,...a}}function Qd(t){let e=Ha(t,"agent").trim(),a=Ha(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ct(rt(e),a)}function Zd(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=It(rt(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function ep(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=Mt(rt(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function tp(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=Lt(rt(e),a);return{summary:`removed skill "${a}"`,...n}}function ap(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}=C(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 np(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}=C(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 rp(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}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(d=>d.kind===a&&d.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 cs=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function op(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(!cs.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(p=>p.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(d=>d.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 sp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&cs.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 ip(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}=C(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 lp(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(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 cp(t){let e=!!t?.enabled,{summary:a}=C(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 dp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(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 pp(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}=C(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 up(t){let e=!!t?.enabled,{summary:a}=C(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 mp(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}=C(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 fp(t){let e=!!t?.enabled,{summary:a}=C(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 hp(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}=C(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 gp(t){let e=!!t?.enabled,{summary:a}=C(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 xp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-ALPDUE4H.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 bp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(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 vp(t){let e=!!t?.enabled,{summary:a}=C(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 yp(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}=C(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 wp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=C(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function kp(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=Xe(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Jt(n))try{jd(n,r)}catch{}os(n,JSON.stringify(a,null,2)+`
|
|
5496
|
-
`,"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 ds(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function _p(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}=C(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 Sp(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=C(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 Ep(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}=C(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 Tp(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}=C(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 Ap(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(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 Cp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=C(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 Ip(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}=C(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 Mp(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}=C(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 Lp(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}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(p=>p.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let p=l.boards[c];return l.boards[c]={...p,...d,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function Rp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=C(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 Pp(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}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(p=>p.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 d=l.columns.findIndex(p=>p.id===a);return d>=0?(l.columns[d]={...l.columns[d],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function $p(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}=C(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 jp(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 Op(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 Np(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 Dp(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}=C(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 Hp(t){let{summary:e}=C(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=er(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=Vr(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 Bp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Ar(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function zp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(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}}gt();import{resolve as Up}from"path";function ps(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5495
|
+
`)}catch{}return{summary:l}}function Kd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=C(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=ps(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 Jd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(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 Vd(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}=C(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 Yd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(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 rt(t){let{url:e,headers:a}=qa(),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 xe(t,e){let{url:a,headers:n}=qa(),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 Qd(t,e){try{let{url:a,headers:n}=qa(),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 qa(){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 ot(t){let a=za()?.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 Ba(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Zd(t){let e=Ba(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Fe(ot(e));return{agentId:e,...a}}function ep(t){let e=Ba(t,"agent").trim(),a=Ba(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return It(ot(e),a)}function tp(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=Mt(ot(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function ap(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=Lt(ot(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function np(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=Rt(ot(e),a);return{summary:`removed skill "${a}"`,...n}}function rp(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}=C(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 op(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}=C(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 sp(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}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(d=>d.kind===a&&d.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 ds=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function ip(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(!ds.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(p=>p.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(d=>d.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 lp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&ds.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 cp(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}=C(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 dp(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(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 pp(t){let e=!!t?.enabled,{summary:a}=C(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 up(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(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 mp(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}=C(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 fp(t){let e=!!t?.enabled,{summary:a}=C(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 hp(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}=C(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 gp(t){let e=!!t?.enabled,{summary:a}=C(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 xp(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}=C(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 bp(t){let e=!!t?.enabled,{summary:a}=C(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 vp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-ALPDUE4H.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 yp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(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 wp(t){let e=!!t?.enabled,{summary:a}=C(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 kp(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}=C(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 _p(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=C(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function Sp(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=Ke(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Vt(n))try{Nd(n,r)}catch{}ss(n,JSON.stringify(a,null,2)+`
|
|
5496
|
+
`,"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 ps(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Ep(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}=C(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 Tp(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=C(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 Ap(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}=C(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 Cp(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}=C(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 Ip(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(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 Mp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=C(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 Lp(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}=C(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 Rp(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}=C(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 Pp(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}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(p=>p.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let p=l.boards[c];return l.boards[c]={...p,...d,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function $p(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=C(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 jp(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}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(p=>p.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 d=l.columns.findIndex(p=>p.id===a);return d>=0?(l.columns[d]={...l.columns[d],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Op(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}=C(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 Np(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 Dp(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 Hp(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 Bp(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}=C(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 zp(t){let{summary:e}=C(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=tr(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=Yr(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 qp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Cr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Fp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(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}}xt();import{resolve as Gp}from"path";function us(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5497
5497
|
|
|
5498
5498
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
5499
5499
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -5548,7 +5548,7 @@ ${s||"You are "+a+"."}
|
|
|
5548
5548
|
<h2>Recent classifications</h2>
|
|
5549
5549
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
5550
5550
|
<div id="recent"></div>
|
|
5551
|
-
</section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5551
|
+
</section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Up,scripts:`${e}<script>${Wp}</script>`})}var Up=`
|
|
5552
5552
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
5553
5553
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
5554
5554
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5652,7 +5652,7 @@ details {
|
|
|
5652
5652
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5653
5653
|
}
|
|
5654
5654
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5655
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
5655
|
+
details[open] summary { margin-bottom: 8px; }`,Wp=`
|
|
5656
5656
|
const $ = (id) => document.getElementById(id);
|
|
5657
5657
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5658
5658
|
|
|
@@ -5872,7 +5872,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5872
5872
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5873
5873
|
|
|
5874
5874
|
refresh();
|
|
5875
|
-
`;function
|
|
5875
|
+
`;function fs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(us({peers:a,localToken:n}))}async function hs(t,e,a){try{let n=t.method==="GET"?void 0:await tu(t),r=Xp(),o={"GET /api/admin/graph/state":()=>Kp(r),"POST /api/admin/graph/classifications/approve":()=>Jp(r,n),"POST /api/admin/graph/classifications/reject":()=>Vp(r,n),"POST /api/admin/graph/nodes":()=>Yp(r,n),"PATCH /api/admin/graph/nodes":()=>Qp(r,n),"DELETE /api/admin/graph/nodes":()=>Zp(r,n),"PUT /api/admin/graph/schema":()=>eu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Fa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Fa(e,200,l)}catch(n){Fa(e,400,{error:n?.message||"graph op failed"})}}function Xp(){let t=X(),e=Gp(process.cwd(),t.graph.baseDir);return new zn({baseDir:e})}function Kp(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 Jp(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=gs(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=Ua(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Vp(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=gs(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function gs(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 Yp(t,e){let a=ms(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?ms(String(e.parentId)):null,o=Ua({[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 Qp(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ua({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Zp(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function eu(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 Ua(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 ms(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Fa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function tu(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 xs=`
|
|
5876
5876
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
5877
5877
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
5878
5878
|
<p class="apv__lead">What you asked agents for that is not finished, oldest first. Reply, hand it to an agent, close it as done, or drop it. Nothing leaves this list by getting old.</p>
|
|
@@ -5889,7 +5889,7 @@ refresh();
|
|
|
5889
5889
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5890
5890
|
</form>
|
|
5891
5891
|
</details>
|
|
5892
|
-
</section>`,
|
|
5892
|
+
</section>`,bs=`
|
|
5893
5893
|
.apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
|
|
5894
5894
|
.apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
|
|
5895
5895
|
.apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
|
|
@@ -5911,7 +5911,7 @@ refresh();
|
|
|
5911
5911
|
.apv__req select { min-height: 40px; max-width: 100%; }
|
|
5912
5912
|
.apv__mic.is-on { border-color: var(--ax-err); color: var(--ax-err); }
|
|
5913
5913
|
.apv__acts + .apv__acts { margin-top: 8px; }
|
|
5914
|
-
`,
|
|
5914
|
+
`,vs=`
|
|
5915
5915
|
(function(){
|
|
5916
5916
|
var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
|
|
5917
5917
|
function $(id){ return document.getElementById(id); }
|
|
@@ -6053,7 +6053,7 @@ function busy(){
|
|
|
6053
6053
|
}
|
|
6054
6054
|
setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
|
|
6055
6055
|
})();
|
|
6056
|
-
`;function
|
|
6056
|
+
`;function ys(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
6057
6057
|
<header class="apv__head">
|
|
6058
6058
|
<div>
|
|
6059
6059
|
<h1>Approvals</h1>
|
|
@@ -6075,7 +6075,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
|
|
|
6075
6075
|
<ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
|
|
6076
6076
|
<p id="apv-snoozed" class="apv__foot"></p>
|
|
6077
6077
|
|
|
6078
|
-
${
|
|
6078
|
+
${xs}
|
|
6079
6079
|
|
|
6080
6080
|
<details class="apv__settings" id="apv-settings">
|
|
6081
6081
|
<summary>Settings: expiry, later, daily digest</summary>
|
|
@@ -6090,7 +6090,7 @@ ${gs}
|
|
|
6090
6090
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
6091
6091
|
</form>
|
|
6092
6092
|
</details>
|
|
6093
|
-
</div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
6093
|
+
</div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:au+bs,scripts:`${e}<script>${nu}</script><script>${vs}</script>`})}var au=`
|
|
6094
6094
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
6095
6095
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
6096
6096
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -6139,7 +6139,7 @@ ${gs}
|
|
|
6139
6139
|
@media (max-width: 560px) {
|
|
6140
6140
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
6141
6141
|
}
|
|
6142
|
-
`,
|
|
6142
|
+
`,nu=`
|
|
6143
6143
|
(function(){
|
|
6144
6144
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
6145
6145
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -6307,7 +6307,7 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
6307
6307
|
load();
|
|
6308
6308
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
6309
6309
|
})();
|
|
6310
|
-
`;import{existsSync as
|
|
6310
|
+
`;import{existsSync as ru,readFileSync as ou}from"fs";var Re="/api/admin/approvals/requests";function ws(t){let e=Xn(t);if(!ru(e))return[];try{let a=JSON.parse(ou(e,"utf-8"))?.agents??{};return Object.entries(a).map(([n,r])=>({id:n,name:typeof r?.name=="string"&&r.name?r.name:n}))}catch{return[]}}var ks=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function _s(t,e,a,n){try{return await su(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function su(t,e,a,n){if(t==="GET"&&e===Re){let o=Et(n);return{status:200,body:{items:o?o.listOpen().map(s=>cr(s,o)):[],agents:ws(n.configPath),settings:St(n.configPath)}}}let r=e===`${Re}/reply`?"reply":e===`${Re}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=Et(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",p=ws(n.configPath).find(f=>f.id===d);if(r==="handoff"&&!p)return{status:400,body:{error:`"${d}" is not an agent on this node`}};if(!St(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,d,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=p?.name??d;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Re}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=Et(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Re}/settings`){let o={},s=l=>{let c=a[l];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${l} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=ks(a.from),o.channels=ks(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i=await or(o,{configPath:n.configPath,reload:n.reload});return i.success?{status:200,body:{ok:!0,settings:St(n.configPath)}}:{status:400,body:{error:i.error}}}return{status:404,body:{error:"Not found"}}}var iu=["yes","no","later"];function ae(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Yt(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 Ss(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(ys({peers:e,localToken:a}))}async function Es(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 ae(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Re)){let i=await _s(o,a,o==="POST"?await Yt(t):{},s);return ae(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=Tt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return ae(e,200,{...i,settings:Ie(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Yt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!iu.includes(c))return ae(e,400,{error:"send { key, action: yes | no | later }"}),!0;let d=Ie(s.configPath),p=await At(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:d.laterHours,by:"operator (dashboard)"});return p.ok?(ae(e,200,{ok:!0,message:p.message}),!0):(ae(e,409,{error:p.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Yt(t),l=dr(s,typeof i.key=="string"?i.key:"",!!Ie(s.configPath).popup?.enabled);return l.ok?(ae(e,200,{ok:!0,message:l.message}),!0):(ae(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Yt(t),l={},c=p=>{let m=i[p];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${p} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let p=i.destination.trim();if(!p)l.destination=null;else{let m=Hr(p);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let d=await Br(l,{configPath:s.configPath,reload:s.reload});return d.success?(ae(e,200,{ok:!0,settings:Ie(s.configPath)}),!0):(ae(e,400,{error:d.error}),!0)}}catch(i){return ae(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return ae(e,404,{error:"Not found"}),!0}ba();function Ts(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ue({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates, your clients and guests. Open a person to see the machines they paired and what they asked for."})+`
|
|
6311
6311
|
<div class="pp">
|
|
6312
6312
|
<div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
|
|
6313
6313
|
<section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
|
|
@@ -6320,7 +6320,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6320
6320
|
</ol>
|
|
6321
6321
|
</section>
|
|
6322
6322
|
<ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
|
|
6323
|
-
</div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:
|
|
6323
|
+
</div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:lu,scripts:`${e}<script>${cu}</script>`})}var lu=`
|
|
6324
6324
|
.pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
|
|
6325
6325
|
.pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
|
|
6326
6326
|
.pp-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -6361,7 +6361,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6361
6361
|
.pp-text { overflow-wrap: anywhere; }
|
|
6362
6362
|
.pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
6363
6363
|
@media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
|
|
6364
|
-
`,
|
|
6364
|
+
`,cu=`
|
|
6365
6365
|
(function () {
|
|
6366
6366
|
var list = document.getElementById('pp-list');
|
|
6367
6367
|
var msg = document.getElementById('pp-msg');
|
|
@@ -6499,7 +6499,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6499
6499
|
load();
|
|
6500
6500
|
setInterval(load, 30000);
|
|
6501
6501
|
})();
|
|
6502
|
-
`;var
|
|
6502
|
+
`;var Wa="/api/admin/people";function du(t,e){let a=Ur(t,e);return a?{...e,answer:a}:e}function pu(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function uu(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&pu(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:gt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var mu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function As(t,e,a,n){if(a!=="/people"&&a!==Wa&&!a.startsWith(`${Wa}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(be(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Ts({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return be(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(d=>du(n.root,d)),s=()=>uu(n.people(),o());if(r==="GET"&&a===Wa){let c=s();return be(e,200,{people:c,paired:c.reduce((d,p)=>d+p.machines.active+p.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(f=>f.id===i[1]);if(!c)return be(e,404,{error:`no person "${i[1]}"`}),!0;let d=n.db(),p=[],m=[];try{d&&(p=zr(d,c.id))}catch{}try{d&&(m=Ot(d,c.id,20))}catch{}return be(e,200,{person:c,devices:o(c.id).sort(mu),requests:p,runs:m,database:!!d}),!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,d]=l,p=n.members.byToken(d);if(!p||p.personId!==c)return be(e,404,{error:"no such machine for this person"}),!0;if(p.state==="removed")return be(e,409,{error:"this machine's access has already ended"}),!0;let m=Gr({tokens:n.tokens??new G,members:n.members,now:n.now},d,"removed by the owner (dashboard)");return be(e,200,{ok:!0,device:m}),!0}return be(e,404,{error:"not found"}),!0}import{resolve as bu}from"path";import{existsSync as vu}from"fs";import yu from"better-sqlite3";var Cs=new WeakSet;function fu(t,e,a={}){if(Cs.has(t))return;Cs.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let c=i[l].bind(i);i[l]=(...d)=>{let p=r();try{return c(...d)}finally{let m=r()-p;m>=n&&e({sql:s,ms:m})}}}return i}}function hu(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function Se(t,e){fu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${hu(a)}`))}function Is(t={}){let e=`<div class="ax-obs">
|
|
6503
6503
|
<header class="ax-obs__head">
|
|
6504
6504
|
<h1>Health</h1>
|
|
6505
6505
|
<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>
|
|
@@ -6621,7 +6621,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6621
6621
|
</div>
|
|
6622
6622
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
6623
6623
|
</section>
|
|
6624
|
-
</div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6624
|
+
</div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:gu,scripts:`<script>${xu}</script>`})}var gu=`
|
|
6625
6625
|
.ax-obs { padding: 16px 24px; }
|
|
6626
6626
|
.ax-obs__head { margin-bottom: 16px; }
|
|
6627
6627
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -6738,7 +6738,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6738
6738
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
6739
6739
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
6740
6740
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
6741
|
-
`,
|
|
6741
|
+
`,xu=`
|
|
6742
6742
|
(function(){
|
|
6743
6743
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
6744
6744
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -7122,7 +7122,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7122
7122
|
|
|
7123
7123
|
load(current);
|
|
7124
7124
|
})();
|
|
7125
|
-
`;var
|
|
7125
|
+
`;var Rs={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 Ps(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ga(t){let e=Rs[Ps(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 wu(){let t=bu(process.cwd(),".agentx/db.sqlite");if(!vu(t))return null;try{let e=new yu(t,{readonly:!0,fileMustExist:!0});return Se(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function $s(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Is({peers:a}))}function ku(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 ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function js(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=wu();if(!r)return ve(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ku(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
7126
7126
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
7127
7127
|
FROM route_traces
|
|
7128
7128
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
@@ -7137,8 +7137,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7137
7137
|
FROM task_history
|
|
7138
7138
|
WHERE ${i.join(" AND ")}
|
|
7139
7139
|
ORDER BY started_at DESC LIMIT @limit
|
|
7140
|
-
`,p=r.db.prepare(c).all(l).map(m=>({...m,plain:
|
|
7141
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
7140
|
+
`,p=r.db.prepare(c).all(l).map(m=>({...m,plain:Os(m.error)}));return ve(e,200,{rows:p}),!0}if(n==="summary"||n==="overview")return ve(e,200,_u(r.db)),!0;if(n==="activity")return ve(e,200,Su(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Ms(i.searchParams.get("range"));return ve(e,200,Ls(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Ms(i.searchParams.get("range")),c=Ls(r.db,l),d=Eu(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(d),!0}return ve(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Os(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(`
|
|
7141
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function _u(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,d=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),p=v=>d.length?d[Math.min(d.length-1,Math.floor(d.length*v))].duration_ms:0,m=p(.5),f=p(.95),b=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((v,A)=>v+Ga(A),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((v,A)=>v+Ga(A),0),g=t.prepare(`
|
|
7142
7142
|
SELECT agent_id,
|
|
7143
7143
|
COUNT(*) AS tasks,
|
|
7144
7144
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -7161,7 +7161,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7161
7161
|
FROM task_history
|
|
7162
7162
|
WHERE status='error' AND started_at >= ?
|
|
7163
7163
|
ORDER BY started_at DESC LIMIT 5
|
|
7164
|
-
`).all(o).map(v=>({...v,plain:
|
|
7164
|
+
`).all(o).map(v=>({...v,plain:Os(v.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:f,spendToday:b,spendDelta:b-S,idleAgentCount:w.length},perAgent:g,perChannel:x,idleAgents:w,recentErrors:T}}function Su(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(`
|
|
7165
7165
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
7166
7166
|
COUNT(*) AS tasks,
|
|
7167
7167
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -7188,7 +7188,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7188
7188
|
WHERE started_at >= @since
|
|
7189
7189
|
GROUP BY agent_id
|
|
7190
7190
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
7191
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
7191
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Ms(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 Ls(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
7192
7192
|
SELECT day, agent_id, model,
|
|
7193
7193
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
7194
7194
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -7196,15 +7196,15 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7196
7196
|
FROM usage_daily
|
|
7197
7197
|
${a}
|
|
7198
7198
|
ORDER BY day
|
|
7199
|
-
`).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,d=0,p=0,m=0,f=0,
|
|
7199
|
+
`).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,d=0,p=0,m=0,f=0,_=0,b=0,S=0,g={},x={};for(let E of n){let L=Ga(E),j=Ps(E.model),$=Rs[j],O=(E.tier2_input_tokens||0)/1e6*$.input*.5+(E.tier2_output_tokens||0)/1e6*$.output*.5+(E.tier2_cache_read_tokens||0)/1e6*$.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*$.cacheCreate*.5,U=(E.input_tokens||0)+(E.tier2_input_tokens||0),ce=(E.output_tokens||0)+(E.tier2_output_tokens||0),Z=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),oe=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);p+=L,E.day>=s&&(d+=L,_+=E.tasks||0),E.day>=i&&E.day<s&&(S+=L,b+=E.tasks||0),E.day===r&&(l+=L),E.day===o&&(c+=L),E.day===r&&(m+=O),E.day>=s&&(f+=O);let ee=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});ee.tasks+=E.tasks||0,ee.input+=U,ee.output+=ce,ee.cacheRead+=Z,ee.cacheCreate+=oe,ee.cost+=L,ee.tier2+=O;let F=ee.agents[E.agent_id]||(ee.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});F.tasks+=E.tasks||0,F.cost+=L,F.tier2+=O,F.input+=U,F.output+=ce,F.cacheRead+=Z,F.cacheCreate+=oe,E.model&&(F.model=E.model);let N=x[E.agent_id]||(x[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});N.tasks+=E.tasks||0,N.cost+=L,N.tier2+=O,N.input+=U,N.output+=ce,N.cacheRead+=Z,N.cacheCreate+=oe,E.model&&(N.model=E.model)}let u=Object.values(g).sort((E,L)=>E.date<L.date?-1:1),h=0,w=0,y=0,T=0,v=0,A=0;for(let E of u)h+=E.tasks,w+=E.input,y+=E.output,T+=E.cacheRead,v+=E.cacheCreate,A+=E.cost;let R=Object.entries(x).map(([E,L])=>({agent_id:E,...L,tokens:L.input+L.output+L.cacheRead+L.cacheCreate})).sort((E,L)=>L.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:d,spend30d:p,tier2Today:m,tier2_7d:f,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:h,tokensRange:w+y+T+v,cacheHitRange:T+w>0?T/(T+w):0,costPerTaskRange:h>0?A/h:0,spendDeltaWoW:S>0?(d-S)/S:0,tasksDeltaWoW:b>0?(_-b)/b:0},days:u,perAgent:R}}function Eu(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+`
|
|
7200
7200
|
`+a.join(`
|
|
7201
7201
|
`)+`
|
|
7202
|
-
`}import{resolve as
|
|
7202
|
+
`}import{resolve as Tu}from"path";import{existsSync as Au}from"fs";import Cu from"better-sqlite3";function Iu(){let t=Tu(process.cwd(),".agentx/intent/ledger.sqlite");if(!Au(t))return null;try{let e=new Cu(t,{readonly:!0,fileMustExist:!0});return Se(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ns>6e4&&(Ns=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Ns=0;function Pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Mu(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 Ds(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Iu();if(!r)return Pe(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=Mu(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),d=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let p=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",f=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),_=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,b=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${p}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),x=r.db.prepare(`
|
|
7203
7203
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
7204
7204
|
LEFT JOIN intent_resolutions r
|
|
7205
7205
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
7206
7206
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
7207
|
-
`).get().n;return Pe(e,200,{since:s??null,eventsBySource:f,totalDecisions:
|
|
7207
|
+
`).get().n;return Pe(e,200,{since:s??null,eventsBySource:f,totalDecisions:_,decisionsByOutcome:b,totalDivergences:S,divergencesBySource:g,inFlight:x}),!0}if(n==="events"){let p=[],m={limit:d};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i),l&&(p.push("project = @project"),m.project=l);let f=`
|
|
7208
7208
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
7209
7209
|
FROM intent_events
|
|
7210
7210
|
${p.length?"WHERE "+p.join(" AND "):""}
|
|
@@ -7226,7 +7226,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7226
7226
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
7227
7227
|
WHERE ${p.join(" AND ")}
|
|
7228
7228
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
7229
|
-
`;return Pe(e,200,{rows:r.db.prepare(f).all(m)}),!0}return Pe(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Pe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function
|
|
7229
|
+
`;return Pe(e,200,{rows:r.db.prepare(f).all(m)}),!0}return Pe(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Pe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Hs(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
7230
7230
|
<header class="ax-led__head">
|
|
7231
7231
|
<h1>Intent ledger</h1>
|
|
7232
7232
|
<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>
|
|
@@ -7431,7 +7431,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7431
7431
|
}
|
|
7432
7432
|
load();
|
|
7433
7433
|
})();
|
|
7434
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7434
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Bs(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
7435
7435
|
<header class="ax-cost__head">
|
|
7436
7436
|
<div>
|
|
7437
7437
|
<h1>Cost</h1>
|
|
@@ -8004,7 +8004,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8004
8004
|
load();
|
|
8005
8005
|
setInterval(load, 30000);
|
|
8006
8006
|
})();
|
|
8007
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
8007
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function zs(t={}){let e=`<div class="ax-pj__root">
|
|
8008
8008
|
<aside class="ax-pj__list">
|
|
8009
8009
|
<header>
|
|
8010
8010
|
<h2>Projects</h2>
|
|
@@ -8031,7 +8031,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8031
8031
|
</header>
|
|
8032
8032
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
8033
8033
|
</section>
|
|
8034
|
-
</div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
8034
|
+
</div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Lu,scripts:`<script>${Ru}</script>`})}var Lu=`
|
|
8035
8035
|
.ax-pj__root {
|
|
8036
8036
|
display: grid;
|
|
8037
8037
|
grid-template-columns: 360px 1fr;
|
|
@@ -8218,7 +8218,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8218
8218
|
}
|
|
8219
8219
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
8220
8220
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
8221
|
-
`,
|
|
8221
|
+
`,Ru=`
|
|
8222
8222
|
(function(){
|
|
8223
8223
|
const $ = (sel) => document.querySelector(sel);
|
|
8224
8224
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -8868,22 +8868,22 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8868
8868
|
load();
|
|
8869
8869
|
});
|
|
8870
8870
|
})();
|
|
8871
|
-
`;import{resolve as Va,join as Gu}from"path";import{existsSync as Ya,readdirSync as Xu,readFileSync as Ku}from"fs";import Ju from"better-sqlite3";var qs=String.raw`[\w.-]+(?:/[\w.-]+)+`,Lu=new RegExp(`^(?:chat:)?(${qs}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Ru=new RegExp(`^\\[(?:GitLab|GitHub) (${qs}) `);function zs(t){if(!t)return null;let e=t.match(Lu);return e?e[1]:null}function Ga(t){if(!t)return null;let e=t.trimStart().match(Ru);return e?e[1]:null}function Yt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():zs(typeof n?.chatId=="string"?n.chatId:null)??zs(e)??Ga(a)}function Pu(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Qt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var $u=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,ju=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ou=t=>/^issue/i.test(t)?"issue":"mr";function Nu(t){let e=t.subject.match($u)??t.inputPreview.trimStart().match(ju);return e?{kind:Ou(e[1]),n:Number(e[2])}:null}function Du(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 Fs(t){if(!Pu(t.projectId))return[];let e=Nu(t);return e?[e]:Du(t.inputPreview)}var Hu=6e4,Bu=5*6e4,zu=40,Us=6,Ws=new Map;function Gs(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 Fs(n)){let s=Qt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=zu)return[...e.values()]}}return[...e.values()]}async function Xs(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Qt(s.project,s.ref),l=Ws.get(i);l&&n-l.at<(s.github?Bu:Hu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Us)await Promise.all(o.slice(s,s+Us).map(async i=>{let l=Qt(i.project,i.ref),c=null;try{c=i.github?await Fu(i,e,a):await qu(i,e,a)}catch{}Ws.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Ks(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 qu(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 Ks(`${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 Fu(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 Ks(`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}Rn();var Xa=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Js(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=mt(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=Xa(o.from,80);if(s){a.callback={from:s,status:Xa(o.status,20)??"done"};let i=Xa(o.peer,80);i&&(a.callback.peer=i)}}return a}Rn();xa();var Vs={kind:"agentx",id:"agentx",name:"AgentX"},Ka={kind:"person",id:"unknown",name:"Unknown"},Uu=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Ys=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),$e=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Wu(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=$e(o?.id)??(e==="whatsapp"?$e(n?.from):void 0),i=$e(o?.username)??$e(o?.login);return s||i?{id:s,username:i,name:$e(o?.name)}:null}function Qs(t){let e=s=>({kind:"person",id:`person:${s}`,name:Nn(t.people,s)}),a=(s,i)=>i||Uu.has(s)?Vs:{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=$e(n.person)??Hn(t.people,s)?.id;if(i)return e(i);let l=mt(s),c=l?.channel??t.channel;if(Ln(s)==="human")return Ys(s?.senderUsername)?a(c,!1):Ka;let d=!!$e(n.senderAgentId)||ma(l?l.sender:s?.sender);return c==="desktop"&&!d?Ka:a(c,d)}let r=Wu(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Dn(t.people,t.channel,r);return o?e(o.id):ma(r.name)?Vs:Mn.has(t.channel)&&!Ys(r.username)?Ka:a(t.channel,!1)}function Qa(){let t=Va(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ya(t))return null;try{let e=new Ju(t,{readonly:!0,fileMustExist:!0});return Se(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Zs>6e4&&(Zs=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Zs=0;function ye(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var je={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 Vu(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in je)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in je)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in je)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 je)return s}return"workflow"}return t}function ai(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 Yu(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 ni(t,e,a){return Yn(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 Qu(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&&!Ja(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ja(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:em(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&&!Ja(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",p=ei(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:p}}}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:ei(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 Zu={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function em(t,e){let a=Zu[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ei(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ja(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 ri(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}
|
|
8871
|
+
`;import{resolve as Ya,join as Ku}from"path";import{existsSync as Qa,readdirSync as Ju,readFileSync as Vu}from"fs";import Yu from"better-sqlite3";var Fs=String.raw`[\w.-]+(?:/[\w.-]+)+`,Pu=new RegExp(`^(?:chat:)?(${Fs}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),$u=new RegExp(`^\\[(?:GitLab|GitHub) (${Fs}) `);function qs(t){if(!t)return null;let e=t.match(Pu);return e?e[1]:null}function Xa(t){if(!t)return null;let e=t.trimStart().match($u);return e?e[1]:null}function Qt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():qs(typeof n?.chatId=="string"?n.chatId:null)??qs(e)??Xa(a)}function ju(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Zt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ou=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Nu=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Du=t=>/^issue/i.test(t)?"issue":"mr";function Hu(t){let e=t.subject.match(Ou)??t.inputPreview.trimStart().match(Nu);return e?{kind:Du(e[1]),n:Number(e[2])}:null}function Bu(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 Us(t){if(!ju(t.projectId))return[];let e=Hu(t);return e?[e]:Bu(t.inputPreview)}var zu=6e4,qu=5*6e4,Fu=40,Ws=6,Gs=new Map;function Xs(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 Us(n)){let s=Zt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Fu)return[...e.values()]}}return[...e.values()]}async function Ks(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Zt(s.project,s.ref),l=Gs.get(i);l&&n-l.at<(s.github?qu:zu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Ws)await Promise.all(o.slice(s,s+Ws).map(async i=>{let l=Zt(i.project,i.ref),c=null;try{c=i.github?await Wu(i,e,a):await Uu(i,e,a)}catch{}Gs.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Js(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 Uu(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 Js(`${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 Wu(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 Js(`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}Pn();var Ka=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Vs(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=ft(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}Pn();ba();var Ys={kind:"agentx",id:"agentx",name:"AgentX"},Ja={kind:"person",id:"unknown",name:"Unknown"},Gu=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Qs=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),$e=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Xu(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=$e(o?.id)??(e==="whatsapp"?$e(n?.from):void 0),i=$e(o?.username)??$e(o?.login);return s||i?{id:s,username:i,name:$e(o?.name)}:null}function Zs(t){let e=s=>({kind:"person",id:`person:${s}`,name:Dn(t.people,s)}),a=(s,i)=>i||Gu.has(s)?Ys:{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=$e(n.person)??Bn(t.people,s)?.id;if(i)return e(i);let l=ft(s),c=l?.channel??t.channel;if(Rn(s)==="human")return Qs(s?.senderUsername)?a(c,!1):Ja;let d=!!$e(n.senderAgentId)||fa(l?l.sender:s?.sender);return c==="desktop"&&!d?Ja:a(c,d)}let r=Xu(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Hn(t.people,t.channel,r);return o?e(o.id):fa(r.name)?Ys:Ln.has(t.channel)&&!Qs(r.username)?Ja:a(t.channel,!1)}function Za(){let t=Ya(process.cwd(),".agentx/intent/ledger.sqlite");if(!Qa(t))return null;try{let e=new Yu(t,{readonly:!0,fileMustExist:!0});return Se(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ei>6e4&&(ei=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ei=0;function ye(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var je={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 Qu(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in je)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in je)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in je)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 je)return s}return"workflow"}return t}function ni(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 Zu(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 ri(t,e,a){return Qn(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 em(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&&!Va(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Va(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:am(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&&!Va(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",p=ti(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:p}}}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:ti(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 tm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function am(t,e){let a=tm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ti(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Va(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 oi(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}
|
|
8872
8872
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
8873
|
-
${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
|
|
8873
|
+
${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 nm(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 si(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
8874
8874
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
8875
8875
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
8876
|
-
`).all(r),s=new Map,i=new Map;if(o.length>0){let v=o.map(j=>j.id),A=v.map((j,$)=>`@id${$}`).join(","),R=Object.fromEntries(v.map((j,$)=>[`id${$}`,j])),
|
|
8876
|
+
`).all(r),s=new Map,i=new Map;if(o.length>0){let v=o.map(j=>j.id),A=v.map((j,$)=>`@id${$}`).join(","),R=Object.fromEntries(v.map((j,$)=>[`id${$}`,j])),E=t.prepare(`
|
|
8877
8877
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
8878
8878
|
FROM intent_decisions WHERE event_id IN (${A}) ORDER BY decided_at ASC
|
|
8879
|
-
`).all(R);for(let j of
|
|
8879
|
+
`).all(R);for(let j of E)s.has(j.event_id)||s.set(j.event_id,[]),s.get(j.event_id).push(j);let L=t.prepare(`
|
|
8880
8880
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
8881
8881
|
FROM intent_resolutions WHERE decision_event_id IN (${A})
|
|
8882
|
-
`).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,c=new Map,d=new Map,p=new Map,m=[],f=e?.business?.projects??[],
|
|
8882
|
+
`).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,c=new Map,d=new Map,p=new Map,m=[],f=e?.business?.projects??[],_=e?.business?.contactMap??[],b=wa(e?.business??{}),S=e?.people??[];for(let v of o){let A=null;try{A=JSON.parse(v.raw_json)}catch{}let R=ri(v.source,A,_),E=oi(v.source,A),L=Vs(A),j=v.project??Qt(A,v.subject,E),$=null,O=null;R?($=R.client,O=R.project||`${R.client}/_chat`):j&&($=wt(j,f),O=j);let U=Qu(v.source,v.intent||"",A),ce=je[U]||{label:U,color:"#6b7280"};d.has(U)||d.set(U,{id:U,label:ce.label,color:ce.color});let Z=Zs({source:v.source,channel:U,raw:A,people:S,channelLabel:N=>je[N]?.label??N}),oe="__system",ee,F=em(v.source,v.intent||"",A);if(F){oe=F.id,ee=F.kind;let N=R?.displayName||F.name;(!p.has(F.id)||R?.displayName)&&p.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else p.has("__system")||p.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(v.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let qc=`${v.id}|${N.decided_by}`,ut=i.get(qc),An=N.decided_at,Cn=ut?.resolved_at??null,ua=Cn===null,Fc=ut?.duration_ms??(ua?n-An:0),Uc=ua?"active":ut?.status==="error"||ut?.status==="fail"?"error":"completed",te,et;if($)te=$,et=O;else{let ma=b.get(N.agent_id);ma?(te=ma,et=`${ma}/_${v.source}`):(te="unmapped",et=`unmapped/_${v.source}`)}l.has(te)||l.set(te,{id:te,name:te,color:ni(te),projects:[]}),c.has(te)||c.set(te,new Set),c.get(te).add(et),m.push({id:`${v.id}|${N.decided_by}`,agentId:N.agent_id,clientId:te,projectId:et,channelId:U,initiatorId:oe,initiatorKind:ee,subject:nm(v.subject),intent:v.intent||"",startedAt:An,resolvedAt:Cn,duration:Fc,active:ua,outcome:Uc,tokens:0,inputPreview:E,system:Zu(N.agent_id,e),...L,starter:Z})}}let g=[...l.values()].map(v=>({...v,projects:[...c.get(v.id)||[]].sort()})).sort((v,A)=>v.id.localeCompare(A.id)),x=[],u=new Set;if(e){let v=e.business??{},A=R=>{let E=v.orgChart?.[R]?.role,L=E?v.roles?.[E]?.title:void 0;return typeof L=="string"&&L.trim()?L.trim():void 0};for(let[R,E]of Object.entries(e.agents||{})){let L={id:R,name:E.name||R,tier:E.tier==="claude-code"?"lead":"worker",model:E.model||"",role:E.systemPrompt?E.systemPrompt.split(/[.\n]/)[0].slice(0,60):E.tier||"",title:A(R)};x.push(L),u.add(R)}}for(let v of m)u.has(v.agentId)||(x.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),u.add(v.agentId));x.sort((v,A)=>v.id.localeCompare(A.id));let h=[],w=new Set;for(let[v,A]of Object.entries(je))h.push({id:v,label:A.label,color:A.color}),w.add(v);for(let v of d.values())w.has(v.id)||h.push(v);let y=[...p.values()];y.find(v=>v.id==="__system")||y.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:x,channels:h,initiators:y,dispatches:m,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function en(t){let e=Za();if(!e)return null;try{return si(e.db,li(),t)}finally{e.close()}}function ii(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:d}of t){l.gitlab??=d.forges?.gitlab,l.github??=d.forges?.github,d.now>s&&(s=d.now),d.windowH>i&&(i=d.windowH);for(let p of d.clients){let m=e.get(p.id);if(!m)e.set(p.id,{...p,projects:[...p.projects]});else{let f=Array.from(new Set([...m.projects,...p.projects])).sort();e.set(p.id,{...m,projects:f})}}for(let p of d.agents)a.has(p.id)||a.set(p.id,p);for(let p of d.channels)n.has(p.id)||n.set(p.id,p);for(let p of d.initiators)r.has(p.id)||r.set(p.id,p);for(let p of d.dispatches){let m=rm(p);if(m.clientId!==p.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:ni(m.clientId),projects:[]}),m.projectId!==p.projectId){let f=e.get(m.clientId);f.projects.includes(m.projectId)||e.set(m.clientId,{...f,projects:[...f.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,d)=>c.id.localeCompare(d.id)),agents:[...a.values()].sort((c,d)=>c.id.localeCompare(d.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,d)=>d.startedAt-c.startedAt)}}function rm(t){if(t.clientId!=="unmapped")return t;let e=Xa(t.inputPreview);if(!e)return t;let a=we?.business?.projects??[];return{...t,projectId:e,clientId:wt(e,a)}}async function ea(t){let e=we?.channels?.gitlab,a=await Ks(Xs(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 we=null;function li(){return we&&{...we,people:nt(we.people)}}function ci(t){we=t}async function di(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Za();if(!n)return ye(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=pi(parseInt(r.searchParams.get("hours")||"6",10));ye(e,200,await ea(si(n.db,li(),o)))}catch(r){ye(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var om=5e3;async function tn(t,e,a,n=en){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
|
|
8883
8883
|
|
|
8884
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
8884
|
+
`);let r=new URL(t.url||"/","http://_"),o=pi(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
|
|
8885
8885
|
|
|
8886
|
-
`)}catch{i()}},25e3);try{for(;!s;){try{let d=await n(o),p=d&&await
|
|
8886
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let d=await n(o),p=d&&await ea(d);if(s)break;p?(e.write(`event: snapshot
|
|
8887
8887
|
`),e.write(`data: ${JSON.stringify(p)}
|
|
8888
8888
|
|
|
8889
8889
|
`)):e.write(`event: error
|
|
@@ -8892,7 +8892,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
8892
8892
|
`)}catch(d){e.write(`event: error
|
|
8893
8893
|
data: ${JSON.stringify({error:d?.message??String(d)})}
|
|
8894
8894
|
|
|
8895
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
8895
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<om;)await new Promise(d=>setTimeout(d,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function pi(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function sm(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Ya(process.cwd(),".agentx/task-history",t,n);if(!Qa(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Ya(process.cwd(),".agentx/task-history",t,o);return Qa(s)?ai(s,e,a):null}return ai(r,e,a)}function ai(t,e,a){let n=null,r=1/0;for(let o of Ju(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Vu(Ku(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let d=Date.parse(i);if(!Number.isFinite(d))continue;l=d}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function ui(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 ye(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Za();if(!l)return ye(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 ye(e,404,{error:"event not found"}),!0;let d=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(!d)return ye(e,404,{error:"decision not found"}),!0;let p=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let f=oi(c.source,m),_=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||f,b=null,S=null;if(d.agent_id){let y=sm(d.agent_id,d.decided_at);if(y){typeof y.responseText=="string"&&(b=y.responseText);let T=y.transcript;Array.isArray(T)&&(S=T.length)}}let g=we?.business?.projects??[],x=we?.business?.contactMap??[],u=wa(we?.business??{}),h={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},w=ri(c.source,m,x);if(w)h={client:w.client,project:w.project||`${w.client}/_chat`,via:`contactMap (channel=${w.channel??"*"}${w.username?` username=${w.username}`:""}${w.chatId?` chatId=${w.chatId}`:""})`};else if(c.project||Qt(m,c.subject,f)){let y=c.project||Qt(m,c.subject,f);h={client:wt(y,g),project:y,via:c.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(d.agent_id){let y=u.get(d.agent_id);y&&(h={client:y,project:`${y}/_${c.source}`,via:`orgChart fallback (agent ${d.agent_id} reports up to a PM whose project belongs to ${y})`})}ye(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:d.decided_by,agentId:d.agent_id,outcome:d.outcome,reason:d.reason,startedAt:d.decided_at,resolvedAt:p?.resolved_at??null,durationMs:p?.duration_ms??null,input:_,response:b,transcriptLen:S,resolutionStatus:p?.status??null,resultSummary:p?.result_summary??null,attribution:h})}catch(c){ye(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as dm,readFileSync as pm}from"fs";import{resolve as fi}from"path";xt();function mi(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=im.replace(/__AGENT_ID__/g,H(e));return I({title:`AgentX \xB7 ${H(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${H(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:lm,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>${cm}</script>`})}var im=`
|
|
8896
8896
|
<!-- Breadcrumb -->
|
|
8897
8897
|
<div class="ax-crumb">
|
|
8898
8898
|
<a href="/admin">Settings</a>
|
|
@@ -9481,7 +9481,7 @@ data: ${JSON.stringify({error:d?.message??String(d)})}
|
|
|
9481
9481
|
</div>
|
|
9482
9482
|
</div>
|
|
9483
9483
|
</div>
|
|
9484
|
-
`,
|
|
9484
|
+
`,lm=`
|
|
9485
9485
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
9486
9486
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
9487
9487
|
* primitives live in components.css.ts. */
|
|
@@ -9600,7 +9600,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
9600
9600
|
|
|
9601
9601
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
9602
9602
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
9603
|
-
`,
|
|
9603
|
+
`,cm=`
|
|
9604
9604
|
const $ = (id) => document.getElementById(id);
|
|
9605
9605
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
9606
9606
|
|
|
@@ -10456,15 +10456,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
10456
10456
|
/* ===== Boot ===== */
|
|
10457
10457
|
initOptsToggles();
|
|
10458
10458
|
loadAgent();
|
|
10459
|
-
`;function
|
|
10460
|
-
`);return
|
|
10461
|
-
`);return
|
|
10459
|
+
`;function hi(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mi({agentId:a,peers:n,localToken:r}))}async function gi(t,e,a){try{let n=t.method==="GET"?void 0:await Pm(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){ta(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,p={"GET ":()=>st(i),"PATCH ":()=>um(i,n),"PATCH capability":()=>hm(i,n),"POST mcp":()=>mm(i,n),"DELETE mcp":()=>fm(i,n),"GET identity":()=>gm(i),"GET identity/file":()=>xm(i,String(o.path||"")),"PUT identity/file":()=>bm(i,n),"GET skills":()=>vm(i),"POST skills":()=>ym(i,n),"DELETE skills":()=>wm(i,n),"GET skills/tree":()=>km(i,String(o.slug||"")),"GET skills/file":()=>_m(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Sm(i,n),"GET skills/deps":()=>Em(i,String(o.slug||"")),"POST skills/install":()=>Tm(i,n,t),"POST skills/deps":()=>Am(i,n,t),"GET channels":()=>Cm(i),"GET activity":()=>Im(i,t),"GET handovers":()=>Mm(i),"POST handovers":()=>Lm(i,n),"DELETE handovers":()=>Rm(n)}[c];if(!p){ta(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await p();ta(e,200,m)}catch(n){ta(e,400,{error:n?.message||"agent op failed"})}}function xi(){let t=fi(process.cwd(),"agentx.json");return dm(t)?JSON.parse(pm(t,"utf-8")):null}function V(t){let e=xi();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 st(t){let{def:e,cfg:a}=V(t),n=e.workspace?Fe(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 um(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}=C(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:st(t)}}function mm(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}=C(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:st(t)}}function fm(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(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:st(t)}}function hm(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}=C(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:st(t)}}function gm(t){let{def:e}=V(t);return Fe(e.workspace)}function xm(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return It(a.workspace,e)}function bm(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return Mt(n.workspace,a,String(e?.content??""))}function vm(t){let{def:e}=V(t),a=Fe(e.workspace);return{skills:a.skills,workspace:a.workspace}}function ym(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Lt(n.workspace,a,{title:e?.title,content:e?.content})}function wm(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Rt(n.workspace,a)}function km(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Sr(a.workspace,e),r=Pt(a.workspace,e);return{slug:e,tree:n,deps:r}}function _m(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Er(n.workspace,e,a)}function Sm(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return Tr(r.workspace,a,n,String(e?.content??""))}function Em(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Pt(a.workspace,e)}async function Tm(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=bi(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(`
|
|
10460
|
+
`);return vi(a,r,s,`install-${n}:${Date.now()}`)}async function Am(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=bi(e?.worker),{def:o}=V(t),s=Pt(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=fi(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(`
|
|
10461
|
+
`);return vi(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function bi(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 vi(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(),d;try{d=JSON.parse(c)}catch{d={content:c}}if(!l.ok)throw new Error(d?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:d?.taskId,content:d?.content,duration:d?.duration,error:d?.error}}function Cm(t){let e=xi(),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 Im(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 an(){return new qn}function Mm(t){let e=an(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Lm(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=an().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 Rm(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:an().remove(e,a,n)?"Released":"No active handover for that chat"}}function ta(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Pm(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 Oe={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 yi=[{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 nn(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Oe)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
10462
10462
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
10463
10463
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
10464
10464
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
10465
10465
|
<main id="grid" class="ax-live__body"></main>
|
|
10466
10466
|
</div>
|
|
10467
|
-
`;return I({title:`${Oe.brand} \xB7 ${Oe.subtitle}`,activeTab:"live",subtitle:Oe.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css
|
|
10467
|
+
`;return I({title:`${Oe.brand} \xB7 ${Oe.subtitle}`,activeTab:"live",subtitle:Oe.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:$m,scripts:e+`<script>${jm}</script>`,headExtras:`<script>
|
|
10468
10468
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
10469
10469
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
10470
10470
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -10475,7 +10475,7 @@ loadAgent();
|
|
|
10475
10475
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
10476
10476
|
right.insertBefore(extras, right.firstChild);
|
|
10477
10477
|
});
|
|
10478
|
-
</script>`})}var
|
|
10478
|
+
</script>`})}var $m=`
|
|
10479
10479
|
/* --- Page frame --- */
|
|
10480
10480
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
10481
10481
|
|
|
@@ -10682,7 +10682,7 @@ loadAgent();
|
|
|
10682
10682
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
10683
10683
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
10684
10684
|
}
|
|
10685
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
10685
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,jm=`
|
|
10686
10686
|
'use strict';
|
|
10687
10687
|
|
|
10688
10688
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -11253,7 +11253,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11253
11253
|
});
|
|
11254
11254
|
}
|
|
11255
11255
|
|
|
11256
|
-
`;var
|
|
11256
|
+
`;var wi=`
|
|
11257
11257
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
11258
11258
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
11259
11259
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -11427,7 +11427,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11427
11427
|
.mx-summary{max-width:56vw}
|
|
11428
11428
|
}
|
|
11429
11429
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
11430
|
-
`;var
|
|
11430
|
+
`;var ki=`<script>
|
|
11431
11431
|
window.MX=(function(){
|
|
11432
11432
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
11433
11433
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -11536,7 +11536,7 @@ window.MX=(function(){
|
|
|
11536
11536
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
11537
11537
|
setHealth:setHealth,get:get};
|
|
11538
11538
|
})();
|
|
11539
|
-
</script>`;var
|
|
11539
|
+
</script>`;var _i=`<script>
|
|
11540
11540
|
window.MXD=(function(){
|
|
11541
11541
|
function el(id){return document.getElementById(id)}
|
|
11542
11542
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -11750,7 +11750,7 @@ window.MXD=(function(){
|
|
|
11750
11750
|
|
|
11751
11751
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
11752
11752
|
})();
|
|
11753
|
-
</script>`;var
|
|
11753
|
+
</script>`;var Si=`<script>
|
|
11754
11754
|
(function(){
|
|
11755
11755
|
var LANES=[
|
|
11756
11756
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -12066,7 +12066,7 @@ window.MXD=(function(){
|
|
|
12066
12066
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
12067
12067
|
load();
|
|
12068
12068
|
})();
|
|
12069
|
-
</script>`;var
|
|
12069
|
+
</script>`;var Ei=`<script>
|
|
12070
12070
|
(function(){
|
|
12071
12071
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
12072
12072
|
var esc=MX.esc;
|
|
@@ -12244,7 +12244,7 @@ window.MXD=(function(){
|
|
|
12244
12244
|
}
|
|
12245
12245
|
load();setInterval(load,5000);
|
|
12246
12246
|
})();
|
|
12247
|
-
</script>`;var
|
|
12247
|
+
</script>`;var Ti=`
|
|
12248
12248
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
12249
12249
|
.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}
|
|
12250
12250
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -12285,7 +12285,7 @@ window.MXD=(function(){
|
|
|
12285
12285
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
12286
12286
|
.mx-rt-name{max-width:100%}
|
|
12287
12287
|
}
|
|
12288
|
-
`,
|
|
12288
|
+
`,Ai=`<script>
|
|
12289
12289
|
(function(){
|
|
12290
12290
|
var root=document.getElementById('mx-routines');
|
|
12291
12291
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -12412,7 +12412,7 @@ window.MXD=(function(){
|
|
|
12412
12412
|
syncBar();
|
|
12413
12413
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
12414
12414
|
})();
|
|
12415
|
-
</script>`;var
|
|
12415
|
+
</script>`;var Ci=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Ii=`<script>
|
|
12416
12416
|
(function(){
|
|
12417
12417
|
var root=document.getElementById('mx-feed');
|
|
12418
12418
|
if(!root)return;
|
|
@@ -12487,12 +12487,12 @@ window.MXD=(function(){
|
|
|
12487
12487
|
}
|
|
12488
12488
|
load();setInterval(load,5000);
|
|
12489
12489
|
})();
|
|
12490
|
-
</script>`;var ne={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 re(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var
|
|
12490
|
+
</script>`;var ne={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 re(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Om=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Nm=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Dm=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Mi(t){let e=ue({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">
|
|
12491
12491
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
12492
|
-
${
|
|
12492
|
+
${Nm.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("")}
|
|
12493
12493
|
</div>
|
|
12494
12494
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
12495
|
-
${
|
|
12495
|
+
${Dm.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
12496
12496
|
</div>
|
|
12497
12497
|
</div>
|
|
12498
12498
|
<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">
|
|
@@ -12545,7 +12545,7 @@ window.MXD=(function(){
|
|
|
12545
12545
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
12546
12546
|
${re(ne.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>')}
|
|
12547
12547
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
12548
|
-
${
|
|
12548
|
+
${Om.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12549
12549
|
</div>
|
|
12550
12550
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
12551
12551
|
</section>
|
|
@@ -12553,7 +12553,7 @@ window.MXD=(function(){
|
|
|
12553
12553
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
12554
12554
|
${re(ne.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>')}
|
|
12555
12555
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
12556
|
-
${
|
|
12556
|
+
${Ci.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12557
12557
|
</div>
|
|
12558
12558
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
12559
12559
|
</section>
|
|
@@ -12586,7 +12586,7 @@ window.MXD=(function(){
|
|
|
12586
12586
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
12587
12587
|
</header>
|
|
12588
12588
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
12589
|
-
</aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
12589
|
+
</aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:wi+Ti,scripts:ki+Hm+_i+Si+Ai+Ei+Ii})}var Hm=`<script>
|
|
12590
12590
|
(function(){
|
|
12591
12591
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
12592
12592
|
var range=document.getElementById('mx-range');
|
|
@@ -12614,10 +12614,10 @@ window.MXD=(function(){
|
|
|
12614
12614
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
12615
12615
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
12616
12616
|
})();
|
|
12617
|
-
</script>`;function
|
|
12617
|
+
</script>`;function Li(t){let e=ue({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."})+`
|
|
12618
12618
|
<div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
|
|
12619
12619
|
<ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
|
|
12620
|
-
<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 I({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:
|
|
12620
|
+
<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 I({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:Bm,scripts:`<script>${zm}</script>`})}var Bm=`
|
|
12621
12621
|
.gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
|
|
12622
12622
|
.gm-empty { color: var(--ax-text-2); }
|
|
12623
12623
|
.gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
@@ -12635,7 +12635,7 @@ window.MXD=(function(){
|
|
|
12635
12635
|
.gm-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
12636
12636
|
.gm-msg.is-bad { color: var(--ax-red-ink); }
|
|
12637
12637
|
.gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
12638
|
-
`,
|
|
12638
|
+
`,zm=`
|
|
12639
12639
|
(function () {
|
|
12640
12640
|
var list = document.getElementById('gm-list');
|
|
12641
12641
|
var msg = document.getElementById('gm-msg');
|
|
@@ -12682,7 +12682,7 @@ window.MXD=(function(){
|
|
|
12682
12682
|
load();
|
|
12683
12683
|
setInterval(load, 30000);
|
|
12684
12684
|
})();
|
|
12685
|
-
`;async function
|
|
12685
|
+
`;async function Ri(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 qm(s,e.days)}function qm(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,d=0,p=0,m=0,f=0,_=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 x of g.days){let u=n.get(x.day)||{day:x.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])u[h][0]+=x[h]?.[0]||0,u[h][1]+=x[h]?.[1]||0;n.set(x.day,u)}for(let x of g.origins){let u=r.get(x.channel)||{channel:x.channel,runs:0,errors:0,hours:0};u.runs+=x.runs,u.errors+=x.errors,u.hours+=x.hours,r.set(x.channel,u)}for(let x of g.causes){let u=o.get(x.cause)||{cause:x.cause,count:0,agents:[],example:""};u.count+=x.count;for(let h of x.agents)u.agents.includes(h)||u.agents.push(h);u.example||(u.example=x.example),o.set(x.cause,u)}for(let x of g.rotations.byReason)s.set(x.reason,(s.get(x.reason)||0)+x.count);c+=g.rotations.total,d+=g.rotations.tokenSum||0,p+=g.rotations.tokenSamples||0,m=Math.max(m,g.rotations.maxTokens),f+=g.retention.traces,_+=g.retention.tracesWithSteps;for(let x of g.jobs)i.push({...x,node:S.name,nodeUrl:S.url});for(let x of g.threads)l.push({...x,node:S.name,nodeUrl:S.url})}let b=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:b.length?Math.min(...b):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:d,tokenSamples:p,maxTokens:m},retention:{traces:f,tracesWithSteps:_}}}async function Pi(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 $i(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 Fm(s,e.day)}function Fm(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 ji(t={}){let e=`
|
|
12686
12686
|
<select id="boardPicker" title="Switch board"></select>
|
|
12687
12687
|
<div class="search">
|
|
12688
12688
|
<span class="icon">\u2315</span>
|
|
@@ -12783,7 +12783,7 @@ window.MXD=(function(){
|
|
|
12783
12783
|
</footer>
|
|
12784
12784
|
</div>
|
|
12785
12785
|
</div>
|
|
12786
|
-
<script src="/sortable.min.js"></script>`;return I({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:
|
|
12786
|
+
<script src="/sortable.min.js"></script>`;return I({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Um,scripts:`<script>${Wm}</script>`,headExtras:`<script>
|
|
12787
12787
|
// The boards page has its own connection dot + wants body height:100%
|
|
12788
12788
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
12789
12789
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -12799,7 +12799,7 @@ window.MXD=(function(){
|
|
|
12799
12799
|
right.insertBefore(dot, right.firstChild);
|
|
12800
12800
|
}
|
|
12801
12801
|
});
|
|
12802
|
-
</script>`})}var
|
|
12802
|
+
</script>`})}var Um=`
|
|
12803
12803
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
12804
12804
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
12805
12805
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -13052,7 +13052,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
13052
13052
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
13053
13053
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
13054
13054
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
13055
|
-
`,
|
|
13055
|
+
`,Wm=`
|
|
13056
13056
|
'use strict';
|
|
13057
13057
|
const state = {
|
|
13058
13058
|
boards: [], current: null, items: {},
|
|
@@ -14105,9 +14105,9 @@ function appendEvents(events) {
|
|
|
14105
14105
|
}
|
|
14106
14106
|
|
|
14107
14107
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
14108
|
-
`;function
|
|
14108
|
+
`;function Oi(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
14109
14109
|
<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>
|
|
14110
|
-
${
|
|
14110
|
+
${yi.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${H(n.alias)}</span>`:"";return`<article class="term"><h3>${H(n.term)}${r}</h3><p>${H(n.definition)}</p></article>`}).join("")}`;return I({title:`${Oe.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Gm})}var Gm=`
|
|
14111
14111
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
14112
14112
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14113
14113
|
.lead {
|
|
@@ -14137,7 +14137,7 @@ article.term .alias {
|
|
|
14137
14137
|
}
|
|
14138
14138
|
article.term p {
|
|
14139
14139
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
14140
|
-
}`;function
|
|
14140
|
+
}`;function Ni(t={}){let e=`<div class="ax-wf__root">
|
|
14141
14141
|
<aside class="ax-wf__list">
|
|
14142
14142
|
<header>
|
|
14143
14143
|
<h2>Workflows</h2>
|
|
@@ -14214,7 +14214,7 @@ article.term p {
|
|
|
14214
14214
|
</aside>
|
|
14215
14215
|
</div>
|
|
14216
14216
|
|
|
14217
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return I({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
14217
|
+
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return I({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Xm,scripts:`<script>${q({workflowHealth:Yn})}${Km}</script>`})}var Xm=`
|
|
14218
14218
|
.ax-wf__root {
|
|
14219
14219
|
display: grid;
|
|
14220
14220
|
grid-template-columns: 340px 1fr;
|
|
@@ -14598,7 +14598,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14598
14598
|
font-size: 12px; z-index: 50;
|
|
14599
14599
|
}
|
|
14600
14600
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
14601
|
-
`,
|
|
14601
|
+
`,Km=`
|
|
14602
14602
|
(() => {
|
|
14603
14603
|
const $ = (sel) => document.querySelector(sel)
|
|
14604
14604
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -15387,7 +15387,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15387
15387
|
setInterval(refresh, 15000)
|
|
15388
15388
|
})
|
|
15389
15389
|
})();
|
|
15390
|
-
`;function
|
|
15390
|
+
`;function Di(t={}){let e=`<div class="ax-proc__root">
|
|
15391
15391
|
<header class="ax-proc__header">
|
|
15392
15392
|
<h1>Procedures</h1>
|
|
15393
15393
|
<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>
|
|
@@ -15431,7 +15431,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15431
15431
|
<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>
|
|
15432
15432
|
<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>
|
|
15433
15433
|
</section>
|
|
15434
|
-
</div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
15434
|
+
</div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Jm,scripts:`<script>${Vm}</script>`})}var Jm=`
|
|
15435
15435
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
15436
15436
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
15437
15437
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -15457,7 +15457,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15457
15457
|
.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); }
|
|
15458
15458
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
15459
15459
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
15460
|
-
`,
|
|
15460
|
+
`,Vm=`
|
|
15461
15461
|
(function(){
|
|
15462
15462
|
function $(sel){ return document.querySelector(sel) }
|
|
15463
15463
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -15557,7 +15557,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15557
15557
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
15558
15558
|
else bootAll()
|
|
15559
15559
|
})();
|
|
15560
|
-
`;function
|
|
15560
|
+
`;function Hi(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
15561
15561
|
data-task-id="${H(t.taskId)}"
|
|
15562
15562
|
data-agent-id="${H(t.agentId)}"
|
|
15563
15563
|
data-node-url="${H(t.nodeUrl)}"
|
|
@@ -15600,7 +15600,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15600
15600
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
15601
15601
|
</div>
|
|
15602
15602
|
</footer>
|
|
15603
|
-
</div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15603
|
+
</div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ym,scripts:`<script>${Qm}</script>`})}var Ym=`
|
|
15604
15604
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
15605
15605
|
the sticky topbar. Breathe. */
|
|
15606
15606
|
.ax-task-page {
|
|
@@ -15742,7 +15742,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15742
15742
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
15743
15743
|
}
|
|
15744
15744
|
|
|
15745
|
-
`,
|
|
15745
|
+
`,Qm=`
|
|
15746
15746
|
(function () {
|
|
15747
15747
|
var root = document.querySelector('.ax-task-page');
|
|
15748
15748
|
if (!root) return;
|
|
@@ -16127,7 +16127,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16127
16127
|
});
|
|
16128
16128
|
|
|
16129
16129
|
})();
|
|
16130
|
-
`;function
|
|
16130
|
+
`;function Bi(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
16131
16131
|
data-agent-id="${H(t.agentId)}"
|
|
16132
16132
|
data-agent-name="${H(e)}"
|
|
16133
16133
|
data-node-url="${H(t.nodeUrl)}">
|
|
@@ -16156,7 +16156,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16156
16156
|
<div class="ax-history__list" id="hist-list">
|
|
16157
16157
|
<div class="ax-history__empty">loading\u2026</div>
|
|
16158
16158
|
</div>
|
|
16159
|
-
</div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
16159
|
+
</div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Zm,scripts:`<script>${ef}</script>`})}var Zm=`
|
|
16160
16160
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
16161
16161
|
flush against the sticky topbar. */
|
|
16162
16162
|
.ax-history {
|
|
@@ -16208,7 +16208,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16208
16208
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
16209
16209
|
}
|
|
16210
16210
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
16211
|
-
`,
|
|
16211
|
+
`,ef=`
|
|
16212
16212
|
(function () {
|
|
16213
16213
|
var root = document.querySelector('.ax-history');
|
|
16214
16214
|
if (!root) return;
|
|
@@ -16308,31 +16308,31 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16308
16308
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
16309
16309
|
});
|
|
16310
16310
|
})();
|
|
16311
|
-
`;function
|
|
16311
|
+
`;function qi(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"])?P(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return Je(t,e,l=>zi(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:af(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return P(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Je(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:c})}):P(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"])?P(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Je(t,e,l=>{try{let c=a.layouts.save(s,l);return P(e,200,{layout:c})}catch(c){return P(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Je(t,e,l=>{let c=va.safeParse(l);if(!c.success)return P(e,200,{ok:!1,issues:c.error.issues.map(p=>({path:p.path.join("."),message:p.message}))});let d=ya(c.data).map(p=>({path:"",message:p}));return P(e,200,{ok:d.length===0,issues:d,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?P(e,200,{workflow:l}):P(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Je(t,e,d=>zi(e,a,d,{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),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var tf=["mesh"];function zi(t,e,a,n){let r=va.safeParse(a);if(!r.success)return P(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=ya(o);if(s.length>0)return P(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return P(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return P(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 d of tf)!(d in l)&&d in c&&(o[d]=c[d])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),d=l?.yamlPath,p=!!d||/yaml round-trip failed/.test(c);return P(t,p?409:500,{error:p?"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:p?"yaml-authored":"save-failed",...d?{path:d}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function af(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,d=r.get("summary")==="1"||r.get("summary")==="true",p=a.runs.list({workflowId:c,limit:l});if(!d)return P(e,200,{runs:p});let m=p.map(f=>({id:f.id,workflowId:f.workflowId,workflowVersion:f.workflowVersion,homeNode:f.homeNode,status:f.status,pending:f.pending,entityRef:f.entityRef,history:(f.history||[]).slice(-5),parentRunId:f.parentRunId,parentNodeId:f.parentNodeId,rootRunId:f.rootRunId,depth:f.depth,createdAt:f.createdAt,updatedAt:f.updatedAt}));return P(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Je(t,e,c=>{let d=c?.status;return d!=="paused"&&d!=="running"&&d!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,d)?P(e,200,{ok:!0,runId:l,status:d}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return nf(t,e,a,l);let c=a.runs.get(l);return c?P(e,200,{run:c}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function nf(t,e,a,n){let r=a.runs.get(n);if(!r)return P(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)}
|
|
16312
16312
|
|
|
16313
16313
|
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(d);try{e.end()}catch{}};t.on("close",s);let i=p=>{if(!o)try{e.write(`data: ${JSON.stringify(p)}
|
|
16314
16314
|
|
|
16315
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,d=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==c&&(c=p.updatedAt,i(p))},2e3);return!0}function
|
|
16315
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,d=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==c&&(c=p.updatedAt,i(p))},2e3);return!0}function Je(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){P(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{P(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{P(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>P(e,400,{error:"body read failed",message:r.message})),!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Zf}from"fs";import{createRequire as eh}from"module";var rf=2048,Fi=/^[A-Za-z0-9_-]{8,256}$/;async function Ui(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(f=>f.publicKey===i).length:0,...s?s.prefs.all(r.id):of()});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 qe(t)}catch(f){return Y(e,400,{error:f.message})}if(a==="/api/app/push/prefs"){let f=Object.keys(pe).filter(g=>c[pe[g].field]!==void 0),_=f.map(g=>pe[g].field).join(", "),b=Object.values(pe).map(g=>g.field).join(" or ");if(f.length===0)return Y(e,400,{error:`send ${b}, true or false`});if(f.some(g=>typeof c[pe[g].field]!="boolean"))return Y(e,400,{error:`${_} must be true or false`});let S={};for(let g of f)s.prefs.set(r.id,g,c[pe[g].field]),S[pe[g].field]=c[pe[g].field];return Y(e,200,{ok:!0,...S})}let d=sf(c.endpoint,o.allowedHosts);if(!d){let f="";try{f=new URL(String(c.endpoint)).hostname}catch{}return Y(e,400,{error:`not a known push service${f?`: ${f}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return Y(e,200,{ok:!0,removed:s.unsubscribe(d,r.id)});let p=c.keys?.p256dh,m=c.keys?.auth;return typeof p!="string"||!Fi.test(p)||typeof m!="string"||!Fi.test(m)?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:d,p256dh:p,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function of(){let t={};for(let e of Object.values(pe))t[e.field]=e.default;return t}function sf(t,e){if(typeof t!="string"||t.length>rf)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}jn();var Gi=50,lf=280;async function Xi(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=cf(await o.recent(Gi))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Wi(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Wi(e,404,{error:"not found"})}function Ki(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||W(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=ht();return r?new Ir(r):null}}}function cf(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:rn(typeof n.summary=="string"?n.summary:"",lf),by:typeof n.agentId=="string"?rn(n.agentId,100):null,node:rn(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,Gi)}function rn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Wi(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var df="operator",pf=50,Ji=4,Vi=500;function uf(t){let e={channel:"app",chatId:t.chatId,sender:df,...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 Yi(t,e,a,n){let{path:r,body:o}=uf(e),s="",i=!1,l=[],c=new Map,d=(p,m,f)=>{let _=p!=="done",b=i?{text:yt(m,_),artifacts:[]}:vt(m,de.perMessage,_),{cleanText:S,ui:g}=p==="done"?kt(b.text):{cleanText:b.text,ui:void 0},x=i?void 0:on(g);return{status:p,text:S,tools:l,files:b.artifacts,...x?{ui:x}:{},...f?{error:f}:{}}};try{let p=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(!p.ok||!p.body){let m=await p.json().then(f=>f?.error).catch(()=>"");return d("error",s,m||`AgentX answered HTTP ${p.status}.`)}for await(let m of ff(p.body)){n(m.event,m.data);let f=m.data??{};if(m.event==="start")i=f.rich===!1;else if(m.event==="text"&&typeof f.text=="string")s+=f.text;else if(m.event==="tool"&&f.status==="start"&&l.length<pf){let _={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};l.push(_),f.id&&c.set(String(f.id),_)}else if(m.event==="tool"&&f.status==="result"&&f.error===!0&&c.has(String(f.id)))c.get(String(f.id)).error=!0;else{if(m.event==="done")return d("done",typeof f.content=="string"&&f.content?f.content:s);if(m.event==="error")return d("error",s,mf(f.error))}}return a.aborted?d("stopped",s):d("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?d("stopped",s):d("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function mf(t){let e=String(t||"The agent could not answer.");return Fn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function on(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,Ji).map(s=>s.slice(0,Vi));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Ji).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Vi)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*ff(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,`
|
|
16316
16316
|
`);let s;for(;(s=n.indexOf(`
|
|
16317
16317
|
|
|
16318
16318
|
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let d of i.split(`
|
|
16319
16319
|
`))d.startsWith("event:")?l=d.slice(6).trim():d.startsWith("data:")&&c.push(d.slice(5).replace(/^ /,""));if(c.length)try{yield{event:l,data:JSON.parse(c.join(`
|
|
16320
|
-
`))}}catch{}}}}finally{e.releaseLock()}}var
|
|
16320
|
+
`))}}catch{}}}}finally{e.releaseLock()}}var aa=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}
|
|
16321
16321
|
data: ${JSON.stringify(s)}
|
|
16322
16322
|
|
|
16323
16323
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
16324
16324
|
|
|
16325
|
-
`)},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
|
|
16326
|
-
`)){let n=
|
|
16327
|
-
`).map(
|
|
16325
|
+
`)},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 Zi(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=hf(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:sn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function sn(t,e=120){for(let a of t.split(`
|
|
16326
|
+
`)){let n=el(a);if(n)return ln(n,e)}return""}function hf(t,e=120){let a=t.split(`
|
|
16327
|
+
`).map(el).filter(Boolean);return a.length?ln(a[a.length-1],e):""}function el(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ln(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var na=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 ra(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Qi=140;function oa(t,e,a,n,r){let o=a==="error"?`Could not answer: ${sn(r||"",Qi-18)||"something went wrong."}`:sn(n,Qi)||"Answered.";return{deviceId:t,title:ln(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var al=8e3,xf=/^[A-Za-z0-9_.:-]{1,64}$/,Ne=new Map,cn=new Map,un=new na;function nl(){return un}async function rl(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??un;if(n==="GET"&&a==="/api/app/agents")return B(e,200,{nodes:await ol(o)});let i=o.store();if(!i)return B(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),B(e,200,{conversations:Zi(r.id,yf(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),B(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return B(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let d=i.get(r.id,decodeURIComponent(l[1]));if(!d)return B(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,d.id);let p=Ne.get(d.id);return B(e,200,{...d,running:!!p,...p?{partial:{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=d&&Ne.get(d.id);if(!d||!p)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,d.id),sl(e);let{id:m,title:f,node:_,nodeName:b,agent:S,agentName:g}=d;return e.write(dn("conversation",{id:m,title:f,node:_,nodeName:b,agent:S,agentName:g})),e.write(dn("resume",{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return B(e,404,{error:"not found"});let c;try{c=await qe(t,64*1024)}catch(d){return B(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=i.get(r.id,String(c.conversationId??""));if(!d)return B(e,404,{error:"no such conversation"});let p=Ne.get(d.id);return p?(p.ac.abort(),pn(d,o,r.name),B(e,200,{stopped:!0})):await pn(d,o,r.name)?B(e,200,{stopped:!0}):B(e,404,{error:"nothing is running in this conversation"})}return await vf(e,c,r,i,o),!0}function bf(t,e,a){let n=Ve(e.url),r=new Set,o=[];for(let s of t){let i=Ve(s.url),l=a.find(p=>Ve(p.peerUrl)===i);l&&r.add(l.peer);let c=i===n,d=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:d.map(p=>{let m=Array.isArray(p.runningTasks)?p.runningTasks.length:0;return{id:p.id,name:p.name||p.id,busy:m>0||(p.active??0)>0,running:m,...p.color?{color:p.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 ol(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return bf(e.nodes,t.daemon,a)}async function vf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>al){B(t,400,{error:`message must be 1\u2013${al} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){B(t,404,{error:"no such conversation"});return}}else{let _=typeof e.node=="string"?e.node:"",b=typeof e.agent=="string"?e.agent:"";if(!xf.test(b)){B(t,400,{error:"pick an agent"});return}let S=(await ol(r)).find(x=>x.target===_);if(!S){B(t,400,{error:`unknown node "${_}"`});return}if(!S.online){B(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(x=>x.id===b);if(!g){B(t,400,{error:`no agent "${b}" on ${S.name}`});return}s=n.create(a.id,{node:_,nodeName:S.name,agent:b,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Ne.has(s.id)){B(t,409,{error:"The agent is still answering in this conversation."});return}let i=new aa(r.orphanLimitMs??18e5);Ne.set(s.id,i);let{id:l,title:c,node:d,nodeName:p,agent:m,agentName:f}=s;cn.set(l,{id:l,deviceId:a.id,title:c,agent:m,...f?{agentName:f}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),sl(t),t.write(dn("conversation",{id:l,title:c,node:d,nodeName:p,agent:m,agentName:f})),i.attach(t);try{let _=e.spoken===!0,b=await Yi(r.daemon,{node:d,agent:m,message:o,chatId:`app:${l}`,spoken:_},i.ac.signal,(u,h)=>i.broadcast(u,h));i.orphaned&&(b.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,pn(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:b.text,status:b.status,at:Date.now(),...b.error?{error:b.error}:{},...b.ui?{ui:b.ui}:{},...b.tools.length?{tools:b.tools}:{}},b.files)??[];i.broadcast("final",{status:b.status,content:b.text,...b.error?{error:b.error}:{},...b.ui?{ui:b.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let x={status:b.status,attached:g,appOpen:(r.presence??un).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&ra(x)&&r.notifyFinish(oa(a.id,s,b.status,b.text,b.error)).catch(()=>{})}finally{Ne.delete(l),cn.delete(l),i.finish()}}function yf(){let t=[];for(let[e,a]of cn){let n=Ne.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function sl(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function dn(t,e){return`event: ${t}
|
|
16328
16328
|
data: ${JSON.stringify(e)}
|
|
16329
16329
|
|
|
16330
|
-
`}async function dn(t,e,a){try{let n=Je(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Je(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Je(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 Je(t){return t.replace(/\/+$/,"")}function B(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as vf}from"stream";var yf=/^\/api\/app\/files\/([^/]+)$/,wf=15e3;async function il(t,e,a,n,r,o){let s=yf.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return De(e,405,{error:"GET only"});let i=o.store();if(!i)return De(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 De(e,404,{error:"no such file"});let d=await kf(c.node,o);if(!d)return De(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let p=new AbortController;e.on("close",()=>p.abort());let m=setTimeout(()=>p.abort(),wf),f;try{let x=new URLSearchParams({agent:c.agent,file:c.path});f=await fetch(`${d.url}${dr}?${x}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return De(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(f.status!==200&&f.status!==206){let x=await f.json().then(h=>h?.error).catch(()=>""),u=[403,404,413,415,416].includes(f.status)?f.status:502;return De(e,u,{error:x||`The computer that made this file answered HTTP ${f.status}.`})}let S=Number(f.headers.get("content-length")||0);if(S>de.bytes)return p.abort(),De(e,413,{error:"the file is too large"});let b=f.headers.get("content-range");if(e.writeHead(f.status,{...pr(c.mime,c.name,c.kind),...f.headers.get("content-length")?{"Content-Length":String(S)}:{},...f.status===206&&b?{"Content-Range":b}:{}}),n==="HEAD"||!f.body)return e.end(),!0;let E=0,g=vf.fromWeb(f.body);return g.on("data",x=>{E+=x.length,E>de.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function kf(t,e){if(t==="local")return{url:sl(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=sl(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function sl(t){return t.replace(/\/+$/,"")}function De(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 cl=8e3;async function dl(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 f=String(t.headers["content-type"]||"");if(!yr(f))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let S=vr(t.headers["x-audio-duration-ms"]);if(S)return t.resume(),Q(e,S.status,{error:S.error});let b=await Ce(t,br.bytes);if(!b)return Q(e,413,{error:wr()});if(!b.length)return Q(e,400,{error:"The recording is empty."});let E={"Content-Type":f,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return ll(e,o.daemon,"/voice/transcribe",b,E,18e4)}let s,i=await Ce(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 d=typeof s?.text=="string"?s.text.slice(0,cl):"";if(!d.trim())return Q(e,400,{error:"text is required"});if(!Sf(c.messages,d))return Q(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:p,...c.node!=="local"?{peer:c.node}:{}};return ll(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function ll(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(_f(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 _f(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Sf(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===cl&&a.content.startsWith(e)))}var Ef=new Set(["ring","offer","answer","ice","hangup"]),Ve=/^[A-Za-z0-9_-]{4,64}$/,Tf=128*1024;async function ul(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 M(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return M(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return M(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),d=et(r.nodeName),p=(Array.isArray(c.peers)?c.peers:[]).filter(f=>et(String(f?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(f=>f&&typeof f.id=="string").map(f=>({id:f.id,name:typeof f.name=="string"&&f.name?f.name:f.id}));return M(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:p,agents:m,camera:c.camera??null})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,Tf);if(!l)return M(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let d=Cf(c,r.nodeName);if(typeof d=="string")return M(e,400,{error:d});let p=ml(d.to);if(p&&d.kind==="ring"){let m=await He(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:p});return M(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(d),signal:AbortSignal.timeout(15e3)}),f=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:f?.error||`AgentX answered HTTP ${m.status}.`})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Ve.test(l)?If(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,4096);if(!l)return M(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Ve.test(d))return M(e,400,{error:"callId is required"});let p=typeof c?.note=="string"?c.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:p},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await pl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ve.test(c))return M(e,400,{error:"callId is required"});let d=Number(l.seconds??0);if(!Number.isFinite(d)||d<0)return M(e,400,{error:"seconds must be 0 or more"});let p=typeof l.note=="string"?l.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/stream`,{seconds:d,note:p});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await pl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ve.test(c))return M(e,400,{error:"callId is required"});let d=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(c)}`);if(d.status>=300)return M(e,d.status,{error:d.body.error});let p=(Array.isArray(d.body.watch?.replies)?d.body.watch.replies:[]).find(m=>m&&m.at===l.at);return!p||typeof p.text!="string"?M(e,404,{error:"no such answer on this share"}):Af(e,o,s,{agent:String(d.body.watch.agentId??""),text:p.text})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await He(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.createdAt}));return M(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 M(e,405,{error:"POST"});let l=await He(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Ve.test(l))return M(e,400,{error:"callId is required"});let c=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return M(e,404,{error:"not found"})}function ml(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function He(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."}}}}async function pl(t,e){let a=await Ce(t,e);if(!a)return null;try{let n=JSON.parse(a.toString("utf8")||"{}");return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}async function Af(t,e,a,n){try{let r=await fetch(`${e}/voice/speak`,{method:"POST",headers:{"Content-Type":"application/json",...a},body:JSON.stringify(n),signal:AbortSignal.timeout(9e4)}),o=r.headers.get("content-type")||"";if(r.ok&&o.startsWith("audio/")){let i=Buffer.from(await r.arrayBuffer());return t.writeHead(200,{"Content-Type":o,"Content-Length":String(i.length),"Cache-Control":"no-store"}),t.end(i),!0}let s=await r.json().catch(()=>({}));return r.ok||typeof s?.text=="string"?M(t,200,{text:typeof s?.text=="string"?s.text:n.text}):M(t,200,{text:n.text,error:s?.error||`AgentX answered HTTP ${r.status}.`})}catch{return M(t,200,{text:n.text,error:"Could not reach AgentX on this computer."})}}function Cf(t,e){let a=String(t?.kind??"");if(!Ef.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Ve.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:")&&!ml(r))return"to must be bot:<agent id> for an agent";if(et(r)===et(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 If(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 M(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?M(e,503,{error:"Calls are off on this computer."}):M(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 M(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{mkdirSync as Mf,readFileSync as Lf,renameSync as Rf,writeFileSync as Pf}from"fs";import{dirname as $f,isAbsolute as jf,resolve as Of}from"path";import{randomBytes as Nf}from"crypto";var fl=60,hl=500,Df=200,bl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Hf=/^[A-Za-z0-9_-]{8,64}$/,Bf=/^[A-Za-z0-9._-]{1,64}$/;function vl(t,e){return jf(e)?e:Of(t,e)}function gl(t){return`${t}_${Nf(6).toString("hex")}`}function xl(){return{places:[],rules:[],seen:[]}}function yl(t,e){let a=typeof t.name=="string"?t.name.trim():"";if(!a)return{ok:!1,error:"Give the place a name."};if([...a].length>fl)return{ok:!1,error:`Keep the name under ${fl} characters.`};let n=Number(t.lat),r=Number(t.lng);if(t.lat===void 0||t.lat===""||!Number.isFinite(n)||n<-90||n>90)return{ok:!1,error:"Latitude must be a number from -90 to 90."};if(t.lng===void 0||t.lng===""||!Number.isFinite(r)||r<-180||r>180)return{ok:!1,error:"Longitude must be a number from -180 to 180."};let o=t.radius===void 0||t.radius===""?e.defaultRadiusMeters:Math.round(Number(t.radius));if(!Number.isFinite(o)||o<e.minRadiusMeters||o>e.maxRadiusMeters)return{ok:!1,error:`The radius must be from ${e.minRadiusMeters} to ${e.maxRadiusMeters} metres.`};let s=i=>Math.round(i*1e6)/1e6;return{ok:!0,value:{name:a,lat:s(n),lng:s(r),radius:o}}}function wl(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!bl.test(a))return{ok:!1,error:"Pick a place."};let n=t.on===void 0?"enter":t.on;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"on must be enter or exit."};let r=typeof t.text=="string"?t.text.trim():"";if(!r)return{ok:!1,error:"Write what to remind you of."};if([...r].length>hl)return{ok:!1,error:`Keep it under ${hl} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Bf.test(o)||!e(o))?{ok:!1,error:`There is no agent called ${o.slice(0,64)} on this computer.`}:t.repeat!==void 0&&typeof t.repeat!="boolean"?{ok:!1,error:"repeat must be true or false."}:{ok:!0,value:{placeId:a,on:n,text:r,...o?{agent:o}:{},repeat:t.repeat===!0}}}function kl(t){let e=typeof t.id=="string"?t.id:"";if(!Hf.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!bl.test(a))return{ok:!1,error:"place must be a place id"};let n=t.transition;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"transition must be enter or exit"};let r=typeof t.time=="number"?t.time:typeof t.time=="string"?Date.parse(t.time):NaN;return Number.isFinite(r)?{ok:!0,value:{id:e,place:a,transition:n,time:r}}:{ok:!1,error:"time must be a timestamp"}}var oa=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(Lf(this.path,"utf-8"));return!e||typeof e!="object"?xl():{places:Array.isArray(e.places)?e.places:[],rules:Array.isArray(e.rules)?e.rules:[],seen:Array.isArray(e.seen)?e.seen.filter(a=>typeof a=="string"):[]}}catch{return xl()}}write(e){Mf($f(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Pf(a,JSON.stringify(e,null,2)+`
|
|
16331
|
-
`,{mode:384}),
|
|
16332
|
-
`)}async function
|
|
16330
|
+
`}async function pn(t,e,a){try{let n=Ve(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Ve(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ve(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 Ve(t){return t.replace(/\/+$/,"")}function B(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as wf}from"stream";var kf=/^\/api\/app\/files\/([^/]+)$/,_f=15e3;async function ll(t,e,a,n,r,o){let s=kf.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return De(e,405,{error:"GET only"});let i=o.store();if(!i)return De(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 De(e,404,{error:"no such file"});let d=await Sf(c.node,o);if(!d)return De(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let p=new AbortController;e.on("close",()=>p.abort());let m=setTimeout(()=>p.abort(),_f),f;try{let x=new URLSearchParams({agent:c.agent,file:c.path});f=await fetch(`${d.url}${pr}?${x}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return De(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(f.status!==200&&f.status!==206){let x=await f.json().then(h=>h?.error).catch(()=>""),u=[403,404,413,415,416].includes(f.status)?f.status:502;return De(e,u,{error:x||`The computer that made this file answered HTTP ${f.status}.`})}let _=Number(f.headers.get("content-length")||0);if(_>de.bytes)return p.abort(),De(e,413,{error:"the file is too large"});let b=f.headers.get("content-range");if(e.writeHead(f.status,{...ur(c.mime,c.name,c.kind),...f.headers.get("content-length")?{"Content-Length":String(_)}:{},...f.status===206&&b?{"Content-Range":b}:{}}),n==="HEAD"||!f.body)return e.end(),!0;let S=0,g=wf.fromWeb(f.body);return g.on("data",x=>{S+=x.length,S>de.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function Sf(t,e){if(t==="local")return{url:il(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=il(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function il(t){return t.replace(/\/+$/,"")}function De(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 dl=8e3;async function pl(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 f=String(t.headers["content-type"]||"");if(!wr(f))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let _=yr(t.headers["x-audio-duration-ms"]);if(_)return t.resume(),Q(e,_.status,{error:_.error});let b=await Ce(t,vr.bytes);if(!b)return Q(e,413,{error:kr()});if(!b.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":f,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return cl(e,o.daemon,"/voice/transcribe",b,S,18e4)}let s,i=await Ce(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 d=typeof s?.text=="string"?s.text.slice(0,dl):"";if(!d.trim())return Q(e,400,{error:"text is required"});if(!Tf(c.messages,d))return Q(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:p,...c.node!=="local"?{peer:c.node}:{}};return cl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function cl(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(Ef(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 Ef(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Tf(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===dl&&a.content.startsWith(e)))}var Af=new Set(["ring","offer","answer","ice","hangup"]),Ye=/^[A-Za-z0-9_-]{4,64}$/,Cf=128*1024,If=24,Mf=2*1024*1024,He=new Map;async function ml(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 M(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return M(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return M(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),d=tt(r.nodeName),p=(Array.isArray(c.peers)?c.peers:[]).filter(f=>tt(String(f?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(f=>f&&typeof f.id=="string").map(f=>({id:f.id,name:typeof f.name=="string"&&f.name?f.name:f.id}));return M(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:p,agents:m,camera:c.camera??null})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,Cf);if(!l)return M(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let d=Rf(c,r.nodeName);if(typeof d=="string")return M(e,400,{error:d});let p=fl(d.to);if(p&&d.kind==="ring"){let m=await Be(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:p});return M(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(d),signal:AbortSignal.timeout(15e3)}),f=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:f?.error||`AgentX answered HTTP ${m.status}.`})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Ye.test(l)?Pf(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,4096);if(!l)return M(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Ye.test(d))return M(e,400,{error:"callId is required"});let p=typeof c?.note=="string"?c.note:"",m=await Be(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:p},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await ul(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ye.test(c))return M(e,400,{error:"callId is required"});let d=Number(l.seconds??0);if(!Number.isFinite(d)||d<0)return M(e,400,{error:"seconds must be 0 or more"});let p=typeof l.note=="string"?l.note:"",m=await Be(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/stream`,{seconds:d,note:p});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await ul(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ye.test(c))return M(e,400,{error:"callId is required"});let d=await Be(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(c)}`);if(d.status>=300)return M(e,d.status,{error:d.body.error});let p=(Array.isArray(d.body.watch?.replies)?d.body.watch.replies:[]).find(b=>b&&b.at===l.at);if(!p||typeof p.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(d.body.watch.agentId??""),f=JSON.stringify([c,p.at,m,p.text]),_=He.get(f);return _?(He.delete(f),He.set(f,_),hl(e,_.type,_.bytes)):Lf(e,o,s,{agent:m,text:p.text},(b,S)=>{if(!(S.length>Mf))for(He.set(f,{type:b,bytes:S});He.size>If;)He.delete(He.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await Be(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.createdAt}));return M(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 M(e,405,{error:"POST"});let l=await Be(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Ye.test(l))return M(e,400,{error:"callId is required"});let c=await Be(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return M(e,404,{error:"not found"})}function fl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Be(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."}}}}async function ul(t,e){let a=await Ce(t,e);if(!a)return null;try{let n=JSON.parse(a.toString("utf8")||"{}");return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}async function Lf(t,e,a,n,r){try{let o=await fetch(`${e}/voice/speak`,{method:"POST",headers:{"Content-Type":"application/json",...a},body:JSON.stringify(n),signal:AbortSignal.timeout(9e4)}),s=o.headers.get("content-type")||"";if(o.ok&&s.startsWith("audio/")){let l=Buffer.from(await o.arrayBuffer());return r(s,l),hl(t,s,l)}let i=await o.json().catch(()=>({}));return o.ok||typeof i?.text=="string"?M(t,200,{text:typeof i?.text=="string"?i.text:n.text}):M(t,200,{text:n.text,error:i?.error||`AgentX answered HTTP ${o.status}.`})}catch{return M(t,200,{text:n.text,error:"Could not reach AgentX on this computer."})}}function hl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function Rf(t,e){let a=String(t?.kind??"");if(!Af.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Ye.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:")&&!fl(r))return"to must be bot:<agent id> for an agent";if(tt(r)===tt(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 Pf(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 M(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?M(e,503,{error:"Calls are off on this computer."}):M(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 M(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{mkdirSync as $f,readFileSync as jf,renameSync as Of,writeFileSync as Nf}from"fs";import{dirname as Df,isAbsolute as Hf,resolve as Bf}from"path";import{randomBytes as zf}from"crypto";var gl=60,xl=500,qf=200,yl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Ff=/^[A-Za-z0-9_-]{8,64}$/,Uf=/^[A-Za-z0-9._-]{1,64}$/;function wl(t,e){return Hf(e)?e:Bf(t,e)}function bl(t){return`${t}_${zf(6).toString("hex")}`}function vl(){return{places:[],rules:[],seen:[]}}function kl(t,e){let a=typeof t.name=="string"?t.name.trim():"";if(!a)return{ok:!1,error:"Give the place a name."};if([...a].length>gl)return{ok:!1,error:`Keep the name under ${gl} characters.`};let n=Number(t.lat),r=Number(t.lng);if(t.lat===void 0||t.lat===""||!Number.isFinite(n)||n<-90||n>90)return{ok:!1,error:"Latitude must be a number from -90 to 90."};if(t.lng===void 0||t.lng===""||!Number.isFinite(r)||r<-180||r>180)return{ok:!1,error:"Longitude must be a number from -180 to 180."};let o=t.radius===void 0||t.radius===""?e.defaultRadiusMeters:Math.round(Number(t.radius));if(!Number.isFinite(o)||o<e.minRadiusMeters||o>e.maxRadiusMeters)return{ok:!1,error:`The radius must be from ${e.minRadiusMeters} to ${e.maxRadiusMeters} metres.`};let s=i=>Math.round(i*1e6)/1e6;return{ok:!0,value:{name:a,lat:s(n),lng:s(r),radius:o}}}function _l(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!yl.test(a))return{ok:!1,error:"Pick a place."};let n=t.on===void 0?"enter":t.on;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"on must be enter or exit."};let r=typeof t.text=="string"?t.text.trim():"";if(!r)return{ok:!1,error:"Write what to remind you of."};if([...r].length>xl)return{ok:!1,error:`Keep it under ${xl} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Uf.test(o)||!e(o))?{ok:!1,error:`There is no agent called ${o.slice(0,64)} on this computer.`}:t.repeat!==void 0&&typeof t.repeat!="boolean"?{ok:!1,error:"repeat must be true or false."}:{ok:!0,value:{placeId:a,on:n,text:r,...o?{agent:o}:{},repeat:t.repeat===!0}}}function Sl(t){let e=typeof t.id=="string"?t.id:"";if(!Ff.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!yl.test(a))return{ok:!1,error:"place must be a place id"};let n=t.transition;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"transition must be enter or exit"};let r=typeof t.time=="number"?t.time:typeof t.time=="string"?Date.parse(t.time):NaN;return Number.isFinite(r)?{ok:!0,value:{id:e,place:a,transition:n,time:r}}:{ok:!1,error:"time must be a timestamp"}}var sa=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(jf(this.path,"utf-8"));return!e||typeof e!="object"?vl():{places:Array.isArray(e.places)?e.places:[],rules:Array.isArray(e.rules)?e.rules:[],seen:Array.isArray(e.seen)?e.seen.filter(a=>typeof a=="string"):[]}}catch{return vl()}}write(e){$f(Df(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Nf(a,JSON.stringify(e,null,2)+`
|
|
16331
|
+
`,{mode:384}),Of(a,this.path)}addPlace(e,a){let n=this.read();if(n.places.length>=a.maxPlaces)return{ok:!1,error:`You already have ${a.maxPlaces} places, the most allowed (app.places.maxPlaces). Remove one first.`};if(n.places.some(o=>o.name.toLowerCase()===e.name.toLowerCase()))return{ok:!1,error:`You already have a place called ${e.name}.`};let r={id:bl("pl"),...e,createdAt:new Date(this.now()).toISOString()};return n.places.push(r),this.write(n),{ok:!0,place:r}}removePlace(e){let a=this.read(),n=a.places.length;return a.places=a.places.filter(r=>r.id!==e),a.places.length===n?!1:(a.rules=a.rules.filter(r=>r.placeId!==e),this.write(a),!0)}addRule(e,a){let n=this.read();if(!n.places.some(o=>o.id===e.placeId))return{ok:!1,error:"That place doesn't exist any more."};if(n.rules.filter(o=>o.placeId===e.placeId).length>=a.maxRulesPerPlace)return{ok:!1,error:`That place already has ${a.maxRulesPerPlace} reminders, the most allowed (app.places.maxRulesPerPlace).`};let r={id:bl("pr"),...e,enabled:!0,createdAt:new Date(this.now()).toISOString()};return n.rules.push(r),this.write(n),{ok:!0,rule:r}}setRuleEnabled(e,a){let n=this.read(),r=n.rules.find(o=>o.id===e);return r?(r.enabled=a,this.write(n),r):null}removeRule(e){let a=this.read(),n=a.rules.length;return a.rules=a.rules.filter(r=>r.id!==e),a.rules.length===n?!1:(this.write(a),!0)}accept(e,a){let n=this.read();if(n.seen.includes(e.id))return{status:"duplicate"};n.seen=[...n.seen,e.id].slice(-qf);let r=this.now(),o=n.places.find(i=>i.id===e.place),s;if(!o)s={status:"unknown-place"};else if(e.time<r-a.maxEventAgeMinutes*6e4)s={status:"too-old"};else{let i=a.cooldownMinutes*6e4,l=n.rules.filter(c=>c.placeId===o.id&&c.on===e.transition&&c.enabled&&!(c.lastFiredAt&&Date.parse(c.lastFiredAt)>r-i));for(let c of l)c.lastFiredAt=new Date(r).toISOString(),c.repeat||(c.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(c=>({...c}))}:{status:"no-rules"}}return this.write(n),s}};Nn();function Wf(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function Gf(t,e,a){let n=new Date(a).toISOString().slice(0,16).replace("T"," ")+" UTC";return[`[Place reminder \xB7 ${e.on==="enter"?"the owner arrived at":"the owner left"} ${t.name} \xB7 ${n}]`,e.text,"","Your answer is sent to the owner's phone as a notification. Keep it short."].join(`
|
|
16332
|
+
`)}async function El(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=Wf(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,Gf(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
|
|
16333
16333
|
|
|
16334
|
-
(${o.agent} couldn't run this: ${String(l?.message||l).slice(0,160)})`}try{await r.push(t,s,i),r.log(`[places] ${o.id} on ${e.id}: pushed to ${t}`)}catch(l){r.log(`[places] ${o.id} on ${e.id}: push failed: ${String(l?.message||l).slice(0,200)}`)}}))}function
|
|
16335
|
-
${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15e3)});if(!i.ok)throw new Error(`HTTP ${i.status} ${(await i.text().catch(()=>"")).slice(0,160)}`)},async task(r,o,s){let i=await fetch(a+"/task",{method:"POST",headers:{...n,...t.operatorKey?{[
|
|
16334
|
+
(${o.agent} couldn't run this: ${String(l?.message||l).slice(0,160)})`}try{await r.push(t,s,i),r.log(`[places] ${o.id} on ${e.id}: pushed to ${t}`)}catch(l){r.log(`[places] ${o.id} on ${e.id}: push failed: ${String(l?.message||l).slice(0,200)}`)}}))}function Tl(t,e=console.error){let a=t.url.replace(/\/+$/,""),n={"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`}:{}};return{async push(r,o,s){let i=await fetch(a+"/channel/send",{method:"POST",headers:n,body:JSON.stringify({channel:"push",chatId:r,text:`${o}
|
|
16335
|
+
${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15e3)});if(!i.ok)throw new Error(`HTTP ${i.status} ${(await i.text().catch(()=>"")).slice(0,160)}`)},async task(r,o,s){let i=await fetch(a+"/task",{method:"POST",headers:{...n,...t.operatorKey?{[On]:t.operatorKey}:{}},body:JSON.stringify({agent:r,message:o,context:{channel:"app",chatId:`place:${s}`,sender:"places"}}),signal:AbortSignal.timeout(6e5)}),l=await i.json().catch(()=>({}));if(!i.ok||l.error)throw new Error(String(l.error||`HTTP ${i.status}`));return String(l.content??"")},log:e}}async function Al(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Il(t,e,a.slice(15),n,o,r)}async function Cl(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Il(t,e,a.slice(11),n,r,null)}async function Il(t,e,a,n,r,o){if(n==="GET"&&a===""){let i=r.enabled?r.store.read():{places:[],rules:[]};return z(e,200,{enabled:r.enabled,reason:r.enabled?null:"Place reminders are off on this computer (app.places.enabled).",pushAvailable:!!r.fire,pushReason:r.fire?null:r.pushReason??null,limits:{defaultRadiusMeters:r.limits.defaultRadiusMeters,minRadiusMeters:r.limits.minRadiusMeters,maxRadiusMeters:r.limits.maxRadiusMeters,maxPlaces:r.limits.maxPlaces},syncMinutes:r.syncMinutes,android:{packageName:r.androidPackage},places:i.places,rules:i.rules,agents:r.agents()})}if(n!=="POST")return z(e,404,{error:"not found"});if(!r.enabled)return z(e,403,{error:"Place reminders are off on this computer (app.places.enabled)."});let s;try{s=await qe(t,4096)}catch(i){return z(e,400,{error:i.message})}if(a==="/event"){if(!o)return z(e,404,{error:"not found"});let i=Sl(s);if(!i.ok)return z(e,400,{error:i.error});let l=r.store.accept(i.value,r.limits);return r.log(`[places] ${o.id} ${i.value.transition} ${i.value.place}: ${l.status}${l.status==="fired"?` (${l.rules.length})`:""}`),l.status==="fired"&&(r.fire?El(o.id,l.place,l.rules,i.value.time,r.fire).catch(c=>r.log(`[places] delivery failed: ${c?.message||c}`)):r.log(`[places] ${l.rules.length} reminder(s) not sent: ${r.pushReason??"this computer doesn't send pushes"}`)),z(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=kl(s,r.limits);if(!i.ok)return z(e,400,{error:i.error});let l=r.store.addPlace(i.value,r.limits);return l.ok?z(e,200,{ok:!0,place:l.place}):z(e,409,{error:l.error})}if(a==="/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removePlace(i)?z(e,200,{ok:!0}):z(e,404,{error:"No such place."})}if(a==="/rules/add"){let i=new Set(r.agents()),l=_l(s,d=>i.has(d));if(!l.ok)return z(e,400,{error:l.error});let c=r.store.addRule(l.value,r.limits);return c.ok?z(e,200,{ok:!0,rule:c.rule}):z(e,409,{error:c.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return z(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?z(e,200,{ok:!0,rule:i}):z(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?z(e,200,{ok:!0}):z(e,404,{error:"No such reminder."})}return z(e,404,{error:"not found"})}function Ml(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new sa(wl(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function Ll(t){let e=t.app.android;return e.certFingerprints.length?[{relation:["delegate_permission/common.handle_all_urls"],target:{namespace:"android_app",package_name:e.packageName,sha256_cert_fingerprints:e.certFingerprints.map(a=>a.toUpperCase())}}]:null}function z(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Rl=`
|
|
16336
16336
|
:root {
|
|
16337
16337
|
--ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
|
|
16338
16338
|
--ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
|
|
@@ -16346,7 +16346,7 @@ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15
|
|
|
16346
16346
|
--ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
|
|
16347
16347
|
--phone-bubble: #1d2f52; --phone-green: #3dbe74;
|
|
16348
16348
|
}
|
|
16349
|
-
`,
|
|
16349
|
+
`,Pl=`
|
|
16350
16350
|
[hidden] { display: none !important; }
|
|
16351
16351
|
main > .sw-peek[hidden] { display: block !important; }
|
|
16352
16352
|
main > #panel-chat.sw-peek[hidden] { display: flex !important; }
|
|
@@ -16452,7 +16452,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
|
|
|
16452
16452
|
@media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
|
|
16453
16453
|
@media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
|
|
16454
16454
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
|
|
16455
|
-
`;var
|
|
16455
|
+
`;var $l=`
|
|
16456
16456
|
window.AXSheet = function (sheet, onClose) {
|
|
16457
16457
|
var handle = document.createElement('button');
|
|
16458
16458
|
handle.type = 'button'; handle.className = 'sheet-handle';
|
|
@@ -16481,7 +16481,7 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
16481
16481
|
handle.addEventListener('pointercancel', reset);
|
|
16482
16482
|
sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
|
|
16483
16483
|
};
|
|
16484
|
-
`;var
|
|
16484
|
+
`;var jl=`
|
|
16485
16485
|
(function () {
|
|
16486
16486
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
16487
16487
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -16730,7 +16730,7 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
16730
16730
|
setInterval(refresh, 15000);
|
|
16731
16731
|
refresh();
|
|
16732
16732
|
})();
|
|
16733
|
-
`;var
|
|
16733
|
+
`;var Ol=`
|
|
16734
16734
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
16735
16735
|
.fx-head h2 { margin: 4px 0 0; }
|
|
16736
16736
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -16787,7 +16787,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16787
16787
|
}
|
|
16788
16788
|
.fx-error:empty { display: none; }
|
|
16789
16789
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
16790
|
-
`;var
|
|
16790
|
+
`;var Nl=`
|
|
16791
16791
|
(function () {
|
|
16792
16792
|
var panel = document.getElementById('panel-alerts');
|
|
16793
16793
|
if (!panel) return;
|
|
@@ -16998,7 +16998,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16998
16998
|
refresh();
|
|
16999
16999
|
loadRecent();
|
|
17000
17000
|
})();
|
|
17001
|
-
`;var
|
|
17001
|
+
`;var Dl=`
|
|
17002
17002
|
(function () {
|
|
17003
17003
|
var panel = document.getElementById('panel-alerts');
|
|
17004
17004
|
if (!panel) return;
|
|
@@ -17145,7 +17145,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17145
17145
|
document.addEventListener('visibilitychange', function () { if (!document.hidden && state) load(); });
|
|
17146
17146
|
load();
|
|
17147
17147
|
})();
|
|
17148
|
-
`,
|
|
17148
|
+
`,Hl=`
|
|
17149
17149
|
.pl-card { margin-top: 12px; }
|
|
17150
17150
|
.pl-list { margin-top: 8px; }
|
|
17151
17151
|
.pl-rules { list-style: none; margin: 6px 0 0; padding: 0; }
|
|
@@ -17164,7 +17164,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17164
17164
|
.pl-check { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); }
|
|
17165
17165
|
.pl-check input { width: 20px; height: 20px; }
|
|
17166
17166
|
#pl-here { justify-self: start; }
|
|
17167
|
-
`;var
|
|
17167
|
+
`;var Bl=`
|
|
17168
17168
|
(function () {
|
|
17169
17169
|
var panel = document.getElementById('panel-alerts');
|
|
17170
17170
|
if (!panel) return;
|
|
@@ -17277,7 +17277,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17277
17277
|
}
|
|
17278
17278
|
load();
|
|
17279
17279
|
})();
|
|
17280
|
-
`;var
|
|
17280
|
+
`;var zl=`
|
|
17281
17281
|
(function () {
|
|
17282
17282
|
var panel = document.getElementById('panel-chat');
|
|
17283
17283
|
var V = window.AXChatView;
|
|
@@ -17560,7 +17560,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17560
17560
|
var last = recall('ax-chat-conv');
|
|
17561
17561
|
if (!fromHash() && last) openConversation(last);
|
|
17562
17562
|
})();
|
|
17563
|
-
`;var
|
|
17563
|
+
`;var ql=`
|
|
17564
17564
|
window.AXChatView = (function () {
|
|
17565
17565
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
17566
17566
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -17841,7 +17841,7 @@ window.AXChatView = (function () {
|
|
|
17841
17841
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
17842
17842
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
17843
17843
|
})();
|
|
17844
|
-
`;var
|
|
17844
|
+
`;var Fl=`
|
|
17845
17845
|
window.AXChatSheets = function (o) {
|
|
17846
17846
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
17847
17847
|
function loadPicker() {
|
|
@@ -17887,7 +17887,7 @@ window.AXChatSheets = function (o) {
|
|
|
17887
17887
|
});
|
|
17888
17888
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
17889
17889
|
};
|
|
17890
|
-
`;var
|
|
17890
|
+
`;var Ul=`
|
|
17891
17891
|
window.AXChatLog = function (o) {
|
|
17892
17892
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
17893
17893
|
function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
|
|
@@ -17950,7 +17950,7 @@ window.AXChatLog = function (o) {
|
|
|
17950
17950
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
17951
17951
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
17952
17952
|
};
|
|
17953
|
-
`;var
|
|
17953
|
+
`;var Wl=`
|
|
17954
17954
|
(function () {
|
|
17955
17955
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
17956
17956
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -18100,7 +18100,7 @@ window.AXChatLog = function (o) {
|
|
|
18100
18100
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
18101
18101
|
poll();
|
|
18102
18102
|
})();
|
|
18103
|
-
`;var
|
|
18103
|
+
`;var Gl=`
|
|
18104
18104
|
.cs { margin: 0 -2px; }
|
|
18105
18105
|
.cs[hidden] { display: none; }
|
|
18106
18106
|
.cs-list {
|
|
@@ -18156,7 +18156,7 @@ window.AXChatLog = function (o) {
|
|
|
18156
18156
|
@media (prefers-reduced-motion: reduce) {
|
|
18157
18157
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
18158
18158
|
}
|
|
18159
|
-
`;function
|
|
18159
|
+
`;function Xl(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 Kl(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Jl=`
|
|
18160
18160
|
body { height: 100dvh; }
|
|
18161
18161
|
main { min-height: 0; }
|
|
18162
18162
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -18266,7 +18266,7 @@ main { min-height: 0; }
|
|
|
18266
18266
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
18267
18267
|
}
|
|
18268
18268
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
18269
|
-
`;var
|
|
18269
|
+
`;var Vl=`
|
|
18270
18270
|
window.AXOrb = (function () {
|
|
18271
18271
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
18272
18272
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -18383,7 +18383,7 @@ window.AXOrb = (function () {
|
|
|
18383
18383
|
}
|
|
18384
18384
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
18385
18385
|
})();
|
|
18386
|
-
`;var
|
|
18386
|
+
`;var Yl=`
|
|
18387
18387
|
window.AXVoiceIO = (function () {
|
|
18388
18388
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
18389
18389
|
var ac = null, playing = null;
|
|
@@ -18501,7 +18501,7 @@ window.AXVoiceIO = (function () {
|
|
|
18501
18501
|
|
|
18502
18502
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
18503
18503
|
})();
|
|
18504
|
-
`;var
|
|
18504
|
+
`;var Ql=`
|
|
18505
18505
|
(function () {
|
|
18506
18506
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
18507
18507
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -18714,7 +18714,7 @@ window.AXVoiceIO = (function () {
|
|
|
18714
18714
|
idle();
|
|
18715
18715
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
18716
18716
|
})();
|
|
18717
|
-
`;var
|
|
18717
|
+
`;var Zl=`
|
|
18718
18718
|
.vx {
|
|
18719
18719
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
18720
18720
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -18750,7 +18750,7 @@ window.AXVoiceIO = (function () {
|
|
|
18750
18750
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
18751
18751
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
18752
18752
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
18753
|
-
`;var
|
|
18753
|
+
`;var ec=`
|
|
18754
18754
|
<main class="card">
|
|
18755
18755
|
<h1>This phone isn't paired</h1>
|
|
18756
18756
|
<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>
|
|
@@ -18764,7 +18764,7 @@ window.AXVoiceIO = (function () {
|
|
|
18764
18764
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
18765
18765
|
</form>
|
|
18766
18766
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
18767
|
-
</main>`,
|
|
18767
|
+
</main>`,tc=`
|
|
18768
18768
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
18769
18769
|
.pair-form label { font-weight: 600; }
|
|
18770
18770
|
.pair-form input {
|
|
@@ -18786,7 +18786,7 @@ window.AXVoiceIO = (function () {
|
|
|
18786
18786
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
18787
18787
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
18788
18788
|
}
|
|
18789
|
-
`,
|
|
18789
|
+
`,ac=`
|
|
18790
18790
|
(function () {
|
|
18791
18791
|
var form = document.getElementById('pair-form');
|
|
18792
18792
|
var input = document.getElementById('pair-code');
|
|
@@ -18878,7 +18878,7 @@ window.AXVoiceIO = (function () {
|
|
|
18878
18878
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
18879
18879
|
}
|
|
18880
18880
|
})();
|
|
18881
|
-
`;var
|
|
18881
|
+
`;var nc=`
|
|
18882
18882
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
18883
18883
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
18884
18884
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -18887,7 +18887,7 @@ window.AXVoiceIO = (function () {
|
|
|
18887
18887
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
18888
18888
|
</div>
|
|
18889
18889
|
<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>
|
|
18890
|
-
</div>`,
|
|
18890
|
+
</div>`,rc=`
|
|
18891
18891
|
.pair-form .scan-btn {
|
|
18892
18892
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
18893
18893
|
}
|
|
@@ -18916,7 +18916,7 @@ window.AXVoiceIO = (function () {
|
|
|
18916
18916
|
}
|
|
18917
18917
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
18918
18918
|
body.scanning { overflow: hidden; }
|
|
18919
|
-
`,
|
|
18919
|
+
`,oc=`
|
|
18920
18920
|
(function () {
|
|
18921
18921
|
var openBtn = document.getElementById('scan-btn');
|
|
18922
18922
|
var box = document.getElementById('scan');
|
|
@@ -19082,7 +19082,7 @@ body.scanning { overflow: hidden; }
|
|
|
19082
19082
|
document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
|
|
19083
19083
|
window.addEventListener('pagehide', close);
|
|
19084
19084
|
})();
|
|
19085
|
-
`;var
|
|
19085
|
+
`;var mn=`
|
|
19086
19086
|
.cam { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; background: var(--ax-bg); }
|
|
19087
19087
|
.cam[hidden] { display: none; }
|
|
19088
19088
|
.cam-live {
|
|
@@ -19141,7 +19141,7 @@ body.scanning { overflow: hidden; }
|
|
|
19141
19141
|
@keyframes cam-pulse { 50% { opacity: .3; } }
|
|
19142
19142
|
@media (prefers-reduced-motion: reduce) { .cam-live.is-stream .cam-dot { animation: none; } }
|
|
19143
19143
|
#cam-stream[aria-pressed="true"] { border-color: var(--ax-red); color: var(--ax-red-ink); }
|
|
19144
|
-
`;var
|
|
19144
|
+
`;var sc='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h12v12H3zM15 10l6-3v10l-6-3"/></svg><span>Share camera</span></button>',ic=`
|
|
19145
19145
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
19146
19146
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
19147
19147
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -19170,7 +19170,7 @@ body.scanning { overflow: hidden; }
|
|
|
19170
19170
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
19171
19171
|
</div>
|
|
19172
19172
|
</div>
|
|
19173
|
-
</div>`,
|
|
19173
|
+
</div>`,lc=`
|
|
19174
19174
|
(function () {
|
|
19175
19175
|
var btn = document.getElementById('cam-btn');
|
|
19176
19176
|
var sheet = document.getElementById('cam');
|
|
@@ -19644,7 +19644,7 @@ body.scanning { overflow: hidden; }
|
|
|
19644
19644
|
});
|
|
19645
19645
|
window.addEventListener('pagehide', function () { stop(); });
|
|
19646
19646
|
})();
|
|
19647
|
-
`;var
|
|
19647
|
+
`;var cc=`
|
|
19648
19648
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
19649
19649
|
<div class="cam-askbar-text">
|
|
19650
19650
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -19654,7 +19654,7 @@ body.scanning { overflow: hidden; }
|
|
|
19654
19654
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
19655
19655
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
19656
19656
|
</div>
|
|
19657
|
-
</div>`,
|
|
19657
|
+
</div>`,dc=`
|
|
19658
19658
|
.cam-askbar[hidden] { display: none; }
|
|
19659
19659
|
.cam-askbar {
|
|
19660
19660
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -19669,7 +19669,7 @@ body.scanning { overflow: hidden; }
|
|
|
19669
19669
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
19670
19670
|
}
|
|
19671
19671
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
19672
|
-
`,
|
|
19672
|
+
`,pc=`
|
|
19673
19673
|
(function () {
|
|
19674
19674
|
var bar = document.getElementById('cam-ask-bar');
|
|
19675
19675
|
if (!bar) return;
|
|
@@ -19739,7 +19739,7 @@ body.scanning { overflow: hidden; }
|
|
|
19739
19739
|
setInterval(poll, 5000);
|
|
19740
19740
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
19741
19741
|
})();
|
|
19742
|
-
`;function
|
|
19742
|
+
`;function uc(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 mc(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}function fc(t){return t>=400?"send":"listen"}function hc(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var gc=`
|
|
19743
19743
|
(function () {
|
|
19744
19744
|
var main = document.querySelector('main');
|
|
19745
19745
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
@@ -19858,7 +19858,7 @@ body.scanning { overflow: hidden; }
|
|
|
19858
19858
|
main.addEventListener('touchend', function () { end(false); });
|
|
19859
19859
|
main.addEventListener('touchcancel', function () { end(true); });
|
|
19860
19860
|
})();
|
|
19861
|
-
`,
|
|
19861
|
+
`,xc=`
|
|
19862
19862
|
main { position: relative; }
|
|
19863
19863
|
main.sw-on { overflow: hidden; }
|
|
19864
19864
|
.sw-on > [role=tabpanel] { will-change: transform; }
|
|
@@ -19869,8 +19869,8 @@ main > .sw-peek {
|
|
|
19869
19869
|
}
|
|
19870
19870
|
main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
|
|
19871
19871
|
@media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
|
|
19872
|
-
`;function
|
|
19873
|
-
${q({afterUnauthorized:
|
|
19872
|
+
`;function bc(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 vc(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function yc(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function wc(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 fn=`
|
|
19873
|
+
${q({afterUnauthorized:So})}
|
|
19874
19874
|
var CACHE = 'agentx-app-v3';
|
|
19875
19875
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
19876
19876
|
self.addEventListener('install', function (e) {
|
|
@@ -19961,7 +19961,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19961
19961
|
return self.clients.openWindow(target);
|
|
19962
19962
|
}));
|
|
19963
19963
|
});
|
|
19964
|
-
`;var
|
|
19964
|
+
`;var Xf="<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 hn(t){return`<meta charset="utf-8">
|
|
19965
19965
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
19966
19966
|
<meta name="theme-color" content="#2979FF">
|
|
19967
19967
|
<meta name="referrer" content="no-referrer">
|
|
@@ -19972,58 +19972,58 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19972
19972
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
19973
19973
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
19974
19974
|
<title>${t}</title>
|
|
19975
|
-
${
|
|
19976
|
-
<style>${
|
|
19975
|
+
${Xf}
|
|
19976
|
+
<style>${Ue}${Rl}${Yf}</style>`}var Kf={chat:"M21 11.5a8.5 8.5 0 0 1-8.5 8.5H4l-2 2V11.5a9.5 9.5 0 0 1 19 0Z",fleet:"M3 3h18v13H3zM8 21h8M12 16v5",activity:"M3 12h4l3-8 4 16 3-8h4",alerts:"M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4"},kc=[{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 _c(){let t=kc.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}"><span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="${Kf[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=kc.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
19977
19977
|
<h2>${a.label}</h2>
|
|
19978
19978
|
<p class="soon">${a.soon}</p>
|
|
19979
19979
|
</section>`).join("");return`<!doctype html>
|
|
19980
19980
|
<html lang="en">
|
|
19981
|
-
<head>${
|
|
19981
|
+
<head>${hn("AgentX")}<style>${Qf}${Ol}${Jl}${Gl}${Zl}${mn}${dc}${xc}${Hl}${Pl}</style></head>
|
|
19982
19982
|
<body>
|
|
19983
19983
|
<header class="bar">
|
|
19984
19984
|
<div>
|
|
19985
19985
|
<h1>AgentX</h1>
|
|
19986
19986
|
<p id="who" class="who">Connecting\u2026</p>
|
|
19987
19987
|
</div>
|
|
19988
|
-
<div class="bar-btns">${
|
|
19988
|
+
<div class="bar-btns">${sc}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 15.5A9 9 0 0 1 8.5 4 9 9 0 1 0 20 15.5Z"/></svg></button></div>
|
|
19989
19989
|
</header>
|
|
19990
19990
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
19991
|
-
${
|
|
19991
|
+
${cc}
|
|
19992
19992
|
<main>${e}</main>
|
|
19993
19993
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
19994
|
-
${
|
|
19995
|
-
<script>${
|
|
19996
|
-
<script>${q({swipeMayStart:
|
|
19997
|
-
<script>${
|
|
19998
|
-
<script>${Pl}</script>
|
|
19994
|
+
${ic}
|
|
19995
|
+
<script>${Jf}</script>
|
|
19996
|
+
<script>${q({swipeMayStart:bc,swipeAxis:vc,swipeOffset:yc,swipeLanding:wc})}${gc}</script>
|
|
19997
|
+
<script>${$l}</script>
|
|
19999
19998
|
<script>${jl}</script>
|
|
20000
|
-
<script>${
|
|
19999
|
+
<script>${Nl}</script>
|
|
20001
20000
|
<script>${Dl}</script>
|
|
20002
|
-
<script>${
|
|
20003
|
-
<script>${q({
|
|
20004
|
-
<script>${
|
|
20005
|
-
<script>${
|
|
20006
|
-
<script>${
|
|
20001
|
+
<script>${Bl}</script>
|
|
20002
|
+
<script>${q({markdownToHtml:lr})}${ql}${Ul}${Fl}${zl}</script>
|
|
20003
|
+
<script>${q({queueSpeech:Xl,nextSpeech:Kl})}${Vl}${Yl}${Ql}</script>
|
|
20004
|
+
<script>${Wl}</script>
|
|
20005
|
+
<script>${q({cameraConstraints:uc,shareClock:mc,streamLabel:hc,talkRelease:fc})}${lc}</script>
|
|
20006
|
+
<script>${pc}</script>
|
|
20007
20007
|
</body>
|
|
20008
|
-
</html>`}function
|
|
20008
|
+
</html>`}function Sc(){return`<!doctype html>
|
|
20009
20009
|
<html lang="en">
|
|
20010
|
-
<head>${
|
|
20010
|
+
<head>${hn("Pair \xB7 AgentX")}</head>
|
|
20011
20011
|
<body>
|
|
20012
20012
|
<main class="card">
|
|
20013
20013
|
<h1>Pairing this phone\u2026</h1>
|
|
20014
20014
|
<p id="msg" role="status">One moment.</p>
|
|
20015
20015
|
</main>
|
|
20016
|
-
<script>${
|
|
20016
|
+
<script>${Vf}</script>
|
|
20017
20017
|
</body>
|
|
20018
|
-
</html>`}function
|
|
20018
|
+
</html>`}function Ec(){return`<!doctype html>
|
|
20019
20019
|
<html lang="en">
|
|
20020
|
-
<head>${
|
|
20021
|
-
<body>${
|
|
20022
|
-
<script>${q({mayBounce:
|
|
20023
|
-
<script>${
|
|
20024
|
-
<script>${
|
|
20020
|
+
<head>${hn("Not paired \xB7 AgentX")}<style>${tc}${rc}</style></head>
|
|
20021
|
+
<body>${ec}${nc}
|
|
20022
|
+
<script>${q({mayBounce:Eo,formatPairInput:Ft,parsePairScan:To})}</script>
|
|
20023
|
+
<script>${ac}</script>
|
|
20024
|
+
<script>${oc}</script>
|
|
20025
20025
|
</body>
|
|
20026
|
-
</html>`}function
|
|
20026
|
+
</html>`}function Tc(){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:"#FFFFFF",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 Jf=`
|
|
20027
20027
|
(function () {
|
|
20028
20028
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
20029
20029
|
function select(tab, focus, keepHash) {
|
|
@@ -20095,7 +20095,7 @@ ${oc}
|
|
|
20095
20095
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
20096
20096
|
}
|
|
20097
20097
|
})();
|
|
20098
|
-
`,
|
|
20098
|
+
`,Vf=`
|
|
20099
20099
|
(function () {
|
|
20100
20100
|
var msg = document.getElementById('msg');
|
|
20101
20101
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -20112,7 +20112,7 @@ ${oc}
|
|
|
20112
20112
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
20113
20113
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
20114
20114
|
})();
|
|
20115
|
-
`,
|
|
20115
|
+
`,Yf=`
|
|
20116
20116
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
20117
20117
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
20118
20118
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -20124,7 +20124,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
20124
20124
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
20125
20125
|
.muted { color: var(--ax-text-2); }
|
|
20126
20126
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
20127
|
-
`,
|
|
20127
|
+
`,Qf=`
|
|
20128
20128
|
body { display: flex; flex-direction: column; }
|
|
20129
20129
|
.bar {
|
|
20130
20130
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -20162,8 +20162,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20162
20162
|
}
|
|
20163
20163
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
20164
20164
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
20165
|
-
`;var
|
|
20166
|
-
`;
|
|
20165
|
+
`;var ia="agentx_app",th=400*86400,ah=new Ct,nh=new Le;async function Ac(t,e,a,n,r={}){if(a==="/.well-known/assetlinks.json"&&n==="GET"){let i=r.assetLinks?.()??null;return i?fe(e,200,"application/json",JSON.stringify(i),"public, max-age=300"):Ee(e,404,{error:"not found"})}if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new G;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",Tc());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",fn);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Ge(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Ge(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",Sc());if(a==="/app/qr.js"){let i=rh();return i?fe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Ee(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=gn(lt(t),o);return i?(e.setHeader("Set-Cookie",xn(lt(t))),Ee(e,200,{device:i.name})):Ee(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await ir(t,{codes:r.pairCodes??new _t,limiter:r.pairLimiter??ah,verify:l=>gn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",xn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ee(e,i.status,i.body)}let s=gn(oh(t),o);if(!s){let i=lt(t);return(r.rejectLog??nh).record(a.slice(0,120),Bt(t,We(bn(t,ia),o),i?We(i,o):null)),a==="/app"?fe(e,401,"text/html; charset=utf-8",Ec()):Ee(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=bn(t,ia);return i&&!lt(t)&&e.setHeader("Set-Cookie",xn(i)),fe(e,200,"text/html; charset=utf-8",_c())}return n==="GET"&&a==="/api/app/me"?Ee(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await sr(t,e,a,n,s.name,r.fleet)||r.push&&await Ui(t,e,a,n,s,r.push)||r.announce&&await Xi(t,e,a,n,s,r.announce)||r.chat&&await rl(t,e,a,n,s,r.chat)||r.chat&&await ll(t,e,a,n,s,r.chat)||r.voice&&await pl(t,e,a,n,s,r.voice)||r.camera&&await ml(t,e,a,n,r.camera)||r.places&&await Al(t,e,a,n,s,r.places)?!0:Ee(e,404,{error:"not found"})}var it;function rh(){if(it!==void 0)return it;try{let t=eh(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
20166
|
+
`;it=Buffer.concat([Buffer.from(a),Zf(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),it=null}return it}function gn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ae(a,"app")?a:null}function xn(t){return`${ia}=${t}; Path=/; Max-Age=${th}; HttpOnly; Secure; SameSite=Lax`}function oh(t){return lt(t)??bn(t,ia)}function lt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function bn(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ee(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}function Cc(t){let e=ue({kicker:"Phone",title:"Places",lead:"Places your phone watches, and what to remind you of when you arrive or leave. The AgentX Android app on your phone notices the crossing and tells this computer only which place and which way: never where you are."})+`
|
|
20167
20167
|
<div class="pl-wrap">
|
|
20168
20168
|
<div id="pl-msg" class="pl-msg" role="status" aria-live="polite"></div>
|
|
20169
20169
|
<form id="pl-add" class="pl-form" autocomplete="off">
|
|
@@ -20175,7 +20175,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20175
20175
|
<button type="submit" class="ax-btn ax-btn--primary">Add place</button>
|
|
20176
20176
|
</form>
|
|
20177
20177
|
<ol id="pl-list" class="pl-list" aria-label="Places"><li class="pl-empty">Loading\u2026</li></ol>
|
|
20178
|
-
</div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:
|
|
20178
|
+
</div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:sh,scripts:`<script>${ih}</script>`})}var sh=`
|
|
20179
20179
|
.pl-wrap { max-width: 1040px; margin: 0 auto; padding: 0 24px 96px; box-sizing: border-box; }
|
|
20180
20180
|
.pl-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
20181
20181
|
.pl-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -20198,7 +20198,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20198
20198
|
.pl-rule-form { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
20199
20199
|
.pl-rule-form input[name=text] { flex: 1 1 240px; }
|
|
20200
20200
|
.pl-btns { margin-left: auto; display: flex; gap: 8px; }
|
|
20201
|
-
`,
|
|
20201
|
+
`,ih=`
|
|
20202
20202
|
(function () {
|
|
20203
20203
|
var list = document.getElementById('pl-list');
|
|
20204
20204
|
var msg = document.getElementById('pl-msg');
|
|
@@ -20277,7 +20277,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20277
20277
|
});
|
|
20278
20278
|
load();
|
|
20279
20279
|
})();
|
|
20280
|
-
`;import{randomBytes as
|
|
20280
|
+
`;import{randomBytes as Ic}from"crypto";var ze={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:de.perMessage},lh=/^[a-f0-9]{32}$/,ch=/^c[a-z0-9]{8,32}$/,dh=/^#[0-9a-fA-F]{6}$/;function vn(t){return ch.test(t)}var ct=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
20281
20281
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
20282
20282
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
20283
20283
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -20290,39 +20290,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20290
20290
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
20291
20291
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
20292
20292
|
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 (
|
|
20293
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return
|
|
20294
|
-
(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(!
|
|
20293
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return vn(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)}${Ic(4).toString("hex")}`,{color:s,...i}=a,l=s&&dh.test(s)?s:void 0,c={id:o,title:uh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
20294
|
+
(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(!vn(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(ph);return{...Mc(n),messages:r}}list(e,a=ze.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
20295
20295
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
20296
20296
|
(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
|
|
20297
|
-
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{...
|
|
20297
|
+
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{...Mc(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){vn(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,
|
|
20298
20298
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
20299
20299
|
FROM app_chat_conversations c
|
|
20300
20300
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
20301
20301
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
20302
|
-
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>
|
|
20302
|
+
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>ze.content?n.content.slice(0,ze.content)+`
|
|
20303
20303
|
|
|
20304
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,
|
|
20304
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,ze.toolsPerMessage),l=[];for(let m of r){if(l.length>=ze.filesPerMessage)break;let f=m.filename.trim(),_=Kn(f);if(!_||!f||f.length>de.pathChars||f.includes("\0"))continue;let b=(f.split(/[\\/]/).pop()||f).slice(0,120);l.push({id:Ic(16).toString("hex"),name:b,mime:_.mime,kind:_.kind,path:f})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),d=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
20305
20305
|
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),p=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
|
|
20306
20306
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)p.run(m.id,a,Number(d.lastInsertRowid),m.path,m.name,m.mime,m.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
20307
|
-
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,
|
|
20308
|
-
(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(!
|
|
20307
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,ze.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
|
|
20308
|
+
(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(!lh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
20309
20309
|
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 = ?
|
|
20310
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,
|
|
20310
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,ze.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 Mc(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 ph(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 uh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var mh=4e3,yn=100,fh=15,Lc=t=>t.replace(/\/+$/,""),la=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=mh){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,yn);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??fh)-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>=yn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${yn}); 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||Lc(l)!==Lc(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=hh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let p=c.row.status,m=!!this.deps.finishAlerts?.(s),f={status:p,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&ra(f)&&this.deps.notifyFinish(oa(s,i,p,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function hh(t,e){let a=t.plain?{text:yt(t.text,!1),artifacts:[]}:vt(t.text,de.perMessage,!1),{cleanText:n,ui:r}=kt(a.text),o=t.plain?void 0:on(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:gh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function gh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}jn();function Qe(){let t=ht();return t&&Se(t,"dashboard"),t}function I0(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let f of a)try{s.set(f.id,Ch(f,t))}catch(_){console.error(` Board "${f.id}" failed to initialize: ${_.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?dt(process.cwd(),t.workflows.dir):void 0,c=new Un(l?{baseDir:l}:void 0),d=new Wn(l?{baseDir:l,nodeId:i}:{nodeId:i}),p=new Gn(l?{baseDir:l}:void 0);ci(t),Qe(),hr({business:t.business?.enabled===!0});let m=xh(async(f,_)=>{try{await Sh(f,_,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:d,workflowLayouts:p})}catch(b){k(_,500,{error:b.message||"internal error"})}});Wh(t).start(),m.listen(n,r,()=>{let f=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
20311
20311
|
Live dashboard: http://${f}:${n}
|
|
20312
20312
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
20313
20313
|
Kanban dashboard: http://${f}:${n}
|
|
20314
|
-
`),console.log(` Boards: ${a.map(S=>S.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 vh=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/places","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function yh(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if((t.url||"/").split(/[?#]/)[0]!==r){k(e,404,{error:"not found"});return}if(ur(t.headers)==="foreign"&&mr(o)){k(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Jo(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>at(a.config.people),members:Lc(a.config.members.logRetentionDays),db:()=>Ye(),linkFor:(u,h)=>xo(u,h,{gitlab:a.config.channels.gitlab?.host})})||await Ec(t,e,r,o,{nodeName:a.config.node?.name,fleet:Oc(a.config),push:En(a.config),announce:Xi(a.config),chat:Nc(a.config),voice:qh(a.config),camera:Fh(a.config),places:Mc(a.config),assetLinks:()=>Il(a.config)}))return;let s=o==="GET"?fo(r):null;if(s){e.writeHead(200,{"Content-Type":s.type,"Cache-Control":"public, max-age=86400"}),e.end(s.body);return}if(o==="GET"&&vh.has(r)&&Kr("page",r),o==="GET"&&r==="/"){let u=$r();if(!u.configExists||u.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(an({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($i({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(an({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Te(a.config);if(!u){k(e,503,{error:"no node available"});return}let h=await new Promise(y=>{let T="";t.on("data",v=>T+=v),t.on("end",()=>y(T)),t.on("error",()=>y(""))}),w=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:h||"{}"});e.writeHead(w.status,{"Content-Type":"application/json"}),e.end(await w.text())}catch(u){k(e,502,{error:"could not reach the node",message:String(u?.message||u)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let u=await Te(a.config),h=o==="POST"?void 0:n.searchParams.get("node"),w=o==="POST"?await he(t):void 0,y=w?.node??h,T=y?u.find(R=>R.url===y):u[0];if(!T){k(e,400,{error:"unknown node"});return}let v=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(T.url+r+v,{method:o,headers:{"Content-Type":"application/json",...T.token?{Authorization:`Bearer ${T.token}`}:{}},...o==="POST"?{body:JSON.stringify({...w,node:void 0})}:{}});k(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){k(e,502,{error:"could not reach the node",message:u?.message||String(u)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let u=await he(t),h={"Content-Type":"application/json"};a.config.dashboard.token&&(h.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/api/workflows/editor/chat`,{method:"POST",headers:h,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Te(a.config);if(!u){k(e,200,{configured:!1,workflows:[]});return}let h=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});k(e,h.status,await h.json().catch(()=>({configured:!1,workflows:[]})))}catch{k(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ro({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(no({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(Zr({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,h=setTimeout(()=>u.abort(),8e3);try{let w=Jn(await Te(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(w.map(async _=>{try{let L=await fetch(_.url+"/monitor",{headers:_.token?{Authorization:`Bearer ${_.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:_.name,url:_.url,ok:!0,data:await L.json()}}catch(L){return{name:_.name,url:_.url,ok:!1,error:L.message}}}));k(e,200,{nodes:R});return}let y=w.find(R=>R.url===n.searchParams.get("node"));if(!y){k(e,400,{error:"Select a known node"});return}let T=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(T)||o==="POST"&&["register","ended","action","retry","clear"].includes(T))){k(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await Kn(t)):void 0,A=await fetch(y.url+"/monitor/"+T+(T==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):T==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:v,signal:u.signal,headers:{"Content-Type":"application/json",...y.token?{Authorization:`Bearer ${y.token}`}:{}}});k(e,A.status,await A.json())}catch(w){k(e,502,{error:w.message})}finally{clearTimeout(h)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ii({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Tc({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mi({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),w=o==="POST"?await he(t).catch(()=>({})):void 0,y=await fetch(`${h}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...w!==void 0?{body:JSON.stringify(w??{})}:{}});k(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ji({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ni({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pr({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",h=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!u){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(Di({taskId:decodeURIComponent(l[1]),agentId:u,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:h,peers:D(a.config)}));return}let c=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(c){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hi({agentId:decodeURIComponent(c[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"){jr(t,e);return}if(o==="POST"&&r==="/api/setup"){await Or(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Nr(t,e);return}if(o==="GET"&&r==="/admin"){ss(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){_s(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){ms(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}Ps(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let u=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(u==="fleet"){if(r==="/api/admin/activity-graph"){await Jh(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await en(t,e,r,w=>Hc(w,a.config));return}let h=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(h){let w=decodeURIComponent(h[1]),y=w.indexOf("::");if(y>0){let T=w.slice(0,y),v=w.slice(y+2),A=a.config.node?.id||a.config.node?.name||"local";if(T===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`;else{let R=(a.config.dashboard?.daemons||[]).find(_=>(_.name||_.url)===T);if(R){let _=dt(R.url.replace(/\/+$/,""),a.config);if(_){await Pc(t,e,_,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}k(e,404,{error:`unknown node "${T}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let h=dt(u,a.config);if(!h){k(e,404,{error:`unknown peer: ${u}`});return}let w=(n.search||"").replace(/[?&]peer=[^&]*/g,T=>T.startsWith("?")?"?":"");await Pc(t,e,h,r+(w==="?"?"":w));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await $s(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Vh(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-DO262COW.js"),w=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",y=await u({running:w});k(e,200,y)}catch(u){k(e,500,{error:u?.message||String(u)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ds({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Ns(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hs({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bs({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 Ah(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 ci(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await en(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await pi(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){fi(t,e,d[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",h=u.startsWith("Bearer ")?u.slice(7):"";if(h!==a.token){let w=new G,y=h?w.verify(h):null;if(!y||!Ae(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await is(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){k(e,200,xr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Ss(t,e,r,n);return}if(await Ts(t,e,r,{people:()=>at(a.config.people),members:Lc(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ye(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await fs(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await hi(t,e,r);return}if(r.startsWith("/api/admin/")){await ls(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(Vo);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){k(e,400,{error:"invalid asset name"});return}let h=Xh("web/"+u);try{let w=await Kh(h),y=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",T=n.searchParams.has("v");e.writeHead(200,{"Content-Type":y,"Cache-Control":T?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(w)}catch{k(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Qe(a.config);k(e,200,u)}catch(u){k(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let u=n.searchParams.get("date")||new Date().toISOString().slice(0,10),h=n.searchParams.get("timezone")||"UTC",w=await Qe(a.config,{date:u,timezone:h});k(e,200,w)}catch(u){k(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(h,w,y,T)=>{let v=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(v)?Math.max(y,Math.min(T,v)):w};try{let h=await Te(a.config);k(e,200,await Li(h,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(h){k(e,502,{error:h.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){k(e,400,{error:"day=YYYY-MM-DD query param required"});return}let h=(w,y,T,v)=>{let A=parseInt(n.searchParams.get(w)||"",10);return Number.isFinite(A)?Math.max(T,Math.min(v,A)):y};try{let w=await Te(a.config);k(e,200,await Pi(w,{day:u,tzOffsetMinutes:h("tzOffset",0,-840,840),limit:h("limit",40,1,200)}))}catch(w){k(e,502,{error:w.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let u=n.searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}let h=n.searchParams,w;if(r==="/api/mesh/thread"){let[y,T,v]=[h.get("agent"),h.get("channel"),h.get("chat")];if(!y||!T||!v){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/thread?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(v)}&limit=${encodeURIComponent(h.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[y,T]=[h.get("kind"),h.get("key")];if(!y||!T){k(e,400,{error:"kind and key required"});return}w=`/analytics/job?kind=${encodeURIComponent(y)}&key=${encodeURIComponent(T)}&limit=${encodeURIComponent(h.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[y,T,v]=[h.get("agent"),h.get("channel"),h.get("chat")];if(!y||!T||!v){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/conversation?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(v)}&tzOffset=${encodeURIComponent(h.get("tzOffset")||"0")}`}else{let y=h.get("task");if(!y){k(e,400,{error:"task required"});return}w=`/analytics/run/${encodeURIComponent(y)}`}try{await Ri(e,await Te(a.config),u,w)}catch(y){k(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){$h(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task");if(!h||!w||!y){k(e,400,{error:"node, agent, task query params required"});return}await jh(t,e,a,h,w,y);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task"),T=u.searchParams.get("limit")||"50";if(!h||!w){k(e,400,{error:"node and agent query params required"});return}await Dh(e,a,h,w,y,T);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("task"),y=u.searchParams.get("kind");if(!h||!w||y!=="cancel"&&y!=="followup"){k(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Hh(t,e,a,h,w,y);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await Sn(t,e,a,u,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!h.ok)throw new Error(`HTTP ${h.status}`);let w=await h.json();k(e,200,w)}catch(u){k(e,502,{error:u.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!h.ok){k(e,h.status,{error:`HTTP ${h.status}`});return}k(e,200,await h.json())}catch(u){k(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await he(t);try{let h=await Wh(a.config,u);k(e,200,h)}catch(h){k(e,502,{error:h.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!Oh(t,e,[`agent:${u}`]))return;await Nh(t,e,a.config,u);return}if(o==="GET"&&r==="/api/node/build"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!h.ok)throw new Error(`HTTP ${h.status}`);k(e,200,gr(await h.json()))}catch(u){k(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",h=u.startsWith("Bearer ")?u.slice(7):"";if(h!==a.token){let w=new G,y=h?w.verify(h):null;if(!y||!Ae(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Ch(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"){k(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(await Tl(t,e,r,o,Mc(a.config)))return;if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await Sn(t,e,a,u,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let h=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let w=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(A=>({name:A.name,url:A.url,token:A.token}))],y={flag:!1},T=[];t.on("close",()=>{y.flag=!0;for(let A of T)try{A.abort()}catch{}});let v=setInterval(()=>{if(!y.flag)try{e.write(`: ping
|
|
20314
|
+
`),console.log(` Boards: ${a.map(_=>_.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 _h=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/places","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Sh(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if((t.url||"/").split(/[?#]/)[0]!==r){k(e,404,{error:"not found"});return}if(mr(t.headers)==="foreign"&&fr(o)){k(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Vo(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>nt(a.config.people),members:Pc(a.config.members.logRetentionDays),db:()=>Qe(),linkFor:(u,h)=>bo(u,h,{gitlab:a.config.channels.gitlab?.host})})||await Ac(t,e,r,o,{nodeName:a.config.node?.name,fleet:Dc(a.config),push:Tn(a.config),announce:Ki(a.config),chat:Hc(a.config),voice:Gh(a.config),camera:Xh(a.config),places:Rc(a.config),assetLinks:()=>Ll(a.config)}))return;let s=o==="GET"?ho(r):null;if(s){e.writeHead(200,{"Content-Type":s.type,"Cache-Control":"public, max-age=86400"}),e.end(s.body);return}if(o==="GET"&&_h.has(r)&&Jr("page",r),o==="GET"&&r==="/"){let u=jr();if(!u.configExists||u.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(nn({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ji({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(nn({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Te(a.config);if(!u){k(e,503,{error:"no node available"});return}let h=await new Promise(y=>{let T="";t.on("data",v=>T+=v),t.on("end",()=>y(T)),t.on("error",()=>y(""))}),w=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:h||"{}"});e.writeHead(w.status,{"Content-Type":"application/json"}),e.end(await w.text())}catch(u){k(e,502,{error:"could not reach the node",message:String(u?.message||u)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let u=await Te(a.config),h=o==="POST"?void 0:n.searchParams.get("node"),w=o==="POST"?await he(t):void 0,y=w?.node??h,T=y?u.find(R=>R.url===y):u[0];if(!T){k(e,400,{error:"unknown node"});return}let v=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(T.url+r+v,{method:o,headers:{"Content-Type":"application/json",...T.token?{Authorization:`Bearer ${T.token}`}:{}},...o==="POST"?{body:JSON.stringify({...w,node:void 0})}:{}});k(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){k(e,502,{error:"could not reach the node",message:u?.message||String(u)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let u=await he(t),h={"Content-Type":"application/json"};a.config.dashboard.token&&(h.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/api/workflows/editor/chat`,{method:"POST",headers:h,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Te(a.config);if(!u){k(e,200,{configured:!1,workflows:[]});return}let h=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});k(e,h.status,await h.json().catch(()=>({configured:!1,workflows:[]})))}catch{k(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oo({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ro({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(eo({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,h=setTimeout(()=>u.abort(),8e3);try{let w=Vn(await Te(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(w.map(async E=>{try{let L=await fetch(E.url+"/monitor",{headers:E.token?{Authorization:`Bearer ${E.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:E.name,url:E.url,ok:!0,data:await L.json()}}catch(L){return{name:E.name,url:E.url,ok:!1,error:L.message}}}));k(e,200,{nodes:R});return}let y=w.find(R=>R.url===n.searchParams.get("node"));if(!y){k(e,400,{error:"Select a known node"});return}let T=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(T)||o==="POST"&&["register","ended","action","retry","clear"].includes(T))){k(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await Jn(t)):void 0,A=await fetch(y.url+"/monitor/"+T+(T==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):T==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:v,signal:u.signal,headers:{"Content-Type":"application/json",...y.token?{Authorization:`Bearer ${y.token}`}:{}}});k(e,A.status,await A.json())}catch(w){k(e,502,{error:w.message})}finally{clearTimeout(h)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mi({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Cc({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Li({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),w=o==="POST"?await he(t).catch(()=>({})):void 0,y=await fetch(`${h}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...w!==void 0?{body:JSON.stringify(w??{})}:{}});k(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oi({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ni({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Di({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",h=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!u){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(Hi({taskId:decodeURIComponent(l[1]),agentId:u,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:h,peers:D(a.config)}));return}let c=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(c){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bi({agentId:decodeURIComponent(c[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"){Or(t,e);return}if(o==="POST"&&r==="/api/setup"){await Nr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Dr(t,e);return}if(o==="GET"&&r==="/admin"){is(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Ss(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){fs(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}$s(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let u=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(u==="fleet"){if(r==="/api/admin/activity-graph"){await Zh(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await tn(t,e,r,w=>zc(w,a.config));return}let h=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(h){let w=decodeURIComponent(h[1]),y=w.indexOf("::");if(y>0){let T=w.slice(0,y),v=w.slice(y+2),A=a.config.node?.id||a.config.node?.name||"local";if(T===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`;else{let R=(a.config.dashboard?.daemons||[]).find(E=>(E.name||E.url)===T);if(R){let E=pt(R.url.replace(/\/+$/,""),a.config);if(E){await jc(t,e,E,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}k(e,404,{error:`unknown node "${T}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let h=pt(u,a.config);if(!h){k(e,404,{error:`unknown peer: ${u}`});return}let w=(n.search||"").replace(/[?&]peer=[^&]*/g,T=>T.startsWith("?")?"?":"");await jc(t,e,h,r+(w==="?"?"":w));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await js(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await eg(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-DO262COW.js"),w=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",y=await u({running:w});k(e,200,y)}catch(u){k(e,500,{error:u?.message||String(u)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Ds(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bs({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zs({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 Lh(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 di(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await tn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ui(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){hi(t,e,d[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",h=u.startsWith("Bearer ")?u.slice(7):"";if(h!==a.token){let w=new G,y=h?w.verify(h):null;if(!y||!Ae(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ls(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){k(e,200,br()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Es(t,e,r,n);return}if(await As(t,e,r,{people:()=>nt(a.config.people),members:Pc(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Qe(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await hs(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await gi(t,e,r);return}if(r.startsWith("/api/admin/")){await cs(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(Yo);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){k(e,400,{error:"invalid asset name"});return}let h=Yh("web/"+u);try{let w=await Qh(h),y=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",T=n.searchParams.has("v");e.writeHead(200,{"Content-Type":y,"Cache-Control":T?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(w)}catch{k(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Ze(a.config);k(e,200,u)}catch(u){k(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let u=n.searchParams.get("date")||new Date().toISOString().slice(0,10),h=n.searchParams.get("timezone")||"UTC",w=await Ze(a.config,{date:u,timezone:h});k(e,200,w)}catch(u){k(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(h,w,y,T)=>{let v=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(v)?Math.max(y,Math.min(T,v)):w};try{let h=await Te(a.config);k(e,200,await Ri(h,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(h){k(e,502,{error:h.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){k(e,400,{error:"day=YYYY-MM-DD query param required"});return}let h=(w,y,T,v)=>{let A=parseInt(n.searchParams.get(w)||"",10);return Number.isFinite(A)?Math.max(T,Math.min(v,A)):y};try{let w=await Te(a.config);k(e,200,await $i(w,{day:u,tzOffsetMinutes:h("tzOffset",0,-840,840),limit:h("limit",40,1,200)}))}catch(w){k(e,502,{error:w.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let u=n.searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}let h=n.searchParams,w;if(r==="/api/mesh/thread"){let[y,T,v]=[h.get("agent"),h.get("channel"),h.get("chat")];if(!y||!T||!v){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/thread?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(v)}&limit=${encodeURIComponent(h.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[y,T]=[h.get("kind"),h.get("key")];if(!y||!T){k(e,400,{error:"kind and key required"});return}w=`/analytics/job?kind=${encodeURIComponent(y)}&key=${encodeURIComponent(T)}&limit=${encodeURIComponent(h.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[y,T,v]=[h.get("agent"),h.get("channel"),h.get("chat")];if(!y||!T||!v){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/conversation?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(v)}&tzOffset=${encodeURIComponent(h.get("tzOffset")||"0")}`}else{let y=h.get("task");if(!y){k(e,400,{error:"task required"});return}w=`/analytics/run/${encodeURIComponent(y)}`}try{await Pi(e,await Te(a.config),u,w)}catch(y){k(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){Dh(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task");if(!h||!w||!y){k(e,400,{error:"node, agent, task query params required"});return}await Hh(t,e,a,h,w,y);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task"),T=u.searchParams.get("limit")||"50";if(!h||!w){k(e,400,{error:"node and agent query params required"});return}await qh(e,a,h,w,y,T);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("task"),y=u.searchParams.get("kind");if(!h||!w||y!=="cancel"&&y!=="followup"){k(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Fh(t,e,a,h,w,y);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await En(t,e,a,u,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!h.ok)throw new Error(`HTTP ${h.status}`);let w=await h.json();k(e,200,w)}catch(u){k(e,502,{error:u.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!h.ok){k(e,h.status,{error:`HTTP ${h.status}`});return}k(e,200,await h.json())}catch(u){k(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await he(t);try{let h=await Jh(a.config,u);k(e,200,h)}catch(h){k(e,502,{error:h.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!Bh(t,e,[`agent:${u}`]))return;await zh(t,e,a.config,u);return}if(o==="GET"&&r==="/api/node/build"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!h.ok)throw new Error(`HTTP ${h.status}`);k(e,200,xr(await h.json()))}catch(u){k(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",h=u.startsWith("Bearer ")?u.slice(7):"";if(h!==a.token){let w=new G,y=h?w.verify(h):null;if(!y||!Ae(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Rh(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"){k(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(await Cl(t,e,r,o,Rc(a.config)))return;if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await En(t,e,a,u,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let h=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let w=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(A=>({name:A.name,url:A.url,token:A.token}))],y={flag:!1},T=[];t.on("close",()=>{y.flag=!0;for(let A of T)try{A.abort()}catch{}});let v=setInterval(()=>{if(!y.flag)try{e.write(`: ping
|
|
20315
20315
|
|
|
20316
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let A of w)(async()=>{let R={Accept:"text/event-stream"};A.token&&(R.Authorization=`Bearer ${A.token}`);let
|
|
20316
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let A of w)(async()=>{let R={Accept:"text/event-stream"};A.token&&(R.Authorization=`Bearer ${A.token}`);let E=new AbortController;T.push(E);try{let L=await fetch(`${A.url.replace(/\/+$/,"")}/events${h?`?${h}`:""}`,{headers:R,signal:E.signal});if(!L.ok||!L.body)return;let j=L.body.getReader(),$=new TextDecoder,O="";for(;!y.flag;){let{done:U,value:ce}=await j.read();if(U)break;O+=$.decode(ce,{stream:!0});let Z;for(;(Z=O.indexOf(`
|
|
20317
20317
|
|
|
20318
20318
|
`))>=0;){let oe=O.slice(0,Z);if(O=O.slice(Z+2),y.flag)break;try{e.write(oe+`
|
|
20319
20319
|
|
|
20320
|
-
`)}catch{y.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),h=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),w=u.searchParams.get("workflowId")||void 0,y=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",T=a.workflowRuns.list({limit:h,workflowId:w}),v=`?limit=${h}${w?`&workflowId=${encodeURIComponent(w)}`:""}${y?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],R=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let U=new AbortController,ce=setTimeout(()=>U.abort(),5e3);try{let Z=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:O,signal:U.signal});if(!Z.ok)return[];let oe=await Z.json();return Array.isArray(oe.runs)?oe.runs:[]}finally{clearTimeout(ce)}}catch{return[]}})),
|
|
20321
|
-
`;
|
|
20320
|
+
`)}catch{y.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),h=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),w=u.searchParams.get("workflowId")||void 0,y=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",T=a.workflowRuns.list({limit:h,workflowId:w}),v=`?limit=${h}${w?`&workflowId=${encodeURIComponent(w)}`:""}${y?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],R=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let U=new AbortController,ce=setTimeout(()=>U.abort(),5e3);try{let Z=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:O,signal:U.signal});if(!Z.ok)return[];let oe=await Z.json();return Array.isArray(oe.runs)?oe.runs:[]}finally{clearTimeout(ce)}}catch{return[]}})),E=new Map;for(let $ of T)E.set($.id,$);for(let $ of R)for(let O of $)E.set(O.id,O);let L=Array.from(E.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,h),j=y?L.map($=>Ah($)):L;k(e,200,{runs:j})}catch(u){k(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let u=decodeURIComponent(f[1]),h=a.workflowRuns.get(u);if(h){k(e,200,{run:h});return}let w=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({url:y.url,token:y.token}))];for(let y of w)try{let T={};y.token&&(T.Authorization=`Bearer ${y.token}`);let v=await fetch(`${y.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:T});if(v.ok){k(e,200,await v.json());return}}catch{}k(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),w=await fetch(`${h}/api/actions/builtin`,{headers:u}),y=await w.json().catch(()=>({error:`HTTP ${w.status}`}));k(e,w.status,y)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let _=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(_){try{let u=await he(t).catch(()=>({})),h={"Content-Type":"application/json"};a.config.dashboard.token&&(h.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:h,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(r.startsWith("/api/workflows")&&qi(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(h,w,y)=>{if(a.token)return!0;let T=ka(h);if(!T)return!0;let v=new G().verify(T);if(!v)return k(w,401,{error:"invalid or revoked token"}),!1;for(let A of y)if(!Ae(v,A))return k(w,403,{error:`token missing scope: ${A}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){k(e,200,a.boards.map(u=>({id:u.id,name:u.name,source:u.source,primaryToolLabel:u.primaryToolLabel,labels:u.labels,columns:u.columns,timeRangeDays:u.timeRangeDays})));return}let b=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(b&&o==="GET"){let u=a.sources.get(b[1]);if(!u){k(e,404,{error:"unknown board"});return}try{let h=typeof u.listMembers=="function"?await u.listMembers():[];k(e,200,h)}catch(h){k(e,502,{error:h.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(S&&o==="GET"){let u=a.sources.get(S[1]);if(!u){k(e,404,{error:"unknown board"});return}try{let h=typeof u.listMilestones=="function"?await u.listMilestones():[];k(e,200,h)}catch(h){k(e,502,{error:h.message})}return}let g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),x=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(g&&o==="PATCH"){let[,u,h]=g,w=decodeURIComponent(h),y=a.boards.find(E=>E.id===u);if(!y){k(e,404,{error:`unknown board: ${u}`});return}let T=a.sources.get(u);if(!T){k(e,503,{error:`board "${u}" source unavailable`});return}let v=await he(t),A=y.columns.find(E=>E.id===v.to),R=y.columns.find(E=>E.id===v.from);if(!A){k(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await Th(T,w,R,A),wn({actor:kn(t),action:"move",boardId:u,itemId:w,payload:{from:v.from,to:v.to}}),k(e,200,{ok:!0})}catch(E){k(e,502,{error:E.message||"transition failed"})}return}if(x){let[,u,h]=x,w=h?decodeURIComponent(h):void 0,y=a.boards.find(v=>v.id===u);if(!y){k(e,404,{error:`unknown board: ${u}`});return}let T=a.sources.get(u);if(!T){k(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!w){let{columns:v,totals:A}=await Eh(y,T,n.searchParams);k(e,200,{columns:v,totals:A});return}if(o==="GET"&&w){try{let v=typeof T.getItem=="function"?await T.getItem(w):null;if(!v){k(e,404,{error:"not found"});return}k(e,200,v)}catch(v){k(e,502,{error:v.message})}return}if(o==="PATCH"&&w){let v=await he(t);try{let A=typeof T.updateItem=="function"?await T.updateItem(w,v):null;if(!A){k(e,501,{error:"update unsupported"});return}wn({actor:kn(t),action:"update",boardId:u,itemId:w,payload:v}),k(e,200,A)}catch(A){k(e,502,{error:A.message})}return}if(o==="POST"&&!w){let v=await he(t);if(!v.title){k(e,400,{error:"title required"});return}if(!T.capabilities.create||!T.create){k(e,400,{error:`source ${T.type} does not support create`});return}try{let A=await T.create({title:v.title,description:v.description,labels:v.labels,assigneeUsernames:v.assigneeUsernames,milestoneTitle:v.milestoneTitle,projectHint:v.projectHint});wn({actor:kn(t),action:"create",boardId:u,itemId:A.id,payload:{title:v.title}}),k(e,201,A)}catch(A){k(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),w={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(w){e.writeHead(302,{Location:w}),e.end();return}}k(e,404,{error:"not found",path:r})}async function Eh(t,e,a){if(!e.capabilities.listAll||!e.listAll){let x={};for(let u of t.columns)x[u.id]=[];return{columns:x,totals:Object.fromEntries(t.columns.map(u=>[u.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),d=t.columns.some(x=>x.kind!=="closed"),p=t.columns.some(x=>x.kind==="closed"),m=d?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],f=p?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let x of t.columns)_[x.id]=[];let b=t.columns.find(x=>x.kind==="closed");for(let x of f)b&&_[b.id].push({...x,stage:b.id});let S=t.columns.filter(x=>x.kind!=="closed");for(let x of m){let u=In(x,S);if(!u)continue;let h=_[u];h&&h.push({...x,stage:u})}if(i)for(let x of Object.keys(_))_[x]=_[x].filter(u=>u.assignee===i);for(let x of Object.keys(_))_[x].sort((u,h)=>{let w=(u.priority??99)-(h.priority??99);return w!==0?w:(h.updatedAt||"").localeCompare(u.updatedAt||"")});let g=Object.fromEntries(Object.entries(_).map(([x,u])=>[x,u.length]));return{columns:_,totals:g}}async function Th(t,e,a,n){let r=Mn(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 Ah(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 Ch(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 _r(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function wn(t){try{let e=dt(process.cwd(),".agentx");Oc(e)||vh(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
20321
|
+
`;bh(dt(e,"board-audit.jsonl"),a)}catch{}}function kn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Ih=2e3;async function Mh(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 x=new AbortController,u=setTimeout(()=>x.abort(),Ih),h=()=>x.abort();return a?.addEventListener("abort",h,{once:!0}),fetch(t+g,{headers:r,signal:x.signal}).then(async w=>{let y=w.ok?await w.json().catch(()=>{}):void 0;return{ok:y!==void 0,json:async()=>y}}).catch(()=>null).finally(()=>{clearTimeout(u),a?.removeEventListener("abort",h)})},[l,c,d,p,m,f,_,b]=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(p&&p.ok){let g=await p.json().then(x=>Array.isArray(x)?x:[],()=>[]);o.crons=g.map(x=>({id:x.id,enabled:x.enabled===!0,schedule:String(x.schedule||""),timezone:x.timezone,agent:String(x.agent||""),kind:typeof x.command=="string"&&x.command.trim()?"command":"agent",model:x.model,nextRun:x.nextRun,retryPending:x.retryPending===!0,consecutiveErrors:Number(x.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Zn.routines))}if(f&&f.ok){let g=await f.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(b&&b.ok){let g=await b.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Nh(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d?.ok?await d.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var ca=null;function Lh(t){if(ca)return ca;let e=dt(process.cwd(),".agentx/wiki");return ca=Qr({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),ca}async function pa(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 Rh(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||W(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){k(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();k(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){k(t,502,{error:s.message||"daemon unreachable"})}}async function Te(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=W(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:W(a,l)})}let s=await pa(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:W(a,i.url)});return[...o.values()]}var Ph=3e3,$h=6e3,jh=5*6e4,Sn=new Map,da=new Map;function Ze(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=da.get(a);if(n)return n;let r=(async()=>{let o=await Te(t,AbortSignal.timeout(Ph)),s=await Promise.all(o.map(async i=>{let l=await Mh(i.url,i.token,AbortSignal.timeout($h),e);return e?l:Oh(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>da.delete(a));return da.set(a,r),r}function Oh(t,e,a=Date.now()){if(e.reachable&&!e.error)return Sn.set(t,{node:e,at:a}),e;let n=Sn.get(t);return!n||a-n.at>jh?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function M0(){Sn.clear(),da.clear()}function Nh(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 Dh(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}
|
|
20322
20322
|
data: ${JSON.stringify(c)}
|
|
20323
20323
|
|
|
20324
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await
|
|
20325
|
-
${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
|
|
20324
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ze(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 Hh(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let _ of a.config.dashboard.daemons)i.add(_.url.replace(/\/+$/,""));try{let _=await pa(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let b of _)i.add(b.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){k(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=W(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let d=new AbortController,p;try{p=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:d.signal})}catch(_){k(e,502,{error:_.message||"upstream connect failed"});return}if(!p.ok||!p.body){k(e,p.status||502,{error:`upstream HTTP ${p.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=p.body.getReader();(async()=>{try{for(;;){let{value:_,done:b}=await m.read();if(b)break;_&&e.write(_)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{d.abort();try{e.end()}catch{}})}function Bh(t,e,a){let n=ka(t);if(!n)return k(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new G().verify(n);if(!r)return k(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!Ae(r,o))return k(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function zh(t,e,a,n){let r=a.agents?.[n];if(!r){k(e,404,{error:"unknown agent"});return}if(r.access!=="public"){k(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await he(t)}catch{k(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){k(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||{}}})}),d=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(d)}catch(c){k(e,502,{error:c.message||"upstream call failed"})}}async function qh(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let p of e.config.dashboard.daemons)i.add(p.url.replace(/\/+$/,""));try{let p=await pa(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of p)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){k(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=W(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let d=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let p=await fetch(`${s}${d}`,{headers:c}),m=await p.text();t.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(p){k(t,502,{error:p.message||"upstream fetch failed"})}}async function Fh(t,e,a,n,r,o){await En(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function En(t,e,a,n,r){let o={};try{o=await he(t)??{}}catch{}let s=await Nc(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Nc(t,e,a,n){let r=(c,d)=>({status:c,text:JSON.stringify(d),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 pa(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let d of c)s.add(d.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=W(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 Tn(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=nr(e.keysFile);return{store:()=>{let r=Qe();return r?new Mr(r):null},publicKey:()=>rr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Rc(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?Tl({url:a,token:W(t.dashboard,a),operatorKey:xa(process.cwd())??void 0}):null;return Ml(t,process.cwd(),n,Tn(t).reason)}function Dc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ze(t,n),async nodePost(n,r,o){let s=await Nc(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=Tt({root:process.cwd()}).items.map($c)}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=pt(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($c)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=Ie(),d=await At({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return d.ok?{status:200,body:{ok:!0,message:d.message}}:{status:409,body:{error:d.error}}}let l=pt(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 _n=null;function Pc(t){return _n?.days!==t&&(_n={days:t,store:new bt(process.cwd(),Date.now,t)}),_n.store}function Hc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=W(t.dashboard,e),n=Dc(t);return{store:()=>{let r=Qe();return r?new ct(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:xa(process.cwd())??void 0},snapshot:()=>Ze(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=>W(t.dashboard,r.replace(/\/+$/,"")),...Uh(t,e,a)}}function Uh(t,e,a){let n=Tn(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}
|
|
20325
|
+
${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 Wh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>W(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Hc(t);return new la({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 Ze(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:nl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Gh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Qe();return a?new ct(a):null},daemon:{url:e,token:W(t.dashboard,e)}}}function Xh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:W(t.dashboard,e)},nodeName:t.node.name}}function $c(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 Kh=`
|
|
20326
20326
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
20327
20327
|
|
|
20328
20328
|
Title pattern:
|
|
@@ -20354,10 +20354,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
20354
20354
|
Shape:
|
|
20355
20355
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
20356
20356
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
20357
|
-
`;async function
|
|
20357
|
+
`;async function Jh(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):
|
|
20358
20358
|
- ${r.knownLabels.slice(0,60).join(`
|
|
20359
20359
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
20360
|
-
`),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:
|
|
20360
|
+
`),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:Kh}})});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 d=(c.content||"").toString(),p=Vh(d);if(!p||typeof p.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+d.slice(0,400));let m=Array.isArray(p.labels)?p.labels.filter(f=>typeof f=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:p.title.trim(),description:(p.description||"").toString(),labels:m,assigneeUsername:typeof p.assigneeUsername=="string"?p.assigneeUsername:void 0,kind:typeof p.kind=="string"?p.kind:void 0,raw:d}}function Vh(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 Yh(t){let e=kh(wh(import.meta.url));return dt(e,t)}async function Qh(t){return yh(t)}function k(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function he(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function Bc(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:Bc(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 Zh(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;k(e,200,await ea(await zc(r,a.config)))}async function zc(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=en(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=pt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,d=setTimeout(()=>c.abort(),8e3);try{let p=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 p.ok?{nodeId:i.name||i.url,snap:await p.json()}:null}finally{clearTimeout(d)}}catch{return null}}));for(let i of s)i&&n.push(i);return ii(n)}async function eg(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 p=process.env.HOME||"",m=[p&&`${p}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),f=m.find(_=>Oc(_));if(!f){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:m}));return}r="tail",o=["-F","-n","200",f]}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}
|
|
20361
20361
|
|
|
20362
20362
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=p=>{i+=p.toString("utf8");let m;for(;(m=i.indexOf(`
|
|
20363
20363
|
`))>=0;){let f=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
|
|
@@ -20365,5 +20365,5 @@ data: ${f.replace(/\n/g," ")}
|
|
|
20365
20365
|
|
|
20366
20366
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
20367
20367
|
|
|
20368
|
-
`)}catch{}},15e3),d=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",d),s.on("exit",d),s.on("error",d)}async function
|
|
20369
|
-
//# sourceMappingURL=board-dashboard-
|
|
20368
|
+
`)}catch{}},15e3),d=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",d),s.on("exit",d),s.on("error",d)}async function jc(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((p,m)=>{let f=[];t.on("data",_=>f.push(_)),t.on("end",()=>p(Buffer.concat(f))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let d=t.headers["x-requested-with"];d&&(l["X-Requested-With"]=Array.isArray(d)?d[0]:d),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let p=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await p.arrayBuffer());e.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(p){k(e,502,{error:`proxy to peer failed: ${p?.message||p}`,target:r})}}function pt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Bc(n),token:n.dashboardToken||n.token}:null}export{Nh as applyAttachSessions,Mh as fetchDaemonAgents,Sh as handleBoardRequest,M0 as resetLiveCaches,Te as resolveNodeTargets,I0 as startBoardDashboard,Oh as withLastGood};
|
|
20369
|
+
//# sourceMappingURL=board-dashboard-7B2B564A.js.map
|