agentix-cli 0.132.0 → 0.133.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{App-VPYWOTTH.js → App-WQPA77VJ.js} +2 -2
- package/dist/{ChatApp-SNED4KJB.js → ChatApp-TGW66I4Y.js} +2 -2
- package/dist/{absorb-eval-WGO4JWTO.js → absorb-eval-37XZJACN.js} +2 -2
- package/dist/{agent-HXQYYLWZ.js → agent-FWHYHXWC.js} +2 -2
- package/dist/{board-dashboard-44JPXA7J.js → board-dashboard-GKE4KWJH.js} +357 -254
- package/dist/board-dashboard-GKE4KWJH.js.map +1 -0
- package/dist/chunk-2BF6HJJD.js +54 -0
- package/dist/chunk-2BF6HJJD.js.map +1 -0
- package/dist/{chunk-Z7RJ3K3J.js → chunk-3TETB22A.js} +2 -2
- package/dist/{chunk-JRVJXAVC.js → chunk-4NEO5KB2.js} +30 -30
- package/dist/chunk-4NEO5KB2.js.map +1 -0
- package/dist/{chunk-XWVBLISN.js → chunk-4XPVU3N2.js} +2 -2
- package/dist/chunk-57Y2WZT2.js +55 -0
- package/dist/chunk-57Y2WZT2.js.map +1 -0
- package/dist/{chunk-UDMI4TYM.js → chunk-ANC5QXFB.js} +2 -2
- package/dist/chunk-BI6VG4DV.js +37 -0
- package/dist/chunk-BI6VG4DV.js.map +1 -0
- package/dist/{chunk-KDQI5S7F.js → chunk-D5IHICX3.js} +2 -2
- package/dist/{chunk-724IBN5Y.js → chunk-F5PVUB4Y.js} +2 -2
- package/dist/{chunk-3K35L73A.js → chunk-F7GKG5ZO.js} +2 -2
- package/dist/{chunk-KKQPV6SO.js → chunk-GUEIF7ZF.js} +2 -2
- package/dist/{chunk-JNKATLF7.js → chunk-GZY5DYXT.js} +2 -2
- package/dist/{chunk-VCQVF44A.js → chunk-HIUHKOKK.js} +2 -2
- package/dist/chunk-IDZXAOBC.js +156 -0
- package/dist/chunk-IDZXAOBC.js.map +1 -0
- package/dist/chunk-IZDKRNXC.js +52 -0
- package/dist/chunk-IZDKRNXC.js.map +1 -0
- package/dist/{chunk-ZG4G6BFP.js → chunk-JA5Y4LDP.js} +2 -2
- package/dist/{chunk-KQH4LPYC.js → chunk-KUOH5MFS.js} +2 -2
- package/dist/{chunk-WWNZL7XB.js → chunk-OQV3LWJI.js} +2 -2
- package/dist/{chunk-CM74OUXW.js → chunk-PHCWYKQW.js} +2 -2
- package/dist/{chunk-QNKSRROH.js → chunk-RJFPCW7T.js} +2 -2
- package/dist/{chunk-74LPAKQY.js → chunk-RTHZQGFC.js} +2 -2
- package/dist/{chunk-MDGYSHO5.js → chunk-S2UXDEGW.js} +2 -2
- package/dist/{chunk-62NXS7PT.js → chunk-SJPQQ4OF.js} +221 -221
- package/dist/chunk-SJPQQ4OF.js.map +1 -0
- package/dist/{chunk-A6QJ4VFT.js → chunk-V4IFJLQS.js} +2 -2
- package/dist/{chunk-3WYLK3SX.js → chunk-VH2ASPFQ.js} +2 -2
- package/dist/{chunk-RYGVTAP4.js → chunk-ZN5DC6WS.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-TXZF32NO.js → client-7UW2ELPP.js} +2 -2
- package/dist/config-TNYVPT4R.js +2 -0
- package/dist/{config-mutate-KDBXIN7R.js → config-mutate-GV7BVG3I.js} +2 -2
- package/dist/config-mutator-AKCR3VKM.js +2 -0
- package/dist/{contributions-FBVULRR4.js → contributions-J57B3KIX.js} +2 -2
- package/dist/{doctor-NBWYG743.js → doctor-ROKIYJRT.js} +2 -2
- package/dist/follow-up-tool-S2U7DFSW.js +7 -0
- package/dist/follow-up-tool-S2U7DFSW.js.map +1 -0
- package/dist/{hub-3QTJ7E3O.js → hub-HOVJC4HR.js} +2 -2
- package/dist/index.d.ts +1339 -3
- package/dist/index.js +1 -1
- package/dist/{program-SA5O6IQ3.js → program-LAOU5DQ3.js} +195 -195
- package/dist/program-LAOU5DQ3.js.map +1 -0
- package/dist/{promote-4XHYWHLA.js → promote-FVWRM4BE.js} +2 -2
- package/dist/query-HBCL3FHO.js +2 -0
- package/dist/query-settings-RD6GEN2V.js +3 -0
- package/dist/query-settings-RD6GEN2V.js.map +1 -0
- package/dist/{registry-LM35AE2P.js → registry-NT4H7HYP.js} +2 -2
- package/dist/{request-planner-4BAAOUBH.js → request-planner-JOXSAAHO.js} +2 -2
- package/dist/{review-candidates-TM53WR7G.js → review-candidates-6N5435V7.js} +2 -2
- package/dist/{routing-QLS6UMLM.js → routing-6G2QVFIG.js} +2 -2
- package/dist/schedule-tool-3NYUPKSC.js +2 -0
- package/dist/{scheduler-PVXLF2VJ.js → scheduler-WOH2O3EP.js} +2 -2
- package/dist/{seat-OUUN3F45.js → seat-I2FBJDTV.js} +2 -2
- package/dist/{select-D7UUSODY.js → select-5YZQJLLD.js} +2 -2
- package/dist/{set-enabled-FDNS6KW6.js → set-enabled-CQEUZLHU.js} +2 -2
- package/dist/{tool-J5FM3OPM.js → tool-PIJXUBEC.js} +2 -2
- package/dist/{tool-SCBQYDI3.js → tool-R77KFLZ3.js} +2 -2
- package/dist/wiki-GCOFERTB.js +2 -0
- package/package.json +2 -1
- package/dist/board-dashboard-44JPXA7J.js.map +0 -1
- package/dist/chunk-2ZDV3DCT.js +0 -52
- package/dist/chunk-2ZDV3DCT.js.map +0 -1
- package/dist/chunk-62NXS7PT.js.map +0 -1
- package/dist/chunk-7D3RJSN4.js +0 -156
- package/dist/chunk-7D3RJSN4.js.map +0 -1
- package/dist/chunk-EQ33PFXP.js +0 -55
- package/dist/chunk-EQ33PFXP.js.map +0 -1
- package/dist/chunk-JRVJXAVC.js.map +0 -1
- package/dist/chunk-RH3J4LCP.js +0 -37
- package/dist/chunk-RH3J4LCP.js.map +0 -1
- package/dist/chunk-S2RRPTS3.js +0 -54
- package/dist/chunk-S2RRPTS3.js.map +0 -1
- package/dist/config-ZIXIH23X.js +0 -2
- package/dist/config-mutator-HKFGPJMG.js +0 -2
- package/dist/follow-up-tool-E5XKSPKA.js +0 -6
- package/dist/follow-up-tool-E5XKSPKA.js.map +0 -1
- package/dist/program-SA5O6IQ3.js.map +0 -1
- package/dist/query-ZGD32CE2.js +0 -2
- package/dist/query-settings-BSDXFS3V.js +0 -3
- package/dist/query-settings-BSDXFS3V.js.map +0 -1
- package/dist/schedule-tool-TTCWBAQ4.js +0 -2
- package/dist/wiki-IGRRQL6H.js +0 -2
- /package/dist/{App-VPYWOTTH.js.map → App-WQPA77VJ.js.map} +0 -0
- /package/dist/{ChatApp-SNED4KJB.js.map → ChatApp-TGW66I4Y.js.map} +0 -0
- /package/dist/{absorb-eval-WGO4JWTO.js.map → absorb-eval-37XZJACN.js.map} +0 -0
- /package/dist/{agent-HXQYYLWZ.js.map → agent-FWHYHXWC.js.map} +0 -0
- /package/dist/{chunk-Z7RJ3K3J.js.map → chunk-3TETB22A.js.map} +0 -0
- /package/dist/{chunk-XWVBLISN.js.map → chunk-4XPVU3N2.js.map} +0 -0
- /package/dist/{chunk-UDMI4TYM.js.map → chunk-ANC5QXFB.js.map} +0 -0
- /package/dist/{chunk-KDQI5S7F.js.map → chunk-D5IHICX3.js.map} +0 -0
- /package/dist/{chunk-724IBN5Y.js.map → chunk-F5PVUB4Y.js.map} +0 -0
- /package/dist/{chunk-3K35L73A.js.map → chunk-F7GKG5ZO.js.map} +0 -0
- /package/dist/{chunk-KKQPV6SO.js.map → chunk-GUEIF7ZF.js.map} +0 -0
- /package/dist/{chunk-JNKATLF7.js.map → chunk-GZY5DYXT.js.map} +0 -0
- /package/dist/{chunk-VCQVF44A.js.map → chunk-HIUHKOKK.js.map} +0 -0
- /package/dist/{chunk-ZG4G6BFP.js.map → chunk-JA5Y4LDP.js.map} +0 -0
- /package/dist/{chunk-KQH4LPYC.js.map → chunk-KUOH5MFS.js.map} +0 -0
- /package/dist/{chunk-WWNZL7XB.js.map → chunk-OQV3LWJI.js.map} +0 -0
- /package/dist/{chunk-CM74OUXW.js.map → chunk-PHCWYKQW.js.map} +0 -0
- /package/dist/{chunk-QNKSRROH.js.map → chunk-RJFPCW7T.js.map} +0 -0
- /package/dist/{chunk-74LPAKQY.js.map → chunk-RTHZQGFC.js.map} +0 -0
- /package/dist/{chunk-MDGYSHO5.js.map → chunk-S2UXDEGW.js.map} +0 -0
- /package/dist/{chunk-A6QJ4VFT.js.map → chunk-V4IFJLQS.js.map} +0 -0
- /package/dist/{chunk-3WYLK3SX.js.map → chunk-VH2ASPFQ.js.map} +0 -0
- /package/dist/{chunk-RYGVTAP4.js.map → chunk-ZN5DC6WS.js.map} +0 -0
- /package/dist/{client-TXZF32NO.js.map → client-7UW2ELPP.js.map} +0 -0
- /package/dist/{config-ZIXIH23X.js.map → config-TNYVPT4R.js.map} +0 -0
- /package/dist/{config-mutate-KDBXIN7R.js.map → config-mutate-GV7BVG3I.js.map} +0 -0
- /package/dist/{config-mutator-HKFGPJMG.js.map → config-mutator-AKCR3VKM.js.map} +0 -0
- /package/dist/{contributions-FBVULRR4.js.map → contributions-J57B3KIX.js.map} +0 -0
- /package/dist/{doctor-NBWYG743.js.map → doctor-ROKIYJRT.js.map} +0 -0
- /package/dist/{hub-3QTJ7E3O.js.map → hub-HOVJC4HR.js.map} +0 -0
- /package/dist/{promote-4XHYWHLA.js.map → promote-FVWRM4BE.js.map} +0 -0
- /package/dist/{query-ZGD32CE2.js.map → query-HBCL3FHO.js.map} +0 -0
- /package/dist/{registry-LM35AE2P.js.map → registry-NT4H7HYP.js.map} +0 -0
- /package/dist/{request-planner-4BAAOUBH.js.map → request-planner-JOXSAAHO.js.map} +0 -0
- /package/dist/{review-candidates-TM53WR7G.js.map → review-candidates-6N5435V7.js.map} +0 -0
- /package/dist/{routing-QLS6UMLM.js.map → routing-6G2QVFIG.js.map} +0 -0
- /package/dist/{schedule-tool-TTCWBAQ4.js.map → schedule-tool-3NYUPKSC.js.map} +0 -0
- /package/dist/{scheduler-PVXLF2VJ.js.map → scheduler-WOH2O3EP.js.map} +0 -0
- /package/dist/{seat-OUUN3F45.js.map → seat-I2FBJDTV.js.map} +0 -0
- /package/dist/{select-D7UUSODY.js.map → select-5YZQJLLD.js.map} +0 -0
- /package/dist/{set-enabled-FDNS6KW6.js.map → set-enabled-CQEUZLHU.js.map} +0 -0
- /package/dist/{tool-J5FM3OPM.js.map → tool-PIJXUBEC.js.map} +0 -0
- /package/dist/{tool-SCBQYDI3.js.map → tool-R77KFLZ3.js.map} +0 -0
- /package/dist/{wiki-IGRRQL6H.js.map → wiki-GCOFERTB.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{B as Ot,C as ro,D as oo,E as so,a as
|
|
1
|
+
import{B as Ot,C as ro,D as oo,E as so,G as io,H as lo,a as qr,b as zr,c as Fr,d as Ur,e as Ae,f as Wr,g as Gr,h as jt,j as Xr,p as Kr,q as Jr,r as Vr,s as Yr,t as Qr,x as Zr,y as eo}from"./chunk-4NEO5KB2.js";import"./chunk-MCBTVNPX.js";import{a as to}from"./chunk-5NTWGUSJ.js";import{a as ao,b as no}from"./chunk-KBJNJGBP.js";import"./chunk-KFIJDLQ5.js";import"./chunk-5BI2T3WD.js";import{a as C}from"./chunk-GUEIF7ZF.js";import{a as Or}from"./chunk-LNY6N73E.js";import{a as Br}from"./chunk-BKHIR2YJ.js";import{a as qe,b as z,c as I,h as pe,i as Pt,j as se,k as K,l as $t,m as Nr,n as Dr,o as Hr}from"./chunk-B2QYMUTD.js";import{$a as Pr,A as ur,B as St,Ba as Tr,C as mr,Ca as Ar,D as Et,Da as Cr,E as Tt,F as At,G as fr,H as gr,K as xr,L as br,La as Ir,M as vr,Na as Te,Sa as Mr,T as U,U as yr,Ua as Be,V as wr,Va as Ct,Wa as It,Xa as Mt,Ya as Lt,Za as Lr,_a as Rr,a as er,ab as Rt,c as bt,cb as $r,d as _a,e as tr,fb as jr,i as vt,l as Ze,n as ar,z as _t,za as Er}from"./chunk-F7GKG5ZO.js";import"./chunk-GTJIKXDB.js";import{h as Qn,i as Zn}from"./chunk-ANC5QXFB.js";import{p as nr,t as rr}from"./chunk-S2GAEH2F.js";import{a as H,b as kr,c as _r,g as Sr}from"./chunk-7LN4VKDU.js";import{a as hr}from"./chunk-IMLAPB7G.js";import{a as ir,b as yt,d as lr,e as dr,f as wt}from"./chunk-WCXXXAHV.js";import{g as kt}from"./chunk-LQE73AZR.js";import{b as cr,c as pr}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import"./chunk-AKLZ4YO2.js";import"./chunk-VH2ASPFQ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ee,d as or,e as Sa}from"./chunk-EMGB23H5.js";import{b as sr}from"./chunk-JWDJMFU6.js";import{E as Vn,V as ht,W as gt,X as xt,Y as ce,Z as Yn,a as Fn,f as Un,g as wa,h as ka,l as Wn,m as Gn,n as Xn,y as Jn}from"./chunk-BI6VG4DV.js";import"./chunk-QSKG754X.js";import"./chunk-MEFPXHQJ.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-RJFPCW7T.js";import"./chunk-AFRHKA7B.js";import"./chunk-S2UXDEGW.js";import{a as Kn}from"./chunk-D5IHICX3.js";import"./chunk-3UOTLMXD.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-HIUHKOKK.js";import"./chunk-RTHZQGFC.js";import"./chunk-JP5OAMWQ.js";import"./chunk-4VVHGR7H.js";import{g as zn}from"./chunk-JA5Y4LDP.js";import"./chunk-WPNRDEHW.js";import"./chunk-ILEC3IAV.js";import"./chunk-F5PVUB4Y.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-MCI3DIWW.js";import"./chunk-6TURWSMN.js";import"./chunk-QD6IICK7.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import{B as nc,I as Nn,L as va,O as Dn,Q as mt,R as Hn,T as Bn,V as qn,Z as ya,a as Mn,b as Ln,c as ec,pa as X,u as ct,v as tc,w as xa,x as ba,xa as ft}from"./chunk-2BF6HJJD.js";import{a as Rn,b as pt,c as ga,d as Pn,h as $n}from"./chunk-BRK6M6LA.js";import{d as jn,e as ac,f as ut,n as On}from"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ea(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 co(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ea(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"/>'},Ce=(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>'+Ce(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function po(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>
|
|
@@ -7,8 +7,8 @@ import{B as Ot,C as ro,D as oo,E as so,a as zr,b as qr,c as Fr,d as Ur,e as Ae,f
|
|
|
7
7
|
</div>
|
|
8
8
|
<div class="bf-sync">
|
|
9
9
|
<span class="bf-sync__t" id="synced">Gathering…</span>
|
|
10
|
-
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${Ce(
|
|
11
|
-
<button class="ax-btn" id="refresh" title="Refresh now">${Ce(
|
|
10
|
+
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${Ce(ie.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${Ce(ie.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{B as Ot,C as ro,D as oo,E as so,a as zr,b as qr,c as Fr,d as Ur,e as Ae,f
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${Nt(
|
|
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
|
-
${Nt(
|
|
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
|
-
${Nt(
|
|
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
|
-
${Nt(
|
|
39
|
+
${Nt(ie.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${Ce(
|
|
41
|
+
<div class="bf-search">${Ce(ie.search)}
|
|
42
42
|
<input id="search" type="search" placeholder="Search sessions…" aria-label="Search sessions">
|
|
43
43
|
</div>
|
|
44
44
|
<div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
|
|
@@ -46,15 +46,15 @@ ${Nt(se.file,"Session briefings","brief-count")}
|
|
|
46
46
|
<div id="reviews" class="bf-col"></div>
|
|
47
47
|
|
|
48
48
|
<section class="ax-panel bf-connect">
|
|
49
|
-
<div class="bf-connect__head">${Ce(
|
|
49
|
+
<div class="bf-connect__head">${Ce(ie.plug,17)}<h2>Connect a CLI session</h2>
|
|
50
50
|
<span class="bf-connect__note">Daemon-owned processes only</span></div>
|
|
51
51
|
<div class="bf-discover">
|
|
52
52
|
<div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
|
|
53
|
-
<button class="ax-btn" id="discover">${Ce(
|
|
53
|
+
<button class="ax-btn" id="discover">${Ce(ie.search)} Discover CLIs</button>
|
|
54
54
|
</div>
|
|
55
55
|
<div class="bf-cli" id="discovered"></div>
|
|
56
56
|
<details class="bf-manual">
|
|
57
|
-
<summary>${Ce(
|
|
57
|
+
<summary>${Ce(ie.chev,12)} Register manually</summary>
|
|
58
58
|
<div class="bf-forms">
|
|
59
59
|
<form id="register" class="bf-form">
|
|
60
60
|
<div class="ax-sec-label"><h3>Register a session</h3></div>
|
|
@@ -85,7 +85,7 @@ ${Nt(se.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:rc,scripts:`<script>${z({decayOf:Ea,rankByDecay:co})}const ICON = ${JSON.stringify(ie)};${oc}</script>`})}var rc=`
|
|
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
|
+
}`,oc=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 Ta(t,e=20*6e4,a=6){let n=[...t].sort((l,
|
|
779
|
+
})();`;function Ta(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),c=r[r.length-1];c&&l.startedAt-c.to<=e?(c.to=Math.max(c.to,d),c.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let c=1;c<r.length;c++){let p=r[c].from-r[c-1].to;p<d&&(d=p,l=c)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.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,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function Aa(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 uo(t,e=[],a){let{bands:n,gaps:r}=Ta(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(y=>l.startedAt>=y.from&&l.startedAt<=y.to);if(d===-1)continue;let c=n[d],p=c.to-c.from||1,m=(l.startedAt-c.from)/p*100,g=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:d,track:0,left:m,width:g,marks:o.get(l.id)??[]}),s.set(l.laneKey,_)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,c)=>Aa(l.runs.filter(p=>p.band===c))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as sc}from"crypto";import{readFileSync as ic,statSync as lc}from"fs";import{resolve as dc,dirname as cc}from"path";import{fileURLToPath as pc}from"url";var mo=new Map;function Dt(t){let e=mo.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=cc(pc(import.meta.url)),r=dc(n,"web",t),o=lc(r),s=o.size<8e6?sc("sha1").update(ic(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return mo.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>",uc=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],fo={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 ho(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">${fo[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",
|
|
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":""}>${Ht(
|
|
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
|
+
${uc.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">${Ht(
|
|
809
|
+
<span class="ac-k">${Ht(le.x,11)}canceled</span>
|
|
810
810
|
</div>
|
|
811
811
|
</div>
|
|
812
812
|
|
|
@@ -819,7 +819,7 @@ refresh();
|
|
|
819
819
|
<div id="ax-fleet-root" data-hours="24" data-src="${Dt("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:mc,scripts:`<script>${z({computeBands:Ta,packTracks:Aa,buildTimeline:uo})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(fo)};${fc}</script>`})}var mc=`
|
|
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
|
+
`,fc=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 go(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:hc,scripts:`<script src="${Dt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var hc=`
|
|
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,...ba,n-
|
|
1050
|
-
WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${
|
|
1048
|
+
`;import{createServer as Th}from"http";import{appendFileSync as Ah,existsSync as Wd,mkdirSync as Ch}from"fs";import{readFile as Ih}from"fs/promises";import{fileURLToPath as Mh}from"url";import{dirname as Lh,resolve as it}from"path";Dn();function ze(t,e){if(!t)return"absent";let a=or(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ie=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=xo(t.headers["sec-fetch-mode"]),n.site=xo(t.headers["sec-fetch-site"]),n}function xo(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as bc}from"zlib";var gc=[[[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]]],ye={x:100,y:393,width:979,height:547},Ca="#1a1a18",Ia="#ffffff",bo=Math.hypot(ye.width,ye.height)/2/ye.width,qt={full:.74,safe:.37/bo,android:.29/bo,mac:.6};function Ma(t,e){let a=t*e/ye.width,n=t/2-(ye.x+ye.width/2)*a,r=t/2-(ye.y+ye.height/2)*a;return gc.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function xc(t,e){let a=n=>String(Math.round(n*100)/100);return Ma(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function vo(t=64,e=qt.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${Ia}"/><path fill="${Ca}" d="${xc(t,e)}"/></svg>`}var vc=Ao(Ca),yo=Ao(Ia),wo=new Map;function Fe(t){let e=wo.get(t);return e||(e=To({size:t,width:qt.safe,background:"square"}),wo.set(t,e)),e}var yc=vo();function Eo(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:yc}:t==="/favicon.ico"?{type:"image/png",body:_o(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:_o(180)}:null}var ko=new Map;function _o(t){let e=ko.get(t);return e||(e=To({size:t,width:qt.full,background:"square"}),ko.set(t,e)),e}function To(t){let{size:e}=t,a=t.background==="mac"?So(e,[wc(e)]):null,n=So(e,Ma(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,d=n[l],c=s*r+1+i*4;for(let p=0;p<3;p++)o[c+p]=Math.round(yo[p]+(vc[p]-yo[p])*d);o[c+3]=Math.round(255*(a?a[l]:1))}return kc(e,o)}function wc(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,d]of s)for(let c=0;c<=12;c++){let p=(d+90*c/12)*Math.PI/180;o.push([i+r*Math.cos(p),l+r*Math.sin(p)])}return o}var La=8;function So(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],[d,c]=o[(s+1)%o.length];l!==c&&n.push([i,l,d,c])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<La;s++){let i=o+(s+.5)/La;r.length=0;for(let[l,d,c,p]of n)(i>=d&&i<p||i>=p&&i<d)&&r.push(l+(i-d)*(c-l)/(p-d));r.sort((l,d)=>l-d);for(let l=0;l+1<r.length;l+=2){let d=Math.max(0,r[l]),c=Math.min(t,r[l+1]);for(let p=Math.floor(d);p<c;p++){let m=Math.min(p+1,c)-Math.max(p,d);m>0&&(a[o*t+p]+=m/La)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function Ao(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function kc(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]),Ra("IHDR",a),Ra("IDAT",bc(e)),Ra("IEND",Buffer.alloc(0))])}function Ra(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(Sc(n)),Buffer.concat([a,n,r])}var _c=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 Sc(t){let e=4294967295;for(let a of t)e=_c[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}ft();nc();var zt=7,Ec=["waiting_owner","needs_attention"],Tc={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Ue(t,e){let a=t.toLowerCase().split("@")[0],n=Tc[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 Co(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 Io(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(y=>y.name==="person"),i=y=>({id:y.id,state:y.state,agentId:y.agent_id,text:y.text,channel:y.channel,chatId:y.chat_id,createdAt:y.created_at,updatedAt:y.updated_at,closedAt:y.closed_at??null,question:y.question??null,attentionReason:y.attention_reason??null,evidence:y.evidence??null,where:{label:Ue(y.channel,y.chat_id),url:a.linkFor?.(y.channel,y.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${xa.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...xa).map(i):[],d=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ba.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1049
|
+
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...ba,n-zt*864e5).map(i):[],c=[];try{c=jt(t,e,50).filter(y=>y.startedAt>=n-zt*864e5)}catch{}let p=new Map;if(s&&c.length){let y=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 (${c.map(()=>"?").join(",")})`).all(e,...c.map(S=>S.taskId));for(let S of y)p.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=c.map(y=>({...y,where:y.channel?{label:Ue(y.channel,y.chatId??""),url:a.linkFor?.(y.channel,y.chatId??"")??null}:null,request:p.get(y.taskId)??null})),g=new Set(m.map(y=>y.request?.id).filter(Boolean)),_=[...l.filter(y=>!Ec.includes(y.state)),...d].filter(y=>!g.has(y.id));return{open:l,recent:d,runs:m,other:_}}ya();ac();var Mo={waiting:0,yours:0,ahead:null};function Lo(t,e,a={}){let n=jn(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,d=s.get(l)??0;s.set(l,d+1);let c=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};c.waiting++,i.person===e&&(c.yours++,c.ahead===null&&(c.ahead=d),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Ue(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:d})),r.set(i.agentId,c)}return{byAgent:r,mine:o}}var Ac=4e3;function Ro(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-zt*864e5).map(r=>r.agent_id)}function Po(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(mt);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 d=n.queue?.get(l)??Mo,c=s.get(l),p=c??i.get(l);if(!p)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:d};let m=o(p.person??null),g=p.status==="error"||p.status==="timeout",_=c?"working":g&&m==="you"?"blocked":"free",y=m==="you"&&p.channel!=="a2a",S=y&&p.channel;return{agentId:l,state:_,by:m,at:c?p.started_at:p.finished_at??p.started_at,text:c||y?p.message_preview??null:null,fullText:y&&c&&String(p.original_message??p.message_preview??"").slice(0,Ac)||null,where:S?{label:Ue(p.channel,p.chat_id??""),url:n.linkFor?.(p.channel,p.chat_id??"")??null}:null,queue:d}})}function $o(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function jo(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 Oo(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 No(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 Do(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 Ho(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 Bo(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 qo(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 zo=`
|
|
1053
1053
|
(function () {
|
|
1054
1054
|
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1055
1055
|
var who = document.getElementById('who');
|
|
@@ -1364,7 +1364,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1364
1364
|
.blank { padding: 28px 24px; border: var(--ax-border-w) dashed var(--ax-border-2); border-radius: var(--ax-radius-lg); }
|
|
1365
1365
|
.blank p + p { margin-top: 8px; color: var(--ax-text-2); }
|
|
1366
1366
|
.foot { margin-top: 28px; font-size: 14px; color: var(--ax-text-2); }
|
|
1367
|
-
`,
|
|
1367
|
+
`,Fo=`
|
|
1368
1368
|
.pair-form { display: grid; gap: 8px; margin-top: 20px; }
|
|
1369
1369
|
.pair-form label { font-weight: 600; margin-top: 8px; }
|
|
1370
1370
|
.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); }
|
|
@@ -1376,11 +1376,11 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1376
1376
|
.card .pair-msg.bad { color: var(--ax-red-ink); }
|
|
1377
1377
|
[data-theme="dark"] .card .pair-msg.bad { color: var(--ax-red); }
|
|
1378
1378
|
.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); }
|
|
1379
|
-
`,
|
|
1379
|
+
`,Uo=`
|
|
1380
1380
|
.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; }
|
|
1381
1381
|
@keyframes breathe { 50% { opacity: 0.35; } }
|
|
1382
1382
|
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }
|
|
1383
|
-
`;var
|
|
1383
|
+
`;var Cc="<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 Pa(t,e={}){return`<meta charset="utf-8">
|
|
1384
1384
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1385
1385
|
<meta name="theme-color" content="#2979FF">
|
|
1386
1386
|
<meta name="referrer" content="no-referrer">
|
|
@@ -1390,8 +1390,8 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1390
1390
|
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1391
1391
|
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1392
1392
|
<title>${t}</title>
|
|
1393
|
-
${
|
|
1394
|
-
<style>${
|
|
1393
|
+
${Cc}
|
|
1394
|
+
<style>${qe}${Gt}</style>`}function Wo(){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 Go=`
|
|
1395
1395
|
var CACHE = 'agentx-member-v1';
|
|
1396
1396
|
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
1397
1397
|
self.addEventListener('install', function (e) {
|
|
@@ -1424,7 +1424,7 @@ self.addEventListener('fetch', function (e) {
|
|
|
1424
1424
|
`;function $a(t,e="",a="My work"){return`<header class="bar">
|
|
1425
1425
|
<img class="mark" src="/member/icon-192.png" alt="" width="36" height="36">
|
|
1426
1426
|
<div class="grow"><h1>${a}</h1><p id="who" class="who">${t}</p></div>${e}
|
|
1427
|
-
</header>`}var ja=Pa,Oa=$a;function
|
|
1427
|
+
</header>`}var ja=Pa,Oa=$a;function Xo(t){return`<ol class="steps" role="list" 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 Ko(){return`<!doctype html>
|
|
1428
1428
|
<html lang="en">
|
|
1429
1429
|
<head>${ja("My work \xB7 AgentX")}<style>${Xt}</style></head>
|
|
1430
1430
|
<body>
|
|
@@ -1439,15 +1439,15 @@ ${Oa("Connecting\u2026",`
|
|
|
1439
1439
|
<section aria-labelledby="h-sent"><h2 id="h-sent" tabindex="-1">What you sent <span class="n">(last 7 days)</span></h2><ul id="sent" class="rows" role="list"></ul></section>
|
|
1440
1440
|
<p id="updated" class="foot"></p>
|
|
1441
1441
|
</main>
|
|
1442
|
-
<script>${
|
|
1442
|
+
<script>${z({workState:Ic,ageText:Na,connectionNote:Ut,plainPreview:Wt,agentLine:No,sentState:Do,requestState:Ho,summaryLine:Bo,freedAgents:qo})}${zo}</script>
|
|
1443
1443
|
</body>
|
|
1444
|
-
</html>`}function
|
|
1444
|
+
</html>`}function Jo(){return`<!doctype html>
|
|
1445
1445
|
<html lang="en">
|
|
1446
|
-
<head>${ja("Pair this machine \xB7 AgentX")}<style>${
|
|
1446
|
+
<head>${ja("Pair this machine \xB7 AgentX")}<style>${Fo}</style></head>
|
|
1447
1447
|
<body>
|
|
1448
1448
|
${Oa("This machine is not paired yet")}
|
|
1449
1449
|
<main class="narrow">
|
|
1450
|
-
${
|
|
1450
|
+
${Xo(0)}
|
|
1451
1451
|
<div class="card">
|
|
1452
1452
|
<h2>Pair this machine</h2>
|
|
1453
1453
|
<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>
|
|
@@ -1464,24 +1464,24 @@ ${Oa("This machine is not paired yet")}
|
|
|
1464
1464
|
<p class="help">No code? Ask the person who invited you for one. A code works once, for 10 minutes.</p>
|
|
1465
1465
|
</div>
|
|
1466
1466
|
</main>
|
|
1467
|
-
<script>${
|
|
1467
|
+
<script>${z({formatPairInput:Ft})}${Mc}</script>
|
|
1468
1468
|
</body>
|
|
1469
|
-
</html>`}function
|
|
1469
|
+
</html>`}function Vo(){return`<!doctype html>
|
|
1470
1470
|
<html lang="en">
|
|
1471
|
-
<head>${ja("Waiting for the owner \xB7 AgentX")}<style>${
|
|
1471
|
+
<head>${ja("Waiting for the owner \xB7 AgentX")}<style>${Uo}</style></head>
|
|
1472
1472
|
<body>
|
|
1473
1473
|
${Oa("This machine is paired")}
|
|
1474
1474
|
<main class="narrow">
|
|
1475
|
-
${
|
|
1475
|
+
${Xo(1)}
|
|
1476
1476
|
<div class="card">
|
|
1477
1477
|
<h2><span class="pulse" aria-hidden="true"></span>Waiting for the owner</h2>
|
|
1478
1478
|
<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>
|
|
1479
1479
|
<p class="help">If they say no, this page asks for a new code.</p>
|
|
1480
1480
|
</div>
|
|
1481
1481
|
</main>
|
|
1482
|
-
<script>${
|
|
1482
|
+
<script>${Lc}</script>
|
|
1483
1483
|
</body>
|
|
1484
|
-
</html>`}function
|
|
1484
|
+
</html>`}function Ic(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 Na(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 ago";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min ago":Math.floor(r/24)+" d "+r%24+" h ago"}var Mc=`
|
|
1485
1485
|
(function () {
|
|
1486
1486
|
var form = document.getElementById('pair-form');
|
|
1487
1487
|
var machine = document.getElementById('machine');
|
|
@@ -1525,7 +1525,7 @@ ${Oa("This machine is paired")}
|
|
|
1525
1525
|
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1526
1526
|
});
|
|
1527
1527
|
})();
|
|
1528
|
-
`,
|
|
1528
|
+
`,Lc=`
|
|
1529
1529
|
(function () {
|
|
1530
1530
|
var msg = document.getElementById('msg');
|
|
1531
1531
|
function check() {
|
|
@@ -1536,13 +1536,13 @@ ${Oa("This machine is paired")}
|
|
|
1536
1536
|
}
|
|
1537
1537
|
setInterval(check, 5000);
|
|
1538
1538
|
})();
|
|
1539
|
-
`;function
|
|
1539
|
+
`;function Yo(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 Zo(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 Da="/member/client.webmanifest",et="Your project";function es(){return JSON.stringify({id:"/member?client",name:`${et} \xB7 AgentX`,short_name:et,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 Rc=`
|
|
1540
1540
|
.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); }
|
|
1541
1541
|
.wrap .about h2 { margin: 0 0 6px; }
|
|
1542
1542
|
.about p + p { margin-top: 6px; }
|
|
1543
|
-
`;function
|
|
1543
|
+
`;function ts(){return`<!doctype html>
|
|
1544
1544
|
<html lang="en">
|
|
1545
|
-
<head>${Pa(`${et} \xB7 AgentX`,{manifest:Da,appTitle:et})}<style>${
|
|
1545
|
+
<head>${Pa(`${et} \xB7 AgentX`,{manifest:Da,appTitle:et})}<style>${qe}${Gt}${Xt}${Rc}</style></head>
|
|
1546
1546
|
<body>
|
|
1547
1547
|
${$a("Connecting\u2026",`
|
|
1548
1548
|
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,et)}
|
|
@@ -1557,9 +1557,9 @@ ${$a("Connecting\u2026",`
|
|
|
1557
1557
|
</section>
|
|
1558
1558
|
<p id="updated" class="foot"></p>
|
|
1559
1559
|
</main>
|
|
1560
|
-
<script>${
|
|
1560
|
+
<script>${z({ageText:Na,connectionNote:Ut,plainPreview:Wt,clientSentState:Yo,clientRequestState:Qo,clientSummary:Zo})}${Pc}</script>
|
|
1561
1561
|
</body>
|
|
1562
|
-
</html>`}var
|
|
1562
|
+
</html>`}var Pc=`
|
|
1563
1563
|
(function () {
|
|
1564
1564
|
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1565
1565
|
var who = document.getElementById('who');
|
|
@@ -1666,10 +1666,10 @@ ${$a("Connecting\u2026",`
|
|
|
1666
1666
|
showConn();
|
|
1667
1667
|
load();
|
|
1668
1668
|
})();
|
|
1669
|
-
`;var Kt="agentx_member",Rd=90*86400,Pd=new At,ns=t=>t.replace(/^\[app\]/,"[member]"),$d=new Ie(t=>console.log(ns(t))),es=new WeakMap;function jd(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return $d;let e=es.get(t.log);return e||es.set(t.log,e=new Ie(a=>t.log(ns(a)))),e}var ts=null;function tt(t,e=X){try{return ts=e().people}catch{return ts??t}}async function rs(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 ht(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new kt(r.root),limiter:r.pairLimiter??Pd,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return fe(e,200,"application/manifest+json",Fo());if(a===Da)return fe(e,200,"application/manifest+json",Qo());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),fe(e,200,"text/javascript; charset=utf-8",Uo);if(a==="/member/icon-192.png")return fe(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/member/icon-512.png")return fe(e,200,"image/png",Fe(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Jr(t,i);return p.status===200&&e.setHeader("Set-Cookie",as(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),we(e,p.status,p.body)}let l=Yr(Nd(t),i,Kr(t));if(!l.ok){if(l.status===401){let p=Ha(t);return jd(r).record(a.slice(0,120),Bt(t,qe(Ba(t,Kt),o),p?qe(p,o):null)),a==="/member"?fe(e,401,"text/html; charset=utf-8",Xo()):we(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?fe(e,202,"text/html; charset=utf-8",Ko()):we(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=Ba(t,Kt);return p&&!Ha(t)&&e.setHeader("Set-Cookie",as(p)),fe(e,200,"text/html; charset=utf-8",d?Zo():Go())}if(n==="GET"&&a==="/api/member/me")return we(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 we(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=Ao(p,l.personId,{now:m,linkFor:r.linkFor}),_=(T,h)=>{let u=h instanceof Error?h.message:String(h);/no such table/i.test(u)||r.log?.(`[member] ${T} failed: ${u}`)},b={byAgent:new Map,mine:[]};try{b=Io(p,l.personId,{linkFor:r.linkFor})}catch(T){_("the line",T)}let S=[];if(d)return we(e,200,{...Od(g),agents:S});try{let T=Mo(p,c??{id:l.personId},m);S=Lo(p,l.personId,T,{people:r.people(),linkFor:r.linkFor,queue:b.byAgent})}catch(T){_("agent cards",T)}return we(e,200,{...g,agents:S,queued:b.mine})}return we(e,404,{error:"not found"})}function Od(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 as(t){return`${Kt}=${t}; Path=/; Max-Age=${Rd}; HttpOnly; Secure; SameSite=Lax`}function Nd(t){return Ha(t)??Ba(t,Kt)}function Ha(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ba(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 we(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}Qc();var os='/*! 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 ms,writeFileSync as fs,rmSync as Mx,mkdirSync as Fd,copyFileSync as Ud,readdirSync as Wd}from"fs";import{resolve as Ge}from"path";Zc();function is(t){let e=dt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:dt.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=dt.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 ss=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function ls(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 cs(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:ss(t?.chats),senders:ss(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 ds(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 ps(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}"`})}ft();var ue={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 us(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=pe({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+Hd()+Nr,css:zd,scripts:`${e}<script>${Dr}
|
|
1669
|
+
`;var Kt="agentx_member",$c=90*86400,jc=new At,os=t=>t.replace(/^\[app\]/,"[member]"),Oc=new Ie(t=>console.log(os(t))),as=new WeakMap;function Nc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Oc;let e=as.get(t.log);return e||as.set(t.log,e=new Ie(a=>t.log(os(a)))),e}var ns=null;function tt(t,e=X){try{return ns=e().people}catch{return ns??t}}async function ss(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 ht(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new kt(r.root),limiter:r.pairLimiter??jc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return fe(e,200,"application/manifest+json",Wo());if(a===Da)return fe(e,200,"application/manifest+json",es());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),fe(e,200,"text/javascript; charset=utf-8",Go);if(a==="/member/icon-192.png")return fe(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/member/icon-512.png")return fe(e,200,"image/png",Fe(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Jr(t,i);return p.status===200&&e.setHeader("Set-Cookie",rs(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),we(e,p.status,p.body)}let l=Yr(Hc(t),i,Kr(t));if(!l.ok){if(l.status===401){let p=Ha(t);return Nc(r).record(a.slice(0,120),Bt(t,ze(Ba(t,Kt),o),p?ze(p,o):null)),a==="/member"?fe(e,401,"text/html; charset=utf-8",Jo()):we(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?fe(e,202,"text/html; charset=utf-8",Vo()):we(e,403,{error:l.error,waiting:!0})}let d=r.people().find(p=>p.id===l.personId),c=d?.role==="client";if(n==="GET"&&a==="/member"){let p=Ba(t,Kt);return p&&!Ha(t)&&e.setHeader("Set-Cookie",rs(p)),fe(e,200,"text/html; charset=utf-8",c?ts():Ko())}if(n==="GET"&&a==="/api/member/me")return we(e,200,{person:l.personId,name:d?.name??l.personId,role:d?.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 we(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=Io(p,l.personId,{now:m,linkFor:r.linkFor}),_=(T,h)=>{let u=h instanceof Error?h.message:String(h);/no such table/i.test(u)||r.log?.(`[member] ${T} failed: ${u}`)},y={byAgent:new Map,mine:[]};try{y=Lo(p,l.personId,{linkFor:r.linkFor})}catch(T){_("the line",T)}let S=[];if(c)return we(e,200,{...Dc(g),agents:S});try{let T=Ro(p,d??{id:l.personId},m);S=Po(p,l.personId,T,{people:r.people(),linkFor:r.linkFor,queue:y.byAgent})}catch(T){_("agent cards",T)}return we(e,200,{...g,agents:S,queued:y.mine})}return we(e,404,{error:"not found"})}function Dc(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 rs(t){return`${Kt}=${t}; Path=/; Max-Age=${$c}; HttpOnly; Secure; SameSite=Lax`}function Hc(t){return Ha(t)??Ba(t,Kt)}function Ha(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ba(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 we(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}ec();var is='/*! 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 hs,writeFileSync as gs,rmSync as Rx,mkdirSync as Wc,copyFileSync as Gc,readdirSync as Xc}from"fs";import{resolve as Ge}from"path";tc();function ds(t){let e=ct.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ct.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=ct.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 ls=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function cs(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 ps(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:ls(t?.chats),senders:ls(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 us(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 ms(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}"`})}ft();var ue={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 fs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=pe({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+qc()+Nr,css:Fc,scripts:`${e}<script>${Dr}
|
|
1670
1670
|
${Hr}
|
|
1671
|
-
${
|
|
1672
|
-
${
|
|
1671
|
+
${Bc}
|
|
1672
|
+
${Uc}</script>`})}var Bc=`
|
|
1673
1673
|
(function(){
|
|
1674
1674
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1675
1675
|
async function voiceMissing() {
|
|
@@ -1763,8 +1763,8 @@ ${qd}</script>`})}var Dd=`
|
|
|
1763
1763
|
refresh();
|
|
1764
1764
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1765
1765
|
document.addEventListener('ax-config-saved', refresh);
|
|
1766
|
-
})();`;function
|
|
1767
|
-
`:"";return
|
|
1766
|
+
})();`;function qc(){let t=_r().business?`<button data-tab="business">Business</button>
|
|
1767
|
+
`:"";return zc.replace("__BUSINESS_TABS__",t)}var zc=`
|
|
1768
1768
|
<div id="peer-banner" class="peer-banner">
|
|
1769
1769
|
<span class="label">Managing</span>
|
|
1770
1770
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -1910,7 +1910,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
1910
1910
|
|
|
1911
1911
|
<section id="tab-agents" class="tab active">
|
|
1912
1912
|
${K({icon:ue.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
|
|
1913
|
-
${
|
|
1913
|
+
${se({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
|
|
1914
1914
|
<div id="agent-list" class="ax-stack"></div>
|
|
1915
1915
|
<details class="add-form" style="margin-top:14px" id="wiki-curator-section">
|
|
1916
1916
|
<summary class="primary">\u{1F4AC} Wiki page curator</summary>
|
|
@@ -1943,7 +1943,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
1943
1943
|
|
|
1944
1944
|
<section id="tab-channels" class="tab">
|
|
1945
1945
|
${K({icon:ue.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
|
|
1946
|
-
${
|
|
1946
|
+
${se({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
|
|
1947
1947
|
|
|
1948
1948
|
<details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
|
|
1949
1949
|
<summary class="primary">\u2699 Notifications routing</summary>
|
|
@@ -2050,7 +2050,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2050
2050
|
|
|
2051
2051
|
<section id="tab-crons" class="tab">
|
|
2052
2052
|
${K({icon:ue.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
|
|
2053
|
-
${
|
|
2053
|
+
${se({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
|
|
2054
2054
|
<div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
|
|
2055
2055
|
|
|
2056
2056
|
<div class="ax-builder">
|
|
@@ -2172,7 +2172,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2172
2172
|
|
|
2173
2173
|
<section id="tab-webhooks" class="tab">
|
|
2174
2174
|
${K({icon:ue.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
|
|
2175
|
-
${
|
|
2175
|
+
${se({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
|
|
2176
2176
|
<div id="webhook-list" class="ax-stack"></div>
|
|
2177
2177
|
<div class="add-form">
|
|
2178
2178
|
<h3>Add a webhook</h3>
|
|
@@ -2215,7 +2215,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2215
2215
|
<section id="tab-mesh" class="tab">
|
|
2216
2216
|
${K({icon:ue.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."})}
|
|
2217
2217
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
2218
|
-
${
|
|
2218
|
+
${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."})}
|
|
2219
2219
|
${$t({label:"Connected peers"})}
|
|
2220
2220
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
2221
2221
|
<div class="add-form">
|
|
@@ -2244,7 +2244,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2244
2244
|
|
|
2245
2245
|
<section id="tab-business" class="tab">
|
|
2246
2246
|
${K({icon:ue.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
|
|
2247
|
-
${
|
|
2247
|
+
${se({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
|
|
2248
2248
|
|
|
2249
2249
|
<div class="ax-stack" style="margin-top:14px">
|
|
2250
2250
|
<h3 style="margin:0 0 6px;font-size:13px">Org chart</h3>
|
|
@@ -2332,7 +2332,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2332
2332
|
|
|
2333
2333
|
<section id="tab-boards-cfg" class="tab">
|
|
2334
2334
|
${K({icon:ue.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
|
|
2335
|
-
${
|
|
2335
|
+
${se({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
|
|
2336
2336
|
|
|
2337
2337
|
<div class="ax-stack" style="margin-top:14px">
|
|
2338
2338
|
<h3 style="margin:0 0 6px;font-size:13px">Boards</h3>
|
|
@@ -2357,7 +2357,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2357
2357
|
|
|
2358
2358
|
<section id="tab-actions" class="tab">
|
|
2359
2359
|
${K({icon:ue.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
|
|
2360
|
-
${
|
|
2360
|
+
${se({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
|
|
2361
2361
|
|
|
2362
2362
|
<div class="ax-stack" style="margin-top:14px">
|
|
2363
2363
|
<h3 style="margin:0 0 6px;font-size:13px">Registered actions</h3>
|
|
@@ -2413,7 +2413,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2413
2413
|
|
|
2414
2414
|
<section id="tab-tokens" class="tab">
|
|
2415
2415
|
${K({icon:ue.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
|
|
2416
|
-
${
|
|
2416
|
+
${se({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
|
|
2417
2417
|
<div id="token-list" class="ax-stack"></div>
|
|
2418
2418
|
<div class="add-form">
|
|
2419
2419
|
<h3>Mint a new token</h3>
|
|
@@ -2433,7 +2433,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2433
2433
|
|
|
2434
2434
|
<section id="tab-advanced" class="tab">
|
|
2435
2435
|
${K({icon:ue.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
|
|
2436
|
-
${
|
|
2436
|
+
${se({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
|
|
2437
2437
|
|
|
2438
2438
|
<div class="ax-jv-toolbar">
|
|
2439
2439
|
<input class="ax-jv-search" id="jv-search" placeholder="Search keys & values\u2026" />
|
|
@@ -2459,7 +2459,7 @@ ${qd}</script>`})}var Dd=`
|
|
|
2459
2459
|
<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>
|
|
2460
2460
|
</section>
|
|
2461
2461
|
</main>
|
|
2462
|
-
`,
|
|
2462
|
+
`,Fc=`
|
|
2463
2463
|
|
|
2464
2464
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
2465
2465
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2667,7 +2667,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2667
2667
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2668
2668
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2669
2669
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2670
|
-
`,
|
|
2670
|
+
`,Uc=`
|
|
2671
2671
|
const $ = (id) => document.getElementById(id);
|
|
2672
2672
|
let state = null;
|
|
2673
2673
|
|
|
@@ -5636,11 +5636,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
5636
5636
|
})();
|
|
5637
5637
|
|
|
5638
5638
|
refresh();
|
|
5639
|
-
`;function hs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(us({peers:a,localToken:n}))}async function gs(t,e){let a=Fa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function xs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await op(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Gd(t),r={"GET /api/admin/state":()=>Kd(),"POST /api/admin/agents":()=>ep(n),"PATCH /api/admin/agents":()=>tp(n),"DELETE /api/admin/agents":()=>ap(n),"POST /api/admin/agents/access":()=>Jd(n),"POST /api/admin/channels/telegram":()=>np(n),"DELETE /api/admin/channels/telegram":()=>Ap(n),"POST /api/admin/channels/telegram/toggle":()=>Cp(n),"POST /api/admin/crons":()=>Ip(n),"DELETE /api/admin/crons":()=>Mp(n),"POST /api/admin/config/raw":()=>Lp(n),"GET /api/admin/tokens":()=>Vd(),"POST /api/admin/tokens":()=>Yd(n),"DELETE /api/admin/tokens":()=>Qd(n),"POST /api/admin/agents/test":()=>Zd(n),"POST /api/admin/agents/integrations":()=>pp(n),"DELETE /api/admin/agents/integrations":()=>up(n),"PATCH /api/admin/agents/integrations":()=>mp(n),"PATCH /api/admin/channels/telegram":()=>rp(n),"POST /api/admin/channels/slack":()=>yp(n),"POST /api/admin/channels/slack/toggle":()=>wp(n),"POST /api/admin/channels/discord":()=>kp(n),"POST /api/admin/channels/discord/toggle":()=>_p(n),"POST /api/admin/channels/gitlab":()=>Sp(n),"POST /api/admin/channels/gitlab/toggle":()=>Ep(n),"POST /api/admin/channels/request-status":()=>eo(n),"GET /api/admin/channels/whatsapp/state":()=>We("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>We("/webrtc/history"),"POST /api/admin/actions":()=>Up(n),"DELETE /api/admin/actions":()=>Wp(n),"POST /api/admin/actions/run":()=>Gp(n),"GET /api/admin/channels/whatsapp/chats":()=>We("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>We("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>he("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Tp(n),"POST /api/admin/webhooks":()=>fp(n),"PATCH /api/admin/webhooks":()=>hp(n),"DELETE /api/admin/webhooks":()=>vp(n),"POST /api/admin/whatsapp-triage":()=>ls(n),"POST /api/admin/whatsapp-triage/rules":()=>cs(n),"PATCH /api/admin/whatsapp-triage/rules":()=>ds(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ps(n),"POST /api/admin/mesh/peers":()=>gp(n),"DELETE /api/admin/mesh/peers":()=>xp(n),"POST /api/admin/mesh/toggle":()=>bp(n),"GET /api/admin/files":()=>sp(t),"GET /api/admin/files/read":()=>ip(t),"PUT /api/admin/files":()=>lp(n),"POST /api/admin/files/skill":()=>cp(n),"DELETE /api/admin/files/skill":()=>dp(n),"POST /api/admin/business/orgchart":()=>Rp(n),"DELETE /api/admin/business/orgchart":()=>Pp(n),"POST /api/admin/business/project":()=>$p(n),"DELETE /api/admin/business/project":()=>Np(n),"POST /api/admin/business/client":()=>jp(n),"DELETE /api/admin/business/client":()=>Op(n),"POST /api/admin/business/contact":()=>Dp(n),"DELETE /api/admin/business/contact":()=>Hp(n),"POST /api/admin/boards":()=>Bp(n),"DELETE /api/admin/boards":()=>zp(n),"POST /api/admin/boards/columns":()=>qp(n),"DELETE /api/admin/boards/columns":()=>Fp(n),"POST /api/admin/notifications":()=>Jp(n),"POST /api/admin/wiki/curator":()=>Kp(n),"POST /api/admin/screen":()=>Yp(n),"POST /api/admin/wiki-notes":()=>Vp(n),"GET /api/admin/wiki-notes/list":()=>We("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>Qp(n),"POST /api/admin/mesh/health":()=>Xp(n),"GET /api/admin/projects":()=>We("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>he("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>he("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>he("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>he("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>he("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>he("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>he("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>he("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){za(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();za(e,200,i)}catch(n){za(e,400,{error:n.message||"admin op failed"})}}function za(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Gd(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 Xd(t){let e=Ge(process.cwd(),t);if(!Vt(e))return[];let a=[];for(let n of Wd(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(ms(Ge(e,n.name),"utf-8")))}catch{}return a}function Fa(){let t=Ge(process.cwd(),"agentx.json");return Vt(t)?JSON.parse(ms(t,"utf-8")):null}function Kd(){let t=Fa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([h,u])=>({id:h,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",wikiAbsorb:u.wiki?.absorb?.enabled!==!1,integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(f=>{let y=f.credentials||{},v={};for(let[E,x]of Object.entries(y))typeof x=="string"&&/^[A-Z][A-Z0-9_]*$/.test(x)?v[E]=process.env[x]?"set":"unset":typeof x=="string"&&(v[E]="literal");return{kind:f.kind,label:f.label,enabled:f.enabled!==!1,credentials:y,credStatus:v,metadata:f.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([h,u])=>({id:h,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(([h,u])=>({id:h,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(h=>({id:h.id,source:h.source,agentId:h.agentId,secretEnv:h.secretEnv||"",description:h.description||"",enabled:h.enabled!==!1,triggers:h.triggers&&typeof h.triggers=="object"?h.triggers:{},defaultWorkflow:h.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(h=>({url:h.url,name:h.name,hasToken:!!h.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},g={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:nr(_.local),ntfy:ro(t.channels?.ntfy)},S=[];try{S=Xd(".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,f)=>u.id.localeCompare(f.id))}catch{}let T=(Array.isArray(t.boards)?t.boards:[]).map(h=>({id:h.id,name:h.name,source:h.source||{type:"gitlab",projects:[]},primaryToolLabel:h.primaryToolLabel||"",timeRangeDays:h.timeRangeDays??30,closedWindowDays:h.closedWindowDays??30,columns:Array.isArray(h.columns)?h.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Zr(t),whatsappTriage:is(t),crons:l,webhooks:c,mesh:d,daemonUrl:p,nodeName:t.node?.name,business:g,boards:T,notifications:b,screen:$r(t.screen),wikiNotes:ao(t.wikiNotes),actions:S,wikiCurator:ys(t)}}function Jd(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 Vd(){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 Yd(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 Qd(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 Zd(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 ep(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=vs(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=Ge(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=Ge(i,"CLAUDE.md");if(!Vt(c))try{Fd(i,{recursive:!0}),fs(c,`# ${a}
|
|
5639
|
+
`;function xs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fs({peers:a,localToken:n}))}async function bs(t,e){let a=Fa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function vs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await ip(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Kc(t),r={"GET /api/admin/state":()=>Vc(),"POST /api/admin/agents":()=>ap(n),"PATCH /api/admin/agents":()=>np(n),"DELETE /api/admin/agents":()=>rp(n),"POST /api/admin/agents/access":()=>Yc(n),"POST /api/admin/channels/telegram":()=>op(n),"DELETE /api/admin/channels/telegram":()=>Ip(n),"POST /api/admin/channels/telegram/toggle":()=>Mp(n),"POST /api/admin/crons":()=>Lp(n),"DELETE /api/admin/crons":()=>Rp(n),"POST /api/admin/config/raw":()=>Pp(n),"GET /api/admin/tokens":()=>Qc(),"POST /api/admin/tokens":()=>Zc(n),"DELETE /api/admin/tokens":()=>ep(n),"POST /api/admin/agents/test":()=>tp(n),"POST /api/admin/agents/integrations":()=>mp(n),"DELETE /api/admin/agents/integrations":()=>fp(n),"PATCH /api/admin/agents/integrations":()=>hp(n),"PATCH /api/admin/channels/telegram":()=>sp(n),"POST /api/admin/channels/slack":()=>kp(n),"POST /api/admin/channels/slack/toggle":()=>_p(n),"POST /api/admin/channels/discord":()=>Sp(n),"POST /api/admin/channels/discord/toggle":()=>Ep(n),"POST /api/admin/channels/gitlab":()=>Tp(n),"POST /api/admin/channels/gitlab/toggle":()=>Ap(n),"POST /api/admin/channels/request-status":()=>eo(n),"GET /api/admin/channels/whatsapp/state":()=>We("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>We("/webrtc/history"),"POST /api/admin/actions":()=>Gp(n),"DELETE /api/admin/actions":()=>Xp(n),"POST /api/admin/actions/run":()=>Kp(n),"GET /api/admin/channels/whatsapp/chats":()=>We("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>We("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>he("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Cp(n),"POST /api/admin/webhooks":()=>gp(n),"PATCH /api/admin/webhooks":()=>xp(n),"DELETE /api/admin/webhooks":()=>wp(n),"POST /api/admin/whatsapp-triage":()=>cs(n),"POST /api/admin/whatsapp-triage/rules":()=>ps(n),"PATCH /api/admin/whatsapp-triage/rules":()=>us(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ms(n),"POST /api/admin/mesh/peers":()=>bp(n),"DELETE /api/admin/mesh/peers":()=>vp(n),"POST /api/admin/mesh/toggle":()=>yp(n),"GET /api/admin/files":()=>lp(t),"GET /api/admin/files/read":()=>dp(t),"PUT /api/admin/files":()=>cp(n),"POST /api/admin/files/skill":()=>pp(n),"DELETE /api/admin/files/skill":()=>up(n),"POST /api/admin/business/orgchart":()=>$p(n),"DELETE /api/admin/business/orgchart":()=>jp(n),"POST /api/admin/business/project":()=>Op(n),"DELETE /api/admin/business/project":()=>Hp(n),"POST /api/admin/business/client":()=>Np(n),"DELETE /api/admin/business/client":()=>Dp(n),"POST /api/admin/business/contact":()=>Bp(n),"DELETE /api/admin/business/contact":()=>qp(n),"POST /api/admin/boards":()=>zp(n),"DELETE /api/admin/boards":()=>Fp(n),"POST /api/admin/boards/columns":()=>Up(n),"DELETE /api/admin/boards/columns":()=>Wp(n),"POST /api/admin/notifications":()=>Yp(n),"POST /api/admin/wiki/curator":()=>Vp(n),"POST /api/admin/screen":()=>Zp(n),"POST /api/admin/wiki-notes":()=>Qp(n),"GET /api/admin/wiki-notes/list":()=>We("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>eu(n),"POST /api/admin/mesh/health":()=>Jp(n),"GET /api/admin/projects":()=>We("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>he("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>he("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>he("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>he("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>he("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>he("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>he("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>he("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){qa(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();qa(e,200,i)}catch(n){qa(e,400,{error:n.message||"admin op failed"})}}function qa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Kc(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 Jc(t){let e=Ge(process.cwd(),t);if(!Vt(e))return[];let a=[];for(let n of Xc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(hs(Ge(e,n.name),"utf-8")))}catch{}return a}function Fa(){let t=Ge(process.cwd(),"agentx.json");return Vt(t)?JSON.parse(hs(t,"utf-8")):null}function Vc(){let t=Fa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([h,u])=>({id:h,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",wikiAbsorb:u.wiki?.absorb?.enabled!==!1,integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(f=>{let b=f.credentials||{},v={};for(let[E,x]of Object.entries(b))typeof x=="string"&&/^[A-Z][A-Z0-9_]*$/.test(x)?v[E]=process.env[x]?"set":"unset":typeof x=="string"&&(v[E]="literal");return{kind:f.kind,label:f.label,enabled:f.enabled!==!1,credentials:b,credStatus:v,metadata:f.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([h,u])=>({id:h,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(([h,u])=>({id:h,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(h=>({id:h.id,source:h.source,agentId:h.agentId,secretEnv:h.secretEnv||"",description:h.description||"",enabled:h.enabled!==!1,triggers:h.triggers&&typeof h.triggers=="object"?h.triggers:{},defaultWorkflow:h.defaultWorkflow||""})):[],c={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(h=>({url:h.url,name:h.name,hasToken:!!h.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},g={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||{},y={longTaskThreshold:_.longTaskThreshold??30,destination:_.destination||null,on:{taskComplete:_.on?.taskComplete!==!1,taskError:_.on?.taskError!==!1,taskQueued:!!_.on?.taskQueued},local:nr(_.local),ntfy:ro(t.channels?.ntfy)},S=[];try{S=Jc(".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,f)=>u.id.localeCompare(f.id))}catch{}let T=(Array.isArray(t.boards)?t.boards:[]).map(h=>({id:h.id,name:h.name,source:h.source||{type:"gitlab",projects:[]},primaryToolLabel:h.primaryToolLabel||"",timeRangeDays:h.timeRangeDays??30,closedWindowDays:h.closedWindowDays??30,columns:Array.isArray(h.columns)?h.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Zr(t),whatsappTriage:ds(t),crons:l,webhooks:d,mesh:c,daemonUrl:p,nodeName:t.node?.name,business:g,boards:T,notifications:y,screen:$r(t.screen),wikiNotes:ao(t.wikiNotes),actions:S,wikiCurator:ks(t)}}function Yc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=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 Qc(){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 Zc(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 ep(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 tp(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 c=X();r=c.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=c.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(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function ap(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=ws(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=Ge(process.cwd(),"agents",e),{summary:l}=C(c=>{if(c.agents=c.agents||{},c.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)),c.agents[e]=p,`added agent "${e}"`}),d=Ge(i,"CLAUDE.md");if(!Vt(d))try{Wc(i,{recursive:!0}),gs(d,`# ${a}
|
|
5640
5640
|
|
|
5641
5641
|
${s||"You are "+a+"."}
|
|
5642
|
-
`)}catch{}return{summary:l}}function tp(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=vs(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),typeof a.wikiAbsorb=="boolean"&&Ot(o,a.wikiAbsorb),`updated agent "${e}"`});return{summary:n}}function ap(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 np(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 rp(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 We(t){let{url:e,headers:a}=Ua(),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 he(t,e){let{url:a,headers:n}=Ua(),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 op(t,e){try{let{url:a,headers:n}=Ua(),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 Ua(){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 at(t){let a=Fa()?.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 qa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function sp(t){let e=qa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Be(at(e));return{agentId:e,...a}}function ip(t){let e=qa(t,"agent").trim(),a=qa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ct(at(e),a)}function lp(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(at(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function cp(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(at(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function dp(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(at(e),a);return{summary:`removed skill "${a}"`,...n}}function pp(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 up(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 mp(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 bs=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function fp(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(!bs.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 hp(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"&&bs.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 gp(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 xp(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 bp(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 vp(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 yp(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 wp(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 kp(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 _p(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 Sp(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 Ep(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 Tp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-PVXLF2VJ.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 Ap(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 Cp(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 Ip(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 Mp(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 Lp(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=Ge(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Vt(n))try{Ud(n,r)}catch{}fs(n,JSON.stringify(a,null,2)+`
|
|
5643
|
-
`,"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 vs(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Rp(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 Pp(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 $p(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 jp(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 Op(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 Np(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 Dp(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 Hp(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 Bp(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 zp(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 qp(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 Fp(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 Up(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 Wp(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 Gp(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 Xp(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}}function ys(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function Kp(t){let{summary:e}=C(a=>{if(a.wiki=a.wiki||{},a.wiki.curator=a.wiki.curator||{},t&&"enabled"in t&&(a.wiki.curator.enabled=!!t.enabled),t&&"agent"in t){let r=String(t.agent||"").trim();if(!r)delete a.wiki.curator.agent;else if(a.agents?.[r])a.wiki.curator.agent=r;else throw new Error(`no agent "${r}"`)}let n=ys(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function Jp(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=rr(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=oo(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 Vp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let e={};"enabled"in t&&(e.enabled=!!t.enabled),"inbox"in t&&(e.inbox=String(t.inbox??"")),"crons"in t&&(e.crons=Array.isArray(t.crons)?t.crons.map(String):String(t.crons??"").split(",")),"absorbAgent"in t&&(e.absorbAgent=String(t.absorbAgent??"")),"maxNotesPerRun"in t&&(e.maxNotesPerRun=Number(t.maxNotesPerRun)),"maxDeferrals"in t&&(e.maxDeferrals=Number(t.maxDeferrals));let{summary:a}=C(n=>no(n,e));return{summary:a}}async function Yp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=jr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Qp(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}}ft();import{resolve as tu}from"path";function ws(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5642
|
+
`)}catch{}return{summary:l}}function np(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=ws(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),typeof a.wikiAbsorb=="boolean"&&Ot(o,a.wikiAbsorb),`updated agent "${e}"`});return{summary:n}}function rp(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 op(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 sp(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 We(t){let{url:e,headers:a}=Ua(),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 he(t,e){let{url:a,headers:n}=Ua(),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 ip(t,e){try{let{url:a,headers:n}=Ua(),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 Ua(){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 at(t){let a=Fa()?.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 za(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function lp(t){let e=za(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Be(at(e));return{agentId:e,...a}}function dp(t){let e=za(t,"agent").trim(),a=za(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ct(at(e),a)}function cp(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(at(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function pp(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(at(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function up(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(at(e),a);return{summary:`removed skill "${a}"`,...n}}function mp(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 d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.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,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);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(d=>d.kind===a&&d.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 fp(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(d=>d.kind===a&&d.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 hp(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 d=(i.integrations||[]).find(c=>c.kind===a&&c.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var ys=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function gp(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(!ys.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(c=>c.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function xp(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"&&ys.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 bp(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 vp(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 yp(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 wp(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 kp(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 _p(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 Sp(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 Ep(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 Tp(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 Ap(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 Cp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-WOH2O3EP.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 Ip(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 Mp(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 Lp(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 Rp(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 Pp(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=Ge(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Vt(n))try{Gc(n,r)}catch{}gs(n,JSON.stringify(a,null,2)+`
|
|
5643
|
+
`,"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 ws(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(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.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 jp(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 Op(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 Np(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 Dp(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 Hp(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 Bp(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 qp(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 zp(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 d=l.boards.findIndex(p=>p.id===e),c={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(c.primaryToolLabel=r),d>=0){let p=l.boards[d];return l.boards[d]={...p,...c,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(c),`board "${e}" added`});return{summary:i}}async function Fp(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 Up(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 d={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");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let c=l.columns.findIndex(p=>p.id===a);return c>=0?(l.columns[c]={...l.columns[c],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Wp(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 Gp(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 Xp(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 Kp(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 Jp(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}}function ks(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function Vp(t){let{summary:e}=C(a=>{if(a.wiki=a.wiki||{},a.wiki.curator=a.wiki.curator||{},t&&"enabled"in t&&(a.wiki.curator.enabled=!!t.enabled),t&&"agent"in t){let r=String(t.agent||"").trim();if(!r)delete a.wiki.curator.agent;else if(a.agents?.[r])a.wiki.curator.agent=r;else throw new Error(`no agent "${r}"`)}let n=ks(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function Yp(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=rr(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=oo(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 e={};"enabled"in t&&(e.enabled=!!t.enabled),"inbox"in t&&(e.inbox=String(t.inbox??"")),"crons"in t&&(e.crons=Array.isArray(t.crons)?t.crons.map(String):String(t.crons??"").split(",")),"absorbAgent"in t&&(e.absorbAgent=String(t.absorbAgent??"")),"maxNotesPerRun"in t&&(e.maxNotesPerRun=Number(t.maxNotesPerRun)),"maxDeferrals"in t&&(e.maxDeferrals=Number(t.maxDeferrals));let{summary:a}=C(n=>no(n,e));return{summary:a}}async function Zp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=jr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function eu(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}}ft();import{resolve as nu}from"path";function _s(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5644
5644
|
|
|
5645
5645
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
5646
5646
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -5695,7 +5695,7 @@ ${s||"You are "+a+"."}
|
|
|
5695
5695
|
<h2>Recent classifications</h2>
|
|
5696
5696
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
5697
5697
|
<div id="recent"></div>
|
|
5698
|
-
</section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5698
|
+
</section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:tu,scripts:`${e}<script>${au}</script>`})}var tu=`
|
|
5699
5699
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
5700
5700
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
5701
5701
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5799,7 +5799,7 @@ details {
|
|
|
5799
5799
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5800
5800
|
}
|
|
5801
5801
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5802
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
5802
|
+
details[open] summary { margin-bottom: 8px; }`,au=`
|
|
5803
5803
|
const $ = (id) => document.getElementById(id);
|
|
5804
5804
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5805
5805
|
|
|
@@ -6019,7 +6019,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
6019
6019
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
6020
6020
|
|
|
6021
6021
|
refresh();
|
|
6022
|
-
`;function
|
|
6022
|
+
`;function Es(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_s({peers:a,localToken:n}))}async function Ts(t,e,a){try{let n=t.method==="GET"?void 0:await uu(t),r=ru(),o={"GET /api/admin/graph/state":()=>ou(r),"POST /api/admin/graph/classifications/approve":()=>su(r,n),"POST /api/admin/graph/classifications/reject":()=>iu(r,n),"POST /api/admin/graph/nodes":()=>lu(r,n),"PATCH /api/admin/graph/nodes":()=>du(r,n),"DELETE /api/admin/graph/nodes":()=>cu(r,n),"PUT /api/admin/graph/schema":()=>pu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Wa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Wa(e,200,l)}catch(n){Wa(e,400,{error:n?.message||"graph op failed"})}}function ru(){let t=X(),e=nu(process.cwd(),t.graph.baseDir);return new zn({baseDir:e})}function ou(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 su(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=As(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=Ga(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function iu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=As(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function As(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 lu(t,e){let a=Ss(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Ss(String(e.parentId)):null,o=Ga({[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 du(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ga({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function cu(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function pu(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 Ga(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 Ss(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Wa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function uu(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 Cs=`
|
|
6023
6023
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
6024
6024
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
6025
6025
|
<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>
|
|
@@ -6041,7 +6041,7 @@ refresh();
|
|
|
6041
6041
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
6042
6042
|
</form>
|
|
6043
6043
|
</details>
|
|
6044
|
-
</section>`,
|
|
6044
|
+
</section>`,Is=`
|
|
6045
6045
|
.apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
|
|
6046
6046
|
.apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
|
|
6047
6047
|
.apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
|
|
@@ -6069,7 +6069,7 @@ refresh();
|
|
|
6069
6069
|
.apv__plan .is-done { color: var(--ax-ok, inherit); }
|
|
6070
6070
|
.apv__plan .is-blocked { color: var(--ax-err); }
|
|
6071
6071
|
.apv__plan small { display: block; color: var(--ax-muted); }
|
|
6072
|
-
`,
|
|
6072
|
+
`,Ms=`
|
|
6073
6073
|
(function(){
|
|
6074
6074
|
var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
|
|
6075
6075
|
function $(id){ return document.getElementById(id); }
|
|
@@ -6234,7 +6234,7 @@ function busy(){
|
|
|
6234
6234
|
}
|
|
6235
6235
|
setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
|
|
6236
6236
|
})();
|
|
6237
|
-
`;function
|
|
6237
|
+
`;function Ls(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
6238
6238
|
<header class="apv__head">
|
|
6239
6239
|
<div>
|
|
6240
6240
|
<h1>Approvals</h1>
|
|
@@ -6256,7 +6256,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
|
|
|
6256
6256
|
<ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
|
|
6257
6257
|
<p id="apv-snoozed" class="apv__foot"></p>
|
|
6258
6258
|
|
|
6259
|
-
${
|
|
6259
|
+
${Cs}
|
|
6260
6260
|
|
|
6261
6261
|
<details class="apv__settings" id="apv-settings">
|
|
6262
6262
|
<summary>Settings: expiry, later, daily digest</summary>
|
|
@@ -6271,7 +6271,7 @@ ${Ts}
|
|
|
6271
6271
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
6272
6272
|
</form>
|
|
6273
6273
|
</details>
|
|
6274
|
-
</div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
6274
|
+
</div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:mu+Is,scripts:`${e}<script>${fu}</script><script>${Ms}</script>`})}var mu=`
|
|
6275
6275
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
6276
6276
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
6277
6277
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -6328,7 +6328,7 @@ ${Ts}
|
|
|
6328
6328
|
@media (max-width: 560px) {
|
|
6329
6329
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
6330
6330
|
}
|
|
6331
|
-
`,
|
|
6331
|
+
`,fu=`
|
|
6332
6332
|
(function(){
|
|
6333
6333
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
6334
6334
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -6552,7 +6552,7 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
6552
6552
|
load();
|
|
6553
6553
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within, .apv__item[data-touched]')) load(); }, 60000);
|
|
6554
6554
|
})();
|
|
6555
|
-
`;import{existsSync as
|
|
6555
|
+
`;import{existsSync as hu,readFileSync as gu}from"fs";var Me="/api/admin/approvals/requests";function Rs(t){let e=Kn(t);if(!hu(e))return[];try{let a=JSON.parse(gu(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 Yt=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Ps(t,e,a,n){try{return await xu(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function xu(t,e,a,n){if(t==="GET"&&e===Me){let o=St(n);return{status:200,body:{items:o?o.listOpen().map(s=>gr(s,o,mr(n))):[],agents:Rs(n.configPath),settings:_t(n.configPath)}}}let r=e===`${Me}/reply`?"reply":e===`${Me}/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=St(n),d=l?.get(o);if(!l||!d||d.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=r==="reply"?d.agentId:typeof a.agentId=="string"?a.agentId:"",p=Rs(n.configPath).find(g=>g.id===c);if(r==="handoff"&&!p)return{status:400,body:{error:`"${c}" is not an agent on this node`}};if(!_t(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,c,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=p?.name??c;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===`${Me}/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=St(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=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",d,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===`${Me}/settings`){let o={},s=d=>{let c=a[d];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${d} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=Yt(a.from),o.channels=Yt(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i={};if(typeof a.plansEnabled=="boolean"&&(i.enabled=a.plansEnabled),i.stallMinutes=s("stallMinutes"),a.maxNudges!==void 0){if(typeof a.maxNudges!="number"||!Number.isInteger(a.maxNudges)||a.maxNudges<0)throw new Error("maxNudges must be a whole number, 0 or more");i.maxNudges=a.maxNudges}i.approveKinds=Yt(a.approveKinds),i.disabledAgents=Yt(a.plansOffFor),Object.values(i).some(d=>d!==void 0)&&(o.plans=i);let l=await ur(o,{configPath:n.configPath,reload:n.reload});return l.success?{status:200,body:{ok:!0,settings:_t(n.configPath)}}:{status:400,body:{error:l.error}}}return{status:404,body:{error:"Not found"}}}var bu=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Qt(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 vu(t){let e=t.choice;return{...typeof e=="number"||typeof e=="string"&&e.trim()?{choice:typeof e=="string"?e.trim():e}:{},...typeof t.text=="string"&&t.text.trim()?{text:t.text}:{}}}function $s(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Ls({peers:e,localToken:a}))}async function js(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Me)){let i=await Ps(o,a,o==="POST"?await Qt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=Et(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:Ae(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Qt(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!bu.includes(d))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let c=Ae(s.configPath),p=await Tt(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:c.laterHours,by:"operator (dashboard)",...vu(i)});return p.ok?(te(e,200,{ok:!0,message:p.message}),!0):(te(e,409,{error:p.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Qt(t),l=xr(s,typeof i.key=="string"?i.key:"",!!Ae(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Qt(t),l={},d=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=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("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=Wr(p);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let c=await Gr(l,{configPath:s.configPath,reload:s.reload});return c.success?(te(e,200,{ok:!0,settings:Ae(s.configPath)}),!0):(te(e,400,{error:c.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}ya();function Os(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=pe({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."})+`
|
|
6556
6556
|
<div class="pp">
|
|
6557
6557
|
<div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
|
|
6558
6558
|
<section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
|
|
@@ -6565,7 +6565,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6565
6565
|
</ol>
|
|
6566
6566
|
</section>
|
|
6567
6567
|
<ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
|
|
6568
|
-
</div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:
|
|
6568
|
+
</div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:yu,scripts:`${e}<script>${wu}</script>`})}var yu=`
|
|
6569
6569
|
.pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
|
|
6570
6570
|
.pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
|
|
6571
6571
|
.pp-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -6606,7 +6606,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6606
6606
|
.pp-text { overflow-wrap: anywhere; }
|
|
6607
6607
|
.pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
6608
6608
|
@media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
|
|
6609
|
-
`,
|
|
6609
|
+
`,wu=`
|
|
6610
6610
|
(function () {
|
|
6611
6611
|
var list = document.getElementById('pp-list');
|
|
6612
6612
|
var msg = document.getElementById('pp-msg');
|
|
@@ -6744,7 +6744,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6744
6744
|
load();
|
|
6745
6745
|
setInterval(load, 30000);
|
|
6746
6746
|
})();
|
|
6747
|
-
`;var Xa="/api/admin/people";function
|
|
6747
|
+
`;var Xa="/api/admin/people";function ku(t,e){let a=Vr(t,e);return a?{...e,answer:a}:e}function _u(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function ge(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function Su(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&_u(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:mt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Eu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Ns(t,e,a,n){if(a!=="/people"&&a!==Xa&&!a.startsWith(`${Xa}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(ge(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Os({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return ge(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=d=>n.members.devices(d).map(c=>ku(n.root,c)),s=()=>Su(n.people(),o());if(r==="GET"&&a===Xa){let d=s();return ge(e,200,{people:d,paired:d.reduce((c,p)=>c+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 d=s().find(g=>g.id===i[1]);if(!d)return ge(e,404,{error:`no person "${i[1]}"`}),!0;let c=n.db(),p=[],m=[];try{c&&(p=Xr(c,d.id))}catch{}try{c&&(m=jt(c,d.id,20))}catch{}return ge(e,200,{person:d,devices:o(d.id).sort(Eu),requests:p,runs:m,database:!!c}),!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[,d,c]=l,p=n.members.byToken(c);if(!p||p.personId!==d)return ge(e,404,{error:"no such machine for this person"}),!0;if(p.state==="removed")return ge(e,409,{error:"this machine's access has already ended"}),!0;let m=Qr({tokens:n.tokens??new G,members:n.members,now:n.now},c,"removed by the owner (dashboard)");return ge(e,200,{ok:!0,device:m}),!0}return ge(e,404,{error:"not found"}),!0}import{resolve as Mu}from"path";import{existsSync as Lu}from"fs";import Ru from"better-sqlite3";var Ds=new WeakSet;function Tu(t,e,a={}){if(Ds.has(t))return;Ds.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 d=i[l].bind(i);i[l]=(...c)=>{let p=r();try{return d(...c)}finally{let m=r()-p;m>=n&&e({sql:s,ms:m})}}}return i}}function Au(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ke(t,e){Tu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Au(a)}`))}function Hs(t={}){let e=`<div class="ax-obs">
|
|
6748
6748
|
<header class="ax-obs__head">
|
|
6749
6749
|
<h1>Health</h1>
|
|
6750
6750
|
<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>
|
|
@@ -6866,7 +6866,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6866
6866
|
</div>
|
|
6867
6867
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
6868
6868
|
</section>
|
|
6869
|
-
</div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6869
|
+
</div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Cu,scripts:`<script>${Iu}</script>`})}var Cu=`
|
|
6870
6870
|
.ax-obs { padding: 16px 24px; }
|
|
6871
6871
|
.ax-obs__head { margin-bottom: 16px; }
|
|
6872
6872
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -6983,7 +6983,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6983
6983
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
6984
6984
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
6985
6985
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
6986
|
-
`,
|
|
6986
|
+
`,Iu=`
|
|
6987
6987
|
(function(){
|
|
6988
6988
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
6989
6989
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -7367,23 +7367,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7367
7367
|
|
|
7368
7368
|
load(current);
|
|
7369
7369
|
})();
|
|
7370
|
-
`;var
|
|
7370
|
+
`;var zs={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 Fs(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ka(t){let e=zs[Fs(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 Pu(){let t=Mu(process.cwd(),".agentx/db.sqlite");if(!Lu(t))return null;try{let e=new Ru(t,{readonly:!0,fileMustExist:!0});return ke(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Us(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hs({peers:a}))}function $u(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 xe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Ws(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Pu();if(!r)return xe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=$u(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
|
|
7371
7371
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
7372
7372
|
FROM route_traces
|
|
7373
7373
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
7374
7374
|
ORDER BY at DESC LIMIT @limit
|
|
7375
|
-
`,
|
|
7375
|
+
`,c=r.db.prepare(d).all(l);return xe(e,200,{rows:c}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
|
|
7376
7376
|
SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
|
|
7377
7377
|
FROM rotations
|
|
7378
7378
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
7379
7379
|
ORDER BY rotated_at DESC LIMIT @limit
|
|
7380
|
-
`,
|
|
7380
|
+
`,c=r.db.prepare(d).all(l);return xe(e,200,{rows:c}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
|
|
7381
7381
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
7382
7382
|
FROM task_history
|
|
7383
7383
|
WHERE ${i.join(" AND ")}
|
|
7384
7384
|
ORDER BY started_at DESC LIMIT @limit
|
|
7385
|
-
`,p=r.db.prepare(
|
|
7386
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
7385
|
+
`,p=r.db.prepare(d).all(l).map(m=>({...m,plain:Gs(m.error)}));return xe(e,200,{rows:p}),!0}if(n==="summary"||n==="overview")return xe(e,200,ju(r.db)),!0;if(n==="activity")return xe(e,200,Ou(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Bs(i.searchParams.get("range"));return xe(e,200,qs(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Bs(i.searchParams.get("range")),d=qs(r.db,l),c=Nu(d.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(c),!0}return xe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return xe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Gs(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(`
|
|
7386
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function ju(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,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,c=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=x=>c.length?c[Math.min(c.length-1,Math.floor(c.length*x))].duration_ms:0,m=p(.5),g=p(.95),y=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((x,A)=>x+Ka(A),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((x,A)=>x+Ka(A),0),T=t.prepare(`
|
|
7387
7387
|
SELECT agent_id,
|
|
7388
7388
|
COUNT(*) AS tasks,
|
|
7389
7389
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -7401,12 +7401,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7401
7401
|
WHERE started_at >= ?
|
|
7402
7402
|
GROUP BY channel
|
|
7403
7403
|
ORDER BY tasks DESC
|
|
7404
|
-
`).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(x=>x.agent_id),f=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(x=>x.agent_id)),
|
|
7404
|
+
`).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(x=>x.agent_id),f=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(x=>x.agent_id)),b=u.filter(x=>!f.has(x)),E=t.prepare(`
|
|
7405
7405
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
7406
7406
|
FROM task_history
|
|
7407
7407
|
WHERE status='error' AND started_at >= ?
|
|
7408
7408
|
ORDER BY started_at DESC LIMIT 5
|
|
7409
|
-
`).all(o).map(x=>({...x,plain:
|
|
7409
|
+
`).all(o).map(x=>({...x,plain:Gs(x.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:m,p95DurationMs:g,spendToday:y,spendDelta:y-S,idleAgentCount:b.length},perAgent:T,perChannel:h,idleAgents:b,recentErrors:E}}function Ou(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(`
|
|
7410
7410
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
7411
7411
|
COUNT(*) AS tasks,
|
|
7412
7412
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -7433,7 +7433,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7433
7433
|
WHERE started_at >= @since
|
|
7434
7434
|
GROUP BY agent_id
|
|
7435
7435
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
7436
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
7436
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Bs(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 qs(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
7437
7437
|
SELECT day, agent_id, model,
|
|
7438
7438
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
7439
7439
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -7441,20 +7441,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7441
7441
|
FROM usage_daily
|
|
7442
7442
|
${a}
|
|
7443
7443
|
ORDER BY day
|
|
7444
|
-
`).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,
|
|
7444
|
+
`).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,d=0,c=0,p=0,m=0,g=0,_=0,y=0,S=0,T={},h={};for(let k of n){let L=Ka(k),j=Fs(k.model),$=zs[j],O=(k.tier2_input_tokens||0)/1e6*$.input*.5+(k.tier2_output_tokens||0)/1e6*$.output*.5+(k.tier2_cache_read_tokens||0)/1e6*$.cacheRead*.5+(k.tier2_cache_create_tokens||0)/1e6*$.cacheCreate*.5,W=(k.input_tokens||0)+(k.tier2_input_tokens||0),de=(k.output_tokens||0)+(k.tier2_output_tokens||0),Q=(k.cache_read_tokens||0)+(k.tier2_cache_read_tokens||0),oe=(k.cache_create_tokens||0)+(k.tier2_cache_create_tokens||0);p+=L,k.day>=s&&(c+=L,_+=k.tasks||0),k.day>=i&&k.day<s&&(S+=L,y+=k.tasks||0),k.day===r&&(l+=L),k.day===o&&(d+=L),k.day===r&&(m+=O),k.day>=s&&(g+=O);let Z=T[k.day]||(T[k.day]={date:k.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=k.tasks||0,Z.input+=W,Z.output+=de,Z.cacheRead+=Q,Z.cacheCreate+=oe,Z.cost+=L,Z.tier2+=O;let F=Z.agents[k.agent_id]||(Z.agents[k.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:k.model});F.tasks+=k.tasks||0,F.cost+=L,F.tier2+=O,F.input+=W,F.output+=de,F.cacheRead+=Q,F.cacheCreate+=oe,k.model&&(F.model=k.model);let N=h[k.agent_id]||(h[k.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:k.model});N.tasks+=k.tasks||0,N.cost+=L,N.tier2+=O,N.input+=W,N.output+=de,N.cacheRead+=Q,N.cacheCreate+=oe,k.model&&(N.model=k.model)}let u=Object.values(T).sort((k,L)=>k.date<L.date?-1:1),f=0,b=0,v=0,E=0,x=0,A=0;for(let k of u)f+=k.tasks,b+=k.input,v+=k.output,E+=k.cacheRead,x+=k.cacheCreate,A+=k.cost;let R=Object.entries(h).map(([k,L])=>({agent_id:k,...L,tokens:L.input+L.output+L.cacheRead+L.cacheCreate})).sort((k,L)=>L.cost-k.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:c,spend30d:p,tier2Today:m,tier2_7d:g,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:f,tokensRange:b+v+E+x,cacheHitRange:E+b>0?E/(E+b):0,costPerTaskRange:f>0?A/f:0,spendDeltaWoW:S>0?(c-S)/S:0,tasksDeltaWoW:y>0?(_-y)/y:0},days:u,perAgent:R}}function Nu(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+`
|
|
7445
7445
|
`+a.join(`
|
|
7446
7446
|
`)+`
|
|
7447
|
-
`}import{resolve as
|
|
7447
|
+
`}import{resolve as Du}from"path";import{existsSync as Hu}from"fs";import Bu from"better-sqlite3";function qu(){let t=Du(process.cwd(),".agentx/intent/ledger.sqlite");if(!Hu(t))return null;try{let e=new Bu(t,{readonly:!0,fileMustExist:!0});return ke(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Xs>6e4&&(Xs=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Xs=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function zu(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 Ks(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=qu();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=zu(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),c=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let p=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",g=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,y=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,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),h=r.db.prepare(`
|
|
7448
7448
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
7449
7449
|
LEFT JOIN intent_resolutions r
|
|
7450
7450
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
7451
7451
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
7452
|
-
`).get().n;return Le(e,200,{since:s??null,eventsBySource:g,totalDecisions:_,decisionsByOutcome:
|
|
7452
|
+
`).get().n;return Le(e,200,{since:s??null,eventsBySource:g,totalDecisions:_,decisionsByOutcome:y,totalDivergences:S,divergencesBySource:T,inFlight:h}),!0}if(n==="events"){let p=[],m={limit:c};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 g=`
|
|
7453
7453
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
7454
7454
|
FROM intent_events
|
|
7455
7455
|
${p.length?"WHERE "+p.join(" AND "):""}
|
|
7456
7456
|
ORDER BY ts DESC LIMIT @limit
|
|
7457
|
-
`;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="divergences"){let p=[],m={limit:
|
|
7457
|
+
`;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="divergences"){let p=[],m={limit:c};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i);let g=`
|
|
7458
7458
|
SELECT ts, source, decided_by,
|
|
7459
7459
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
7460
7460
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
@@ -7462,7 +7462,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7462
7462
|
FROM intent_divergences
|
|
7463
7463
|
${p.length?"WHERE "+p.join(" AND "):""}
|
|
7464
7464
|
ORDER BY ts DESC LIMIT @limit
|
|
7465
|
-
`;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="active"){let p=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:
|
|
7465
|
+
`;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="active"){let p=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:c};i&&(p.push("e.source = @source"),m.source=i);let g=`
|
|
7466
7466
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
7467
7467
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
7468
7468
|
FROM intent_decisions d
|
|
@@ -7471,7 +7471,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7471
7471
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
7472
7472
|
WHERE ${p.join(" AND ")}
|
|
7473
7473
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
7474
|
-
`;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}return Le(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Le(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function
|
|
7474
|
+
`;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}return Le(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Le(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Js(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
7475
7475
|
<header class="ax-led__head">
|
|
7476
7476
|
<h1>Intent ledger</h1>
|
|
7477
7477
|
<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>
|
|
@@ -7676,7 +7676,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7676
7676
|
}
|
|
7677
7677
|
load();
|
|
7678
7678
|
})();
|
|
7679
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7679
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Vs(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
7680
7680
|
<header class="ax-cost__head">
|
|
7681
7681
|
<div>
|
|
7682
7682
|
<h1>Cost</h1>
|
|
@@ -8249,7 +8249,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8249
8249
|
load();
|
|
8250
8250
|
setInterval(load, 30000);
|
|
8251
8251
|
})();
|
|
8252
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
8252
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Ys(t={}){let e=`<div class="ax-pj__root">
|
|
8253
8253
|
<aside class="ax-pj__list">
|
|
8254
8254
|
<header>
|
|
8255
8255
|
<h2>Projects</h2>
|
|
@@ -8276,7 +8276,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8276
8276
|
</header>
|
|
8277
8277
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
8278
8278
|
</section>
|
|
8279
|
-
</div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
8279
|
+
</div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Fu,scripts:`<script>${Uu}</script>`})}var Fu=`
|
|
8280
8280
|
.ax-pj__root {
|
|
8281
8281
|
display: grid;
|
|
8282
8282
|
grid-template-columns: 360px 1fr;
|
|
@@ -8463,7 +8463,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8463
8463
|
}
|
|
8464
8464
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
8465
8465
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
8466
|
-
`,
|
|
8466
|
+
`,Uu=`
|
|
8467
8467
|
(function(){
|
|
8468
8468
|
const $ = (sel) => document.querySelector(sel);
|
|
8469
8469
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -9113,9 +9113,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
9113
9113
|
load();
|
|
9114
9114
|
});
|
|
9115
9115
|
})();
|
|
9116
|
-
`;import{resolve as Za,join as rm}from"path";import{existsSync as en,readdirSync as om,readFileSync as sm}from"fs";import im from"better-sqlite3";var Ys=String.raw`[\w.-]+(?:/[\w.-]+)+`,Fu=new RegExp(`^(?:chat:)?(${Ys}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Uu=new RegExp(`^\\[(?:GitLab|GitHub) (${Ys}) `);function Vs(t){if(!t)return null;let e=t.match(Fu);return e?e[1]:null}function Ja(t){if(!t)return null;let e=t.trimStart().match(Uu);return e?e[1]:null}function Zt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Vs(typeof n?.chatId=="string"?n.chatId:null)??Vs(e)??Ja(a)}function Wu(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function ea(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Gu=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Xu=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ku=t=>/^issue/i.test(t)?"issue":"mr";function Ju(t){let e=t.subject.match(Gu)??t.inputPreview.trimStart().match(Xu);return e?{kind:Ku(e[1]),n:Number(e[2])}:null}function Vu(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 Qs(t){if(!Wu(t.projectId))return[];let e=Ju(t);return e?[e]:Vu(t.inputPreview)}var Yu=6e4,Qu=5*6e4,Zu=40,Zs=6,ei=new Map;function ti(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 Qs(n)){let s=ea(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 ai(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ea(s.project,s.ref),l=ei.get(i);l&&n-l.at<(s.github?Qu:Yu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Zs)await Promise.all(o.slice(s,s+Zs).map(async i=>{let l=ea(i.project,i.ref),c=null;try{c=i.github?await tm(i,e,a):await em(i,e,a)}catch{}ei.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function ni(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 em(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 ni(`${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 tm(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 ni(`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}$n();var Va=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function ri(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=pt(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=Va(o.from,80);if(s){a.callback={from:s,status:Va(o.status,20)??"done"};let i=Va(o.peer,80);i&&(a.callback.peer=i)}}return a}$n();ya();var oi={kind:"agentx",id:"agentx",name:"AgentX"},Ya={kind:"person",id:"unknown",name:"Unknown"},am=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),si=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Re=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function nm(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=Re(o?.id)??(e==="whatsapp"?Re(n?.from):void 0),i=Re(o?.username)??Re(o?.login);return s||i?{id:s,username:i,name:Re(o?.name)}:null}function ii(t){let e=s=>({kind:"person",id:`person:${s}`,name:Hn(t.people,s)}),a=(s,i)=>i||am.has(s)?oi:{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=Re(n.person)??zn(t.people,s)?.id;if(i)return e(i);let l=pt(s),c=l?.channel??t.channel;if(Pn(s)==="human")return si(s?.senderUsername)?a(c,!1):Ya;let d=!!Re(n.senderAgentId)||ga(l?l.sender:s?.sender);return c==="desktop"&&!d?Ya:a(c,d)}let r=nm(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Bn(t.people,t.channel,r);return o?e(o.id):ga(r.name)?oi:Rn.has(t.channel)&&!si(r.username)?Ya:a(t.channel,!1)}function tn(){let t=Za(process.cwd(),".agentx/intent/ledger.sqlite");if(!en(t))return null;try{let e=new im(t,{readonly:!0,fileMustExist:!0});return ke(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-li>6e4&&(li=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var li=0;function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function lm(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Pe)return s}return"workflow"}return t}function pi(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 cm(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 ui(t,e,a){return tr(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 dm(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&&!Qa(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Qa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:um(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&&!Qa(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",p=ci(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:ci(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 pm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function um(t,e){let a=pm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ci(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Qa(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 mi(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}
|
|
9116
|
+
`;import{resolve as Za,join as sm}from"path";import{existsSync as en,readdirSync as im,readFileSync as lm}from"fs";import dm from"better-sqlite3";var Zs=String.raw`[\w.-]+(?:/[\w.-]+)+`,Wu=new RegExp(`^(?:chat:)?(${Zs}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Gu=new RegExp(`^\\[(?:GitLab|GitHub) (${Zs}) `);function Qs(t){if(!t)return null;let e=t.match(Wu);return e?e[1]:null}function Ja(t){if(!t)return null;let e=t.trimStart().match(Gu);return e?e[1]:null}function Zt(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)??Ja(a)}function Xu(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function ea(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ku=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Ju=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Vu=t=>/^issue/i.test(t)?"issue":"mr";function Yu(t){let e=t.subject.match(Ku)??t.inputPreview.trimStart().match(Ju);return e?{kind:Vu(e[1]),n:Number(e[2])}:null}function Qu(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 ei(t){if(!Xu(t.projectId))return[];let e=Yu(t);return e?[e]:Qu(t.inputPreview)}var Zu=6e4,em=5*6e4,tm=40,ti=6,ai=new Map;function ni(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 ei(n)){let s=ea(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=tm)return[...e.values()]}}return[...e.values()]}async function ri(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ea(s.project,s.ref),l=ai.get(i);l&&n-l.at<(s.github?em:Zu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ti)await Promise.all(o.slice(s,s+ti).map(async i=>{let l=ea(i.project,i.ref),d=null;try{d=i.github?await nm(i,e,a):await am(i,e,a)}catch{}ai.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function oi(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 am(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 oi(`${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 nm(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 oi(`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}$n();var Va=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function si(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=pt(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=Va(o.from,80);if(s){a.callback={from:s,status:Va(o.status,20)??"done"};let i=Va(o.peer,80);i&&(a.callback.peer=i)}}return a}$n();ya();var ii={kind:"agentx",id:"agentx",name:"AgentX"},Ya={kind:"person",id:"unknown",name:"Unknown"},rm=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),li=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Re=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function om(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=Re(o?.id)??(e==="whatsapp"?Re(n?.from):void 0),i=Re(o?.username)??Re(o?.login);return s||i?{id:s,username:i,name:Re(o?.name)}:null}function di(t){let e=s=>({kind:"person",id:`person:${s}`,name:Hn(t.people,s)}),a=(s,i)=>i||rm.has(s)?ii:{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=Re(n.person)??qn(t.people,s)?.id;if(i)return e(i);let l=pt(s),d=l?.channel??t.channel;if(Pn(s)==="human")return li(s?.senderUsername)?a(d,!1):Ya;let c=!!Re(n.senderAgentId)||ga(l?l.sender:s?.sender);return d==="desktop"&&!c?Ya:a(d,c)}let r=om(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Bn(t.people,t.channel,r);return o?e(o.id):ga(r.name)?ii:Rn.has(t.channel)&&!li(r.username)?Ya:a(t.channel,!1)}function tn(){let t=Za(process.cwd(),".agentx/intent/ledger.sqlite");if(!en(t))return null;try{let e=new dm(t,{readonly:!0,fileMustExist:!0});return ke(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ci>6e4&&(ci=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ci=0;function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function cm(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Pe)return s}return"workflow"}return t}function mi(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 pm(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 fi(t,e,a){return tr(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 um(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&&!Qa(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Qa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:fm(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,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!Qa(i||l||"")){let c=typeof n.channel=="string"?n.channel:"",p=pi(c);return{id:d,name:l||i||d,avatar:J(l||i||d),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,d=s.name||s.username;return{id:l,name:d,avatar:J(d),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:pi(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 mm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function fm(t,e){let a=mm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function pi(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Qa(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 hi(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}
|
|
9117
9117
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
9118
|
-
${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
|
|
9118
|
+
${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 hm(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 gi(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
9119
9119
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
9120
9120
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
9121
9121
|
`).all(r),s=new Map,i=new Map;if(o.length>0){let x=o.map(j=>j.id),A=x.map((j,$)=>`@id${$}`).join(","),R=Object.fromEntries(x.map((j,$)=>[`id${$}`,j])),k=t.prepare(`
|
|
@@ -9124,20 +9124,20 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
|
|
|
9124
9124
|
`).all(R);for(let j of k)s.has(j.event_id)||s.set(j.event_id,[]),s.get(j.event_id).push(j);let L=t.prepare(`
|
|
9125
9125
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
9126
9126
|
FROM intent_resolutions WHERE decision_event_id IN (${A})
|
|
9127
|
-
`).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,
|
|
9127
|
+
`).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,d=new Map,c=new Map,p=new Map,m=[],g=e?.business?.projects??[],_=e?.business?.contactMap??[],y=_a(e?.business??{}),S=e?.people??[];for(let x of o){let A=null;try{A=JSON.parse(x.raw_json)}catch{}let R=fi(x.source,A,_),k=hi(x.source,A),L=si(A),j=x.project??Zt(A,x.subject,k),$=null,O=null;R?($=R.client,O=R.project||`${R.client}/_chat`):j&&($=bt(j,g),O=j);let W=cm(x.source,x.intent||"",A),de=Pe[W]||{label:W,color:"#6b7280"};c.has(W)||c.set(W,{id:W,label:de.label,color:de.color});let Q=di({source:x.source,channel:W,raw:A,people:S,channelLabel:N=>Pe[N]?.label??N}),oe="__system",Z,F=um(x.source,x.intent||"",A);if(F){oe=F.id,Z=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(x.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let Yd=`${x.id}|${N.decided_by}`,dt=i.get(Yd),Cn=N.decided_at,In=dt?.resolved_at??null,fa=In===null,Qd=dt?.duration_ms??(fa?n-Cn:0),Zd=fa?"active":dt?.status==="error"||dt?.status==="fail"?"error":"completed",ee,Qe;if($)ee=$,Qe=O;else{let ha=y.get(N.agent_id);ha?(ee=ha,Qe=`${ha}/_${x.source}`):(ee="unmapped",Qe=`unmapped/_${x.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:mi(ee),projects:[]}),d.has(ee)||d.set(ee,new Set),d.get(ee).add(Qe),m.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:Qe,channelId:W,initiatorId:oe,initiatorKind:Z,subject:hm(x.subject),intent:x.intent||"",startedAt:Cn,resolvedAt:In,duration:Qd,active:fa,outcome:Zd,tokens:0,inputPreview:k,system:pm(N.agent_id,e),...L,starter:Q})}}let T=[...l.values()].map(x=>({...x,projects:[...d.get(x.id)||[]].sort()})).sort((x,A)=>x.id.localeCompare(A.id)),h=[],u=new Set;if(e){let x=e.business??{},A=R=>{let k=x.orgChart?.[R]?.role,L=k?x.roles?.[k]?.title:void 0;return typeof L=="string"&&L.trim()?L.trim():void 0};for(let[R,k]of Object.entries(e.agents||{})){let L={id:R,name:k.name||R,tier:k.tier==="claude-code"?"lead":"worker",model:k.model||"",role:k.systemPrompt?k.systemPrompt.split(/[.\n]/)[0].slice(0,60):k.tier||"",title:A(R)};h.push(L),u.add(R)}}for(let x of m)u.has(x.agentId)||(h.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),u.add(x.agentId));h.sort((x,A)=>x.id.localeCompare(A.id));let f=[],b=new Set;for(let[x,A]of Object.entries(Pe))f.push({id:x,label:A.label,color:A.color}),b.add(x);for(let x of c.values())b.has(x.id)||f.push(x);let v=[...p.values()];v.find(x=>x.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let E=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:T,agents:h,channels:f,initiators:v,dispatches:m,forges:{gitlab:typeof E=="string"?E:void 0,github:"https://github.com"}}}function an(t){let e=tn();if(!e)return null;try{return gi(e.db,bi(),t)}finally{e.close()}}function xi(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:c}of t){l.gitlab??=c.forges?.gitlab,l.github??=c.forges?.github,c.now>s&&(s=c.now),c.windowH>i&&(i=c.windowH);for(let p of c.clients){let m=e.get(p.id);if(!m)e.set(p.id,{...p,projects:[...p.projects]});else{let g=Array.from(new Set([...m.projects,...p.projects])).sort();e.set(p.id,{...m,projects:g})}}for(let p of c.agents)a.has(p.id)||a.set(p.id,p);for(let p of c.channels)n.has(p.id)||n.set(p.id,p);for(let p of c.initiators)r.has(p.id)||r.set(p.id,p);for(let p of c.dispatches){let m=gm(p);if(m.clientId!==p.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:mi(m.clientId),projects:[]}),m.projectId!==p.projectId){let g=e.get(m.clientId);g.projects.includes(m.projectId)||e.set(m.clientId,{...g,projects:[...g.projects,m.projectId].sort()})}o.push({...m,nodeId:d,id:`${d}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,c)=>d.id.localeCompare(c.id)),agents:[...a.values()].sort((d,c)=>d.id.localeCompare(c.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,c)=>c.startedAt-d.startedAt)}}function gm(t){if(t.clientId!=="unmapped")return t;let e=Ja(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:bt(e,a)}}async function ta(t){let e=ve?.channels?.gitlab,a=await ri(ni(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ve=null;function bi(){return ve&&{...ve,people:tt(ve.people)}}function vi(t){ve=t}async function yi(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=tn();if(!n)return be(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=wi(parseInt(r.searchParams.get("hours")||"6",10));be(e,200,await ta(gi(n.db,bi(),o)))}catch(r){be(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var xm=5e3;async function nn(t,e,a,n=an){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
|
|
9128
9128
|
|
|
9129
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
9129
|
+
`);let r=new URL(t.url||"/","http://_"),o=wi(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
|
|
9130
9130
|
|
|
9131
|
-
`)}catch{i()}},25e3);try{for(;!s;){try{let
|
|
9131
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let c=await n(o),p=c&&await ta(c);if(s)break;p?(e.write(`event: snapshot
|
|
9132
9132
|
`),e.write(`data: ${JSON.stringify(p)}
|
|
9133
9133
|
|
|
9134
9134
|
`)):e.write(`event: error
|
|
9135
9135
|
data: ${JSON.stringify({error:"ledger not available"})}
|
|
9136
9136
|
|
|
9137
|
-
`)}catch(
|
|
9138
|
-
data: ${JSON.stringify({error:
|
|
9137
|
+
`)}catch(c){e.write(`event: error
|
|
9138
|
+
data: ${JSON.stringify({error:c?.message??String(c)})}
|
|
9139
9139
|
|
|
9140
|
-
`)}let
|
|
9140
|
+
`)}let d=Date.now();for(;!s&&Date.now()-d<xm;)await new Promise(c=>setTimeout(c,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function wi(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function bm(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Za(process.cwd(),".agentx/task-history",t,n);if(!en(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Za(process.cwd(),".agentx/task-history",t,o);return en(s)?ui(s,e,a):null}return ui(r,e,a)}function ui(t,e,a){let n=null,r=1/0;for(let o of im(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(lm(sm(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let c=Date.parse(i);if(!Number.isFinite(c))continue;l=c}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function ki(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 be(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=tn();if(!l)return be(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return be(e,404,{error:"event not found"}),!0;let c=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(!c)return be(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(d.raw_json)}catch{}let g=hi(d.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)||g,y=null,S=null;if(c.agent_id){let v=bm(c.agent_id,c.decided_at);if(v){typeof v.responseText=="string"&&(y=v.responseText);let E=v.transcript;Array.isArray(E)&&(S=E.length)}}let T=ve?.business?.projects??[],h=ve?.business?.contactMap??[],u=_a(ve?.business??{}),f={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},b=fi(d.source,m,h);if(b)f={client:b.client,project:b.project||`${b.client}/_chat`,via:`contactMap (channel=${b.channel??"*"}${b.username?` username=${b.username}`:""}${b.chatId?` chatId=${b.chatId}`:""})`};else if(d.project||Zt(m,d.subject,g)){let v=d.project||Zt(m,d.subject,g);f={client:bt(v,T),project:v,via:d.project?`project namespace prefix (${v})`:`forge path in chat id / message (${v})`}}else if(c.agent_id){let v=u.get(c.agent_id);v&&(f={client:v,project:`${v}/_${d.source}`,via:`orgChart fallback (agent ${c.agent_id} reports up to a PM whose project belongs to ${v})`})}be(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:c.decided_by,agentId:c.agent_id,outcome:c.outcome,reason:c.reason,startedAt:c.decided_at,resolvedAt:p?.resolved_at??null,durationMs:p?.duration_ms??null,input:_,response:y,transcriptLen:S,resolutionStatus:p?.status??null,resultSummary:p?.result_summary??null,attribution:f})}catch(d){be(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as km,readFileSync as _m}from"fs";import{resolve as Si}from"path";ft();function _i(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=vm.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:ym,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>${wm}</script>`})}var vm=`
|
|
9141
9141
|
<!-- Breadcrumb -->
|
|
9142
9142
|
<div class="ax-crumb">
|
|
9143
9143
|
<a href="/admin">Settings</a>
|
|
@@ -9735,7 +9735,7 @@ data: ${JSON.stringify({error:d?.message??String(d)})}
|
|
|
9735
9735
|
</div>
|
|
9736
9736
|
</div>
|
|
9737
9737
|
</div>
|
|
9738
|
-
`,
|
|
9738
|
+
`,ym=`
|
|
9739
9739
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
9740
9740
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
9741
9741
|
* primitives live in components.css.ts. */
|
|
@@ -9854,7 +9854,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
9854
9854
|
|
|
9855
9855
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
9856
9856
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
9857
|
-
`,
|
|
9857
|
+
`,wm=`
|
|
9858
9858
|
const $ = (id) => document.getElementById(id);
|
|
9859
9859
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
9860
9860
|
|
|
@@ -10713,15 +10713,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
10713
10713
|
/* ===== Boot ===== */
|
|
10714
10714
|
initOptsToggles();
|
|
10715
10715
|
loadAgent();
|
|
10716
|
-
`;function
|
|
10717
|
-
`);return
|
|
10718
|
-
`);return
|
|
10716
|
+
`;function Ei(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_i({agentId:a,peers:n,localToken:r}))}async function Ti(t,e,a){try{let n=t.method==="GET"?void 0:await Wm(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){aa(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,p={"GET ":()=>nt(i),"PATCH ":()=>Sm(i,n),"PATCH capability":()=>Am(i,n),"POST mcp":()=>Em(i,n),"DELETE mcp":()=>Tm(i,n),"GET identity":()=>Cm(i),"GET identity/file":()=>Im(i,String(o.path||"")),"PUT identity/file":()=>Mm(i,n),"GET skills":()=>Lm(i),"POST skills":()=>Rm(i,n),"DELETE skills":()=>Pm(i,n),"GET skills/tree":()=>$m(i,String(o.slug||"")),"GET skills/file":()=>jm(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Om(i,n),"GET skills/deps":()=>Nm(i,String(o.slug||"")),"POST skills/install":()=>Dm(i,n,t),"POST skills/deps":()=>Hm(i,n,t),"GET channels":()=>Bm(i),"GET activity":()=>qm(i,t),"GET handovers":()=>zm(i),"POST handovers":()=>Fm(i,n),"DELETE handovers":()=>Um(n)}[d];if(!p){aa(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let m=await p();aa(e,200,m)}catch(n){aa(e,400,{error:n?.message||"agent op failed"})}}function Ai(){let t=Si(process.cwd(),"agentx.json");return km(t)?JSON.parse(_m(t,"utf-8")):null}function V(t){let e=Ai();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 nt(t){let{def:e,cfg:a}=V(t),n=e.workspace?Be(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",wikiAbsorb:e.wiki?.absorb?.enabled!==!1,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 Sm(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},typeof e?.wikiAbsorb=="boolean"&&(Ot(r.agents[t],e.wikiAbsorb),a.wikiAbsorb=e.wikiAbsorb),`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function Em(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:nt(t)}}function Tm(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:nt(t)}}function Am(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:nt(t)}}function Cm(t){let{def:e}=V(t);return Be(e.workspace)}function Im(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Ct(a.workspace,e)}function Mm(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return It(n.workspace,a,String(e?.content??""))}function Lm(t){let{def:e}=V(t),a=Be(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Rm(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Mt(n.workspace,a,{title:e?.title,content:e?.content})}function Pm(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)}function $m(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Lr(a.workspace,e),r=Rt(a.workspace,e);return{slug:e,tree:n,deps:r}}function jm(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Rr(n.workspace,e,a)}function Om(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 Pr(r.workspace,a,n,String(e?.content??""))}function Nm(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Rt(a.workspace,e)}async function Dm(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=Ci(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(`
|
|
10717
|
+
`);return Ii(a,r,s,`install-${n}:${Date.now()}`)}async function Hm(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Ci(e?.worker),{def:o}=V(t),s=Rt(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=Si(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(`
|
|
10718
|
+
`);return Ii(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Ci(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 Ii(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}})}),d=await l.text(),c;try{c=JSON.parse(d)}catch{c={content:d}}if(!l.ok)throw new Error(c?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:c?.taskId,content:c?.content,duration:c?.duration,error:c?.error}}function Bm(t){let e=Ai(),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 qm(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 rn(){return new Fn}function zm(t){let e=rn(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Fm(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,d=rn().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:d}}function Um(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:rn().remove(e,a,n)?"Released":"No active handover for that chat"}}function aa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Wm(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var $e={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var Mi=[{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 on(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify($e)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
10719
10719
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
10720
10720
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
10721
10721
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
10722
10722
|
<main id="grid" class="ax-live__body"></main>
|
|
10723
10723
|
</div>
|
|
10724
|
-
`;return I({title:`${$e.brand} \xB7 ${$e.subtitle}`,activeTab:"live",subtitle:$e.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:
|
|
10724
|
+
`;return I({title:`${$e.brand} \xB7 ${$e.subtitle}`,activeTab:"live",subtitle:$e.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Gm,scripts:e+`<script>${Xm}</script>`,headExtras:`<script>
|
|
10725
10725
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
10726
10726
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
10727
10727
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -10732,7 +10732,7 @@ loadAgent();
|
|
|
10732
10732
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
10733
10733
|
right.insertBefore(extras, right.firstChild);
|
|
10734
10734
|
});
|
|
10735
|
-
</script>`})}var
|
|
10735
|
+
</script>`})}var Gm=`
|
|
10736
10736
|
/* --- Page frame --- */
|
|
10737
10737
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
10738
10738
|
|
|
@@ -10856,6 +10856,11 @@ loadAgent();
|
|
|
10856
10856
|
font-size: var(--ax-fs-xs); color: var(--ax-accent);
|
|
10857
10857
|
}
|
|
10858
10858
|
.ax-agent__task-head .elapsed { margin-left: auto; font-family: var(--ax-mono); color: var(--ax-muted); }
|
|
10859
|
+
.ax-agent__task-wf {
|
|
10860
|
+
font-family: var(--ax-mono); font-size: 11px; color: var(--ax-muted);
|
|
10861
|
+
overflow-wrap: anywhere; margin-top: 4px;
|
|
10862
|
+
}
|
|
10863
|
+
.ax-agent__task-wf-label { color: var(--ax-accent); }
|
|
10859
10864
|
.ax-agent__task-body {
|
|
10860
10865
|
font-size: var(--ax-fs-sm); margin-top: 4px;
|
|
10861
10866
|
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
@@ -10947,7 +10952,7 @@ loadAgent();
|
|
|
10947
10952
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
10948
10953
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
10949
10954
|
}
|
|
10950
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
10955
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,Xm=`
|
|
10951
10956
|
'use strict';
|
|
10952
10957
|
|
|
10953
10958
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -11236,6 +11241,17 @@ function lessonHtml(l, nodeUrl) {
|
|
|
11236
11241
|
'</div>';
|
|
11237
11242
|
}
|
|
11238
11243
|
|
|
11244
|
+
// The workflow run a task belongs to and the step it is on (#858). A task
|
|
11245
|
+
// wrapped under workflows.required runs as "task"; its title is the
|
|
11246
|
+
// request, already shown above, so only the step is named.
|
|
11247
|
+
function workflowLine(w) {
|
|
11248
|
+
if (!w || !w.runId) return '';
|
|
11249
|
+
const name = w.workflowId && w.workflowId !== 'task' ? (w.title || w.workflowId) + ' \xB7 ' : '';
|
|
11250
|
+
return '<div class="ax-agent__task-wf" title="Workflow run ' + escapeHtml(w.runId) + '">' +
|
|
11251
|
+
'<span class="ax-agent__task-wf-label">workflow</span> ' + escapeHtml(name) + 'step ' + escapeHtml(w.step || '\u2026') +
|
|
11252
|
+
'</div>';
|
|
11253
|
+
}
|
|
11254
|
+
|
|
11239
11255
|
function renderAgent(a, node) {
|
|
11240
11256
|
const card = document.createElement('div');
|
|
11241
11257
|
const lesson = lessonOf(a, node);
|
|
@@ -11275,6 +11291,7 @@ function renderAgent(a, node) {
|
|
|
11275
11291
|
'<span class="elapsed">' + elapsed + '</span>' +
|
|
11276
11292
|
'</div>' +
|
|
11277
11293
|
'<div class="ax-agent__task-body">' + escapeHtml(t.messagePreview || '(no preview)') + '</div>' +
|
|
11294
|
+
workflowLine(t.workflow) +
|
|
11278
11295
|
actions +
|
|
11279
11296
|
'</div>';
|
|
11280
11297
|
}).join('');
|
|
@@ -11567,7 +11584,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11567
11584
|
});
|
|
11568
11585
|
}
|
|
11569
11586
|
|
|
11570
|
-
`;var
|
|
11587
|
+
`;var Li=`
|
|
11571
11588
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
11572
11589
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
11573
11590
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -11741,7 +11758,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11741
11758
|
.mx-summary{max-width:56vw}
|
|
11742
11759
|
}
|
|
11743
11760
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
11744
|
-
`;var
|
|
11761
|
+
`;var Ri=`<script>
|
|
11745
11762
|
window.MX=(function(){
|
|
11746
11763
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
11747
11764
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -11850,7 +11867,7 @@ window.MX=(function(){
|
|
|
11850
11867
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
11851
11868
|
setHealth:setHealth,get:get};
|
|
11852
11869
|
})();
|
|
11853
|
-
</script>`;var
|
|
11870
|
+
</script>`;var Pi=`<script>
|
|
11854
11871
|
window.MXD=(function(){
|
|
11855
11872
|
function el(id){return document.getElementById(id)}
|
|
11856
11873
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -12064,7 +12081,7 @@ window.MXD=(function(){
|
|
|
12064
12081
|
|
|
12065
12082
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
12066
12083
|
})();
|
|
12067
|
-
</script>`;var
|
|
12084
|
+
</script>`;var $i=`<script>
|
|
12068
12085
|
(function(){
|
|
12069
12086
|
var LANES=[
|
|
12070
12087
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -12380,7 +12397,7 @@ window.MXD=(function(){
|
|
|
12380
12397
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
12381
12398
|
load();
|
|
12382
12399
|
})();
|
|
12383
|
-
</script>`;var
|
|
12400
|
+
</script>`;var ji=`<script>
|
|
12384
12401
|
(function(){
|
|
12385
12402
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
12386
12403
|
var esc=MX.esc;
|
|
@@ -12558,7 +12575,7 @@ window.MXD=(function(){
|
|
|
12558
12575
|
}
|
|
12559
12576
|
load();setInterval(load,5000);
|
|
12560
12577
|
})();
|
|
12561
|
-
</script>`;var
|
|
12578
|
+
</script>`;var Oi=`
|
|
12562
12579
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
12563
12580
|
.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}
|
|
12564
12581
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -12599,7 +12616,7 @@ window.MXD=(function(){
|
|
|
12599
12616
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
12600
12617
|
.mx-rt-name{max-width:100%}
|
|
12601
12618
|
}
|
|
12602
|
-
`,
|
|
12619
|
+
`,Ni=`<script>
|
|
12603
12620
|
(function(){
|
|
12604
12621
|
var root=document.getElementById('mx-routines');
|
|
12605
12622
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -12726,7 +12743,7 @@ window.MXD=(function(){
|
|
|
12726
12743
|
syncBar();
|
|
12727
12744
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
12728
12745
|
})();
|
|
12729
|
-
</script>`;var
|
|
12746
|
+
</script>`;var Di=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Hi=`<script>
|
|
12730
12747
|
(function(){
|
|
12731
12748
|
var root=document.getElementById('mx-feed');
|
|
12732
12749
|
if(!root)return;
|
|
@@ -12801,12 +12818,12 @@ window.MXD=(function(){
|
|
|
12801
12818
|
}
|
|
12802
12819
|
load();setInterval(load,5000);
|
|
12803
12820
|
})();
|
|
12804
|
-
</script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var
|
|
12821
|
+
</script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Km=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Jm=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Vm=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Bi(t){let e=pe({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Pt([{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">
|
|
12805
12822
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
12806
|
-
${
|
|
12823
|
+
${Jm.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("")}
|
|
12807
12824
|
</div>
|
|
12808
12825
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
12809
|
-
${
|
|
12826
|
+
${Vm.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
12810
12827
|
</div>
|
|
12811
12828
|
</div>
|
|
12812
12829
|
<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">
|
|
@@ -12859,7 +12876,7 @@ window.MXD=(function(){
|
|
|
12859
12876
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
12860
12877
|
${ne(ae.routines,"Routines","Everything that runs on its own: schedules and cron- or event-triggered workflows, per node. Flags mark routines that keep failing, went quiet, never ran, or sat disabled.","mx-routines-title",'<span class="ax-tab-count" id="mx-rt-count">0 routines</span>')}
|
|
12861
12878
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
12862
|
-
${
|
|
12879
|
+
${Km.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12863
12880
|
</div>
|
|
12864
12881
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
12865
12882
|
</section>
|
|
@@ -12867,7 +12884,7 @@ window.MXD=(function(){
|
|
|
12867
12884
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
12868
12885
|
${ne(ae.feed,"Mesh feed","The newest events from this machine and every machine it follows. Unreachable machines and announcements show here too. Select an event for its details.","mx-feed-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-feed-count">0 events</span><button class="ax-btn ax-btn--ghost" id="mx-feed-more" type="button" hidden>Show all</button></div>')}
|
|
12869
12886
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
12870
|
-
${
|
|
12887
|
+
${Di.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12871
12888
|
</div>
|
|
12872
12889
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
12873
12890
|
</section>
|
|
@@ -12900,7 +12917,7 @@ window.MXD=(function(){
|
|
|
12900
12917
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
12901
12918
|
</header>
|
|
12902
12919
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
12903
|
-
</aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
12920
|
+
</aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Li+Oi,scripts:Ri+Ym+Pi+$i+Ni+ji+Hi})}var Ym=`<script>
|
|
12904
12921
|
(function(){
|
|
12905
12922
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
12906
12923
|
var range=document.getElementById('mx-range');
|
|
@@ -12928,10 +12945,10 @@ window.MXD=(function(){
|
|
|
12928
12945
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
12929
12946
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
12930
12947
|
})();
|
|
12931
|
-
</script>`;function
|
|
12948
|
+
</script>`;function qi(t){let e=pe({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."})+`
|
|
12932
12949
|
<div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
|
|
12933
12950
|
<ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
|
|
12934
|
-
<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:
|
|
12951
|
+
<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:Qm,scripts:`<script>${Zm}</script>`})}var Qm=`
|
|
12935
12952
|
.gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
|
|
12936
12953
|
.gm-empty { color: var(--ax-text-2); }
|
|
12937
12954
|
.gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
@@ -12949,7 +12966,7 @@ window.MXD=(function(){
|
|
|
12949
12966
|
.gm-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
12950
12967
|
.gm-msg.is-bad { color: var(--ax-red-ink); }
|
|
12951
12968
|
.gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
12952
|
-
`,
|
|
12969
|
+
`,Zm=`
|
|
12953
12970
|
(function () {
|
|
12954
12971
|
var list = document.getElementById('gm-list');
|
|
12955
12972
|
var msg = document.getElementById('gm-msg');
|
|
@@ -12996,7 +13013,7 @@ window.MXD=(function(){
|
|
|
12996
13013
|
load();
|
|
12997
13014
|
setInterval(load, 30000);
|
|
12998
13015
|
})();
|
|
12999
|
-
`;async function
|
|
13016
|
+
`;async function zi(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 d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return ef(s,e.days)}function ef(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=[],d=0,c=0,p=0,m=0,g=0,_=0;for(let{node:S,data:T}of t)if(T){a.runs+=T.totals.runs,a.errors+=T.totals.errors,a.hours+=T.totals.hours,a.agents+=T.totals.agents,a.threads+=T.totals.threads;for(let h of T.days){let u=n.get(h.day)||{day:h.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let f of["cron","workflow","direct"])u[f][0]+=h[f]?.[0]||0,u[f][1]+=h[f]?.[1]||0;n.set(h.day,u)}for(let h of T.origins){let u=r.get(h.channel)||{channel:h.channel,runs:0,errors:0,hours:0};u.runs+=h.runs,u.errors+=h.errors,u.hours+=h.hours,r.set(h.channel,u)}for(let h of T.causes){let u=o.get(h.cause)||{cause:h.cause,count:0,agents:[],example:""};u.count+=h.count;for(let f of h.agents)u.agents.includes(f)||u.agents.push(f);u.example||(u.example=h.example),o.set(h.cause,u)}for(let h of T.rotations.byReason)s.set(h.reason,(s.get(h.reason)||0)+h.count);d+=T.rotations.total,c+=T.rotations.tokenSum||0,p+=T.rotations.tokenSamples||0,m=Math.max(m,T.rotations.maxTokens),g+=T.retention.traces,_+=T.retention.tracesWithSteps;for(let h of T.jobs)i.push({...h,node:S.name,nodeUrl:S.url});for(let h of T.threads)l.push({...h,node:S.name,nodeUrl:S.url})}let y=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:y.length?Math.min(...y):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,T)=>S.day.localeCompare(T.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,T)=>T.runs-S.runs),causes:[...o.values()].sort((S,T)=>T.count-S.count),jobs:i.sort((S,T)=>T.hours-S.hours),threads:l.sort((S,T)=>T.lastAt-T.firstAt-(S.lastAt-S.firstAt)||T.runs-S.runs),rotations:{total:d,byReason:[...s.entries()].map(([S,T])=>({reason:S,count:T})).sort((S,T)=>T.count-S.count),tokenSum:c,tokenSamples:p,maxTokens:m},retention:{traces:g,tracesWithSteps:_}}}async function Fi(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 Ui(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 d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return tf(s,e.day)}function tf(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 d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}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 Wi(t={}){let e=`
|
|
13000
13017
|
<select id="boardPicker" title="Switch board"></select>
|
|
13001
13018
|
<div class="search">
|
|
13002
13019
|
<span class="icon">\u2315</span>
|
|
@@ -13097,7 +13114,7 @@ window.MXD=(function(){
|
|
|
13097
13114
|
</footer>
|
|
13098
13115
|
</div>
|
|
13099
13116
|
</div>
|
|
13100
|
-
<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:
|
|
13117
|
+
<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:af,scripts:`<script>${nf}</script>`,headExtras:`<script>
|
|
13101
13118
|
// The boards page has its own connection dot + wants body height:100%
|
|
13102
13119
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
13103
13120
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -13113,7 +13130,7 @@ window.MXD=(function(){
|
|
|
13113
13130
|
right.insertBefore(dot, right.firstChild);
|
|
13114
13131
|
}
|
|
13115
13132
|
});
|
|
13116
|
-
</script>`})}var
|
|
13133
|
+
</script>`})}var af=`
|
|
13117
13134
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
13118
13135
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
13119
13136
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -13366,7 +13383,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
13366
13383
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
13367
13384
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
13368
13385
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
13369
|
-
`,
|
|
13386
|
+
`,nf=`
|
|
13370
13387
|
'use strict';
|
|
13371
13388
|
const state = {
|
|
13372
13389
|
boards: [], current: null, items: {},
|
|
@@ -14419,9 +14436,9 @@ function appendEvents(events) {
|
|
|
14419
14436
|
}
|
|
14420
14437
|
|
|
14421
14438
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
14422
|
-
`;function
|
|
14439
|
+
`;function Gi(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
14423
14440
|
<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>
|
|
14424
|
-
${
|
|
14441
|
+
${Mi.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:`${$e.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:rf})}var rf=`
|
|
14425
14442
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
14426
14443
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14427
14444
|
.lead {
|
|
@@ -14451,7 +14468,7 @@ article.term .alias {
|
|
|
14451
14468
|
}
|
|
14452
14469
|
article.term p {
|
|
14453
14470
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
14454
|
-
}`;function
|
|
14471
|
+
}`;function Xi(t={}){let e=`<div class="ax-wf__root">
|
|
14455
14472
|
<aside class="ax-wf__list">
|
|
14456
14473
|
<header>
|
|
14457
14474
|
<h2>Workflows</h2>
|
|
@@ -14474,6 +14491,19 @@ article.term p {
|
|
|
14474
14491
|
<p class="hint">Workflows agents started for your requests, grouped by who or what they concern. Open a group to see which step each one is on and what it waits for.</p>
|
|
14475
14492
|
<div id="wf-followups-body" aria-live="polite"><span class="hint">Loading…</span></div>
|
|
14476
14493
|
</section>
|
|
14494
|
+
<section class="ax-wf__required" aria-labelledby="wf-required-title">
|
|
14495
|
+
<details id="wf-required">
|
|
14496
|
+
<summary><h3 id="wf-required-title">Every task in a workflow</h3><span class="hint" id="wf-required-state"></span></summary>
|
|
14497
|
+
<p class="hint">When on, each task an agent gets runs inside a workflow run: a saved workflow that fits, else a plan the agent writes first, else one step. Every run is recorded step by step.</p>
|
|
14498
|
+
<label class="ax-wf__req-row"><input type="checkbox" id="wf-required-enabled" /> Run every task through a workflow</label>
|
|
14499
|
+
<label class="ax-wf__req-row"><input type="checkbox" id="wf-required-exempt" /> Plain questions leave no run (nothing was changed)</label>
|
|
14500
|
+
<details class="ax-wf__req-agents">
|
|
14501
|
+
<summary>Per agent</summary>
|
|
14502
|
+
<div id="wf-required-agents"></div>
|
|
14503
|
+
</details>
|
|
14504
|
+
<span class="hint" id="wf-required-note" aria-live="polite"></span>
|
|
14505
|
+
</details>
|
|
14506
|
+
</section>
|
|
14477
14507
|
<ul id="wf-list" class="ax-wf__cards" aria-live="polite"></ul>
|
|
14478
14508
|
<div id="wf-empty" class="ax-wf__empty" hidden>
|
|
14479
14509
|
<p><b>No workflows yet.</b></p>
|
|
@@ -14536,7 +14566,7 @@ article.term p {
|
|
|
14536
14566
|
</aside>
|
|
14537
14567
|
</div>
|
|
14538
14568
|
|
|
14539
|
-
<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:
|
|
14569
|
+
<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:of,scripts:`<script>${z({workflowHealth:er})}${sf}</script>`})}var of=`
|
|
14540
14570
|
.ax-wf__root {
|
|
14541
14571
|
display: grid;
|
|
14542
14572
|
grid-template-columns: 340px 1fr;
|
|
@@ -14613,6 +14643,18 @@ article.term p {
|
|
|
14613
14643
|
.ax-wf__fu-row b { overflow-wrap: anywhere; }
|
|
14614
14644
|
.ax-wf__fu-row .hint { overflow-wrap: anywhere; }
|
|
14615
14645
|
.ax-wf__fu-row.is-blocked b::before { content: "\u26A0 "; color: var(--ax-err); }
|
|
14646
|
+
.ax-wf__required { border-bottom: var(--ax-border-w) solid var(--ax-border); padding: 8px 16px; }
|
|
14647
|
+
.ax-wf__required > details > summary {
|
|
14648
|
+
cursor: pointer; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; list-style: none;
|
|
14649
|
+
}
|
|
14650
|
+
.ax-wf__required h3 { font-size: 13px; font-weight: 600; margin: 0; }
|
|
14651
|
+
.ax-wf__required details[open] > summary { margin-bottom: 6px; }
|
|
14652
|
+
.ax-wf__required summary:focus-visible, .ax-wf__required input:focus-visible, .ax-wf__required select:focus-visible { outline: 2px solid var(--ax-accent); outline-offset: 2px; }
|
|
14653
|
+
.ax-wf__req-row { display: flex; gap: 6px; align-items: center; font-size: 12px; padding: 3px 0; }
|
|
14654
|
+
.ax-wf__req-agents > summary { cursor: pointer; font-size: 12px; padding: 4px 0; }
|
|
14655
|
+
.ax-wf__req-agent { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 12px; padding: 2px 0; }
|
|
14656
|
+
.ax-wf__req-agent span { overflow-wrap: anywhere; min-width: 0; }
|
|
14657
|
+
.ax-wf__req-agent select { font: inherit; font-size: 12px; background: var(--ax-surface); color: inherit; border: var(--ax-border-w) solid var(--ax-border); border-radius: 4px; }
|
|
14616
14658
|
.ax-wf__n8n {
|
|
14617
14659
|
border-top: var(--ax-border-w) solid var(--ax-border);
|
|
14618
14660
|
padding: 14px 16px; display: flex; flex-direction: column; gap: 8px;
|
|
@@ -14942,7 +14984,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14942
14984
|
font-size: 12px; z-index: 50;
|
|
14943
14985
|
}
|
|
14944
14986
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
14945
|
-
`,
|
|
14987
|
+
`,sf=`
|
|
14946
14988
|
(() => {
|
|
14947
14989
|
const $ = (sel) => document.querySelector(sel)
|
|
14948
14990
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -15643,6 +15685,67 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15643
15685
|
toast("Failed to load workflows: " + e.message)
|
|
15644
15686
|
}
|
|
15645
15687
|
loadFollowUps()
|
|
15688
|
+
loadRequired()
|
|
15689
|
+
}
|
|
15690
|
+
|
|
15691
|
+
// Every task in a workflow (#858): this node's workflows.required.
|
|
15692
|
+
async function loadRequired() {
|
|
15693
|
+
const box = $("#wf-required")
|
|
15694
|
+
if (!box) return
|
|
15695
|
+
let data
|
|
15696
|
+
try {
|
|
15697
|
+
data = await fetchJSON("/api/workflows/required")
|
|
15698
|
+
} catch (e) {
|
|
15699
|
+
$("#wf-required-state").textContent = "unavailable"
|
|
15700
|
+
$("#wf-required-note").textContent = "Could not load the setting: " + e.message
|
|
15701
|
+
return
|
|
15702
|
+
}
|
|
15703
|
+
renderRequired(data)
|
|
15704
|
+
}
|
|
15705
|
+
|
|
15706
|
+
// Whether the engine was on when the page loaded: the daemon only starts
|
|
15707
|
+
// it at boot, so switching it on here needs a restart.
|
|
15708
|
+
let requiredEngineAtLoad = null
|
|
15709
|
+
function renderRequired(data) {
|
|
15710
|
+
const st = data.settings || {}
|
|
15711
|
+
if (requiredEngineAtLoad === null) requiredEngineAtLoad = !!st.engine
|
|
15712
|
+
const overrides = st.agents || {}
|
|
15713
|
+
const onFor = Object.keys(overrides).filter((k) => overrides[k])
|
|
15714
|
+
$("#wf-required-state").textContent = (st.enabled ? "on" : "off") + (onFor.length && !st.enabled ? " \xB7 on for " + onFor.length + " agent(s)" : "")
|
|
15715
|
+
$("#wf-required-enabled").checked = !!st.enabled
|
|
15716
|
+
$("#wf-required-exempt").checked = st.exemptQuestions !== false
|
|
15717
|
+
$("#wf-required-note").textContent = st.engine ? "" : "The workflow engine is off: turning this on also turns it on."
|
|
15718
|
+
$("#wf-required-agents").innerHTML = (data.agents || []).map((id) => {
|
|
15719
|
+
const v = Object.prototype.hasOwnProperty.call(overrides, id) ? (overrides[id] ? "on" : "off") : "default"
|
|
15720
|
+
return '<label class="ax-wf__req-agent"><span>' + esc(id) + '</span><select data-agent="' + esc(id) + '" aria-label="Workflow required for ' + esc(id) + '">' +
|
|
15721
|
+
['default', 'on', 'off'].map((o) => '<option value="' + o + '"' + (o === v ? ' selected' : '') + '>' + (o === 'default' ? 'as above' : o) + '</option>').join("") +
|
|
15722
|
+
'</select></label>'
|
|
15723
|
+
}).join("") || '<span class="hint">No agents on this node.</span>'
|
|
15724
|
+
$("#wf-required-agents").querySelectorAll("select[data-agent]").forEach((sel) => sel.addEventListener("change", () => {
|
|
15725
|
+
saveRequired({ agentId: sel.getAttribute("data-agent"), agentRequired: sel.value })
|
|
15726
|
+
}))
|
|
15727
|
+
}
|
|
15728
|
+
|
|
15729
|
+
;(function bindRequired() {
|
|
15730
|
+
const en = $("#wf-required-enabled")
|
|
15731
|
+
const ex = $("#wf-required-exempt")
|
|
15732
|
+
if (en) en.addEventListener("change", () => saveRequired({ enabled: en.checked }))
|
|
15733
|
+
if (ex) ex.addEventListener("change", () => saveRequired({ exemptQuestions: ex.checked }))
|
|
15734
|
+
})()
|
|
15735
|
+
|
|
15736
|
+
async function saveRequired(patch) {
|
|
15737
|
+
$("#wf-required-note").textContent = "Saving\u2026"
|
|
15738
|
+
try {
|
|
15739
|
+
const data = await postJSON("/api/workflows/required", patch)
|
|
15740
|
+
renderRequired(data)
|
|
15741
|
+
const engineNew = !requiredEngineAtLoad && data.settings && data.settings.engine
|
|
15742
|
+
$("#wf-required-note").textContent = engineNew
|
|
15743
|
+
? "Saved. The workflow engine was off: restart the daemon (agentx daemon restart) to start it."
|
|
15744
|
+
: data.reloaded ? "Saved." : "Saved. Restart the daemon if it does not pick it up."
|
|
15745
|
+
} catch (e) {
|
|
15746
|
+
$("#wf-required-note").textContent = "Not saved: " + e.message
|
|
15747
|
+
loadRequired()
|
|
15748
|
+
}
|
|
15646
15749
|
}
|
|
15647
15750
|
|
|
15648
15751
|
// Follow-ups (#788): running workflows grouped by tag. A group is a
|
|
@@ -15767,7 +15870,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15767
15870
|
setInterval(refresh, 15000)
|
|
15768
15871
|
})
|
|
15769
15872
|
})();
|
|
15770
|
-
`;function
|
|
15873
|
+
`;function Ki(t={}){let e=`<div class="ax-proc__root">
|
|
15771
15874
|
<header class="ax-proc__header">
|
|
15772
15875
|
<h1>Procedures</h1>
|
|
15773
15876
|
<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>
|
|
@@ -15811,7 +15914,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15811
15914
|
<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>
|
|
15812
15915
|
<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>
|
|
15813
15916
|
</section>
|
|
15814
|
-
</div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
15917
|
+
</div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:lf,scripts:`<script>${df}</script>`})}var lf=`
|
|
15815
15918
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
15816
15919
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
15817
15920
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -15837,7 +15940,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15837
15940
|
.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); }
|
|
15838
15941
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
15839
15942
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
15840
|
-
`,
|
|
15943
|
+
`,df=`
|
|
15841
15944
|
(function(){
|
|
15842
15945
|
function $(sel){ return document.querySelector(sel) }
|
|
15843
15946
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -15937,7 +16040,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15937
16040
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
15938
16041
|
else bootAll()
|
|
15939
16042
|
})();
|
|
15940
|
-
`;function
|
|
16043
|
+
`;function Ji(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
15941
16044
|
data-task-id="${H(t.taskId)}"
|
|
15942
16045
|
data-agent-id="${H(t.agentId)}"
|
|
15943
16046
|
data-node-url="${H(t.nodeUrl)}"
|
|
@@ -15980,7 +16083,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15980
16083
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
15981
16084
|
</div>
|
|
15982
16085
|
</footer>
|
|
15983
|
-
</div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
16086
|
+
</div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:cf,scripts:`<script>${pf}</script>`})}var cf=`
|
|
15984
16087
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
15985
16088
|
the sticky topbar. Breathe. */
|
|
15986
16089
|
.ax-task-page {
|
|
@@ -16122,7 +16225,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16122
16225
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
16123
16226
|
}
|
|
16124
16227
|
|
|
16125
|
-
`,
|
|
16228
|
+
`,pf=`
|
|
16126
16229
|
(function () {
|
|
16127
16230
|
var root = document.querySelector('.ax-task-page');
|
|
16128
16231
|
if (!root) return;
|
|
@@ -16507,7 +16610,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16507
16610
|
});
|
|
16508
16611
|
|
|
16509
16612
|
})();
|
|
16510
|
-
`;function
|
|
16613
|
+
`;function Vi(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
16511
16614
|
data-agent-id="${H(t.agentId)}"
|
|
16512
16615
|
data-agent-name="${H(e)}"
|
|
16513
16616
|
data-node-url="${H(t.nodeUrl)}">
|
|
@@ -16536,7 +16639,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16536
16639
|
<div class="ax-history__list" id="hist-list">
|
|
16537
16640
|
<div class="ax-history__empty">loading\u2026</div>
|
|
16538
16641
|
</div>
|
|
16539
|
-
</div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
16642
|
+
</div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:uf,scripts:`<script>${mf}</script>`})}var uf=`
|
|
16540
16643
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
16541
16644
|
flush against the sticky topbar. */
|
|
16542
16645
|
.ax-history {
|
|
@@ -16588,7 +16691,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16588
16691
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
16589
16692
|
}
|
|
16590
16693
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
16591
|
-
`,
|
|
16694
|
+
`,mf=`
|
|
16592
16695
|
(function () {
|
|
16593
16696
|
var root = document.querySelector('.ax-history');
|
|
16594
16697
|
if (!root) return;
|
|
@@ -16688,31 +16791,31 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16688
16791
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
16689
16792
|
});
|
|
16690
16793
|
})();
|
|
16691
|
-
`;function
|
|
16794
|
+
`;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 Xe(t,e,l=>Yi(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:hf(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?Xe(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:d})}):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"])?Xe(t,e,l=>{try{let d=a.layouts.save(s,l);return P(e,200,{layout:d})}catch(d){return P(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Xe(t,e,l=>{let d=wa.safeParse(l);if(!d.success)return P(e,200,{ok:!1,issues:d.error.issues.map(p=>({path:p.path.join("."),message:p.message}))});let c=ka(d.data).map(p=>({path:"",message:p}));return P(e,200,{ok:c.length===0,issues:c,workflow:d.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,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Xe(t,e,c=>Yi(e,a,c,{mode:"update",id:s,convertFromYaml:d}))}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 ff=["mesh"];function Yi(t,e,a,n){let r=wa.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=ka(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,d=e.store.get(n.id);if(d)for(let c of ff)!(c in l)&&c in d&&(o[c]=d[c])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),c=l?.yamlPath,p=!!c||/yaml round-trip failed/.test(d);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).":d,kind:p?"yaml-authored":"save-failed",...c?{path:c}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function hf(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))),d=r.get("workflowId")||void 0,c=r.get("summary")==="1"||r.get("summary")==="true",p=a.runs.list({workflowId:d,limit:l});if(!c)return P(e,200,{runs:p});let m=p.map(g=>({id:g.id,workflowId:g.workflowId,workflowVersion:g.workflowVersion,homeNode:g.homeNode,status:g.status,pending:g.pending,entityRef:g.entityRef,history:(g.history||[]).slice(-5),parentRunId:g.parentRunId,parentNodeId:g.parentNodeId,rootRunId:g.rootRunId,depth:g.depth,createdAt:g.createdAt,updatedAt:g.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 Xe(t,e,d=>{let c=d?.status;return c!=="paused"&&c!=="running"&&c!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,c)?P(e,200,{ok:!0,runId:l,status:c}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return gf(t,e,a,l);let d=a.runs.get(l);return d?P(e,200,{run:d}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function gf(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)}
|
|
16692
16795
|
|
|
16693
|
-
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(
|
|
16796
|
+
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(c);try{e.end()}catch{}};t.on("close",s);let i=p=>{if(!o)try{e.write(`data: ${JSON.stringify(p)}
|
|
16694
16797
|
|
|
16695
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),
|
|
16798
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,c=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==d&&(d=p.updatedAt,i(p))},2e3);return!0}function Xe(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 lh}from"fs";import{createRequire as dh}from"module";On();var el=50,xf=280;async function tl(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=bf(await o.recent(el))}catch(d){l=String(d?.message||"unreachable").slice(0,200)}return Zi(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Zi(e,404,{error:"not found"})}function al(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled)return null;if(n.relayTo)return wt();let r=ut();return r?new sr(r):null}}}function bf(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:sn(typeof n.summary=="string"?n.summary:"",xf),by:typeof n.agentId=="string"?sn(n.agentId,100):null,node:sn(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,el)}function sn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Zi(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var vf="operator",yf=50,nl=4,rl=500;function wf(t){let e={channel:"app",chatId:t.chatId,sender:vf,...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 ol(t,e,a,n){let{path:r,body:o}=wf(e),s="",i=!1,l=[],d=new Map,c=(p,m,g)=>{let _=p!=="done",y=i?{text:xt(m,_),artifacts:[]}:gt(m,ce.perMessage,_),{cleanText:S,ui:T}=p==="done"?vt(y.text):{cleanText:y.text,ui:void 0},h=i?void 0:ln(T);return{status:p,text:S,tools:l,files:y.artifacts,...h?{ui:h}:{},...g?{error:g}:{}}};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(g=>g?.error).catch(()=>"");return c("error",s,m||`AgentX answered HTTP ${p.status}.`)}for await(let m of _f(p.body)){n(m.event,m.data);let g=m.data??{};if(m.event==="start")i=g.rich===!1;else if(m.event==="text"&&typeof g.text=="string")s+=g.text;else if(m.event==="tool"&&g.status==="start"&&l.length<yf){let _={name:String(g.name||"tool").slice(0,80),...g.arg?{arg:String(g.arg).slice(0,80)}:{}};l.push(_),g.id&&d.set(String(g.id),_)}else if(m.event==="tool"&&g.status==="result"&&g.error===!0&&d.has(String(g.id)))d.get(String(g.id)).error=!0;else{if(m.event==="done")return c("done",typeof g.content=="string"&&g.content?g.content:s);if(m.event==="error")return c("error",s,kf(g.error))}}return a.aborted?c("stopped",s):c("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?c("stopped",s):c("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function kf(t){let e=String(t||"The agent could not answer.");return Un(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ln(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,nl).map(s=>s.slice(0,rl));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,nl).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,rl)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*_f(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,`
|
|
16696
16799
|
`);let s;for(;(s=n.indexOf(`
|
|
16697
16800
|
|
|
16698
|
-
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",
|
|
16699
|
-
`))
|
|
16801
|
+
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let c of i.split(`
|
|
16802
|
+
`))c.startsWith("event:")?l=c.slice(6).trim():c.startsWith("data:")&&d.push(c.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
|
|
16700
16803
|
`))}}catch{}}}}finally{e.releaseLock()}}var na=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}
|
|
16701
16804
|
data: ${JSON.stringify(s)}
|
|
16702
16805
|
|
|
16703
16806
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
16704
16807
|
|
|
16705
|
-
`)},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
|
|
16706
|
-
`)){let n=
|
|
16707
|
-
`).map(
|
|
16808
|
+
`)},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 il(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=Sf(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:dn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function dn(t,e=120){for(let a of t.split(`
|
|
16809
|
+
`)){let n=ll(a);if(n)return cn(n,e)}return""}function Sf(t,e=120){let a=t.split(`
|
|
16810
|
+
`).map(ll).filter(Boolean);return a.length?cn(a[a.length-1],e):""}function ll(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function cn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var ra=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 oa(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var sl=140;function sa(t,e,a,n,r){let o=a==="error"?`Could not answer: ${dn(r||"",sl-18)||"something went wrong."}`:dn(n,sl)||"Answered.";return{deviceId:t,title:cn(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var cl=8e3,Tf=/^[A-Za-z0-9_.:-]{1,64}$/,je=new Map,pn=new Map,fn=new ra;function pl(){return fn}async function ul(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??fn;if(n==="GET"&&a==="/api/app/agents")return B(e,200,{nodes:await ml(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:il(r.id,If(),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 c=i.get(r.id,decodeURIComponent(l[1]));if(!c)return B(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,c.id);let p=je.get(c.id);return B(e,200,{...c,running:!!p,...p?{partial:{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let c=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=c&&je.get(c.id);if(!c||!p)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,c.id),fl(e);let{id:m,title:g,node:_,nodeName:y,agent:S,agentName:T}=c;return e.write(un("conversation",{id:m,title:g,node:_,nodeName:y,agent:S,agentName:T})),e.write(un("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 d;try{d=await yt(t,64*1024)}catch(c){return B(e,400,{error:c.message})}if(a==="/api/app/chat/stop"){let c=i.get(r.id,String(d.conversationId??""));if(!c)return B(e,404,{error:"no such conversation"});let p=je.get(c.id);return p?(p.ac.abort(),mn(c,o,r.name),B(e,200,{stopped:!0})):await mn(c,o,r.name)?B(e,200,{stopped:!0}):B(e,404,{error:"nothing is running in this conversation"})}return await Cf(e,d,r,i,o),!0}function Af(t,e,a){let n=Ke(e.url),r=new Set,o=[];for(let s of t){let i=Ke(s.url),l=a.find(p=>Ke(p.peerUrl)===i);l&&r.add(l.peer);let d=i===n,c=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:c.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 ml(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Af(e.nodes,t.daemon,a)}async function Cf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>cl){B(t,400,{error:`message must be 1\u2013${cl} 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:"",y=typeof e.agent=="string"?e.agent:"";if(!Tf.test(y)){B(t,400,{error:"pick an agent"});return}let S=(await ml(r)).find(h=>h.target===_);if(!S){B(t,400,{error:`unknown node "${_}"`});return}if(!S.online){B(t,409,{error:`${S.name} is offline`});return}let T=S.agents.find(h=>h.id===y);if(!T){B(t,400,{error:`no agent "${y}" on ${S.name}`});return}s=n.create(a.id,{node:_,nodeName:S.name,agent:y,agentName:T.name,...T.color?{color:T.color}:{}},o)}if(je.has(s.id)){B(t,409,{error:"The agent is still answering in this conversation."});return}let i=new na(r.orphanLimitMs??18e5);je.set(s.id,i);let{id:l,title:d,node:c,nodeName:p,agent:m,agentName:g}=s;pn.set(l,{id:l,deviceId:a.id,title:d,agent:m,...g?{agentName:g}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),fl(t),t.write(un("conversation",{id:l,title:d,node:c,nodeName:p,agent:m,agentName:g})),i.attach(t);try{let _=e.spoken===!0,y=await ol(r.daemon,{node:c,agent:m,message:o,chatId:`app:${l}`,spoken:_},i.ac.signal,(u,f)=>i.broadcast(u,f));i.orphaned&&(y.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,mn(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:y.text,status:y.status,at:Date.now(),...y.error?{error:y.error}:{},...y.ui?{ui:y.ui}:{},...y.tools.length?{tools:y.tools}:{}},y.files)??[];i.broadcast("final",{status:y.status,content:y.text,...y.error?{error:y.error}:{},...y.ui?{ui:y.ui}:{},...S.length?{files:S}:{}});let T=i.watched();T&&n.markRead(a.id,l);let h={status:y.status,attached:T,appOpen:(r.presence??fn).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&oa(h)&&r.notifyFinish(sa(a.id,s,y.status,y.text,y.error)).catch(()=>{})}finally{je.delete(l),pn.delete(l),i.finish()}}function If(){let t=[];for(let[e,a]of pn){let n=je.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function fl(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function un(t,e){return`event: ${t}
|
|
16708
16811
|
data: ${JSON.stringify(e)}
|
|
16709
16812
|
|
|
16710
|
-
`}async function mn(t,e,a){try{let n=Ke(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Ke(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ke(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 Ke(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 Cf}from"stream";var If=/^\/api\/app\/files\/([^/]+)$/,Mf=15e3;async function fl(t,e,a,n,r,o){let s=If.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Oe(e,405,{error:"GET only"});let i=o.store();if(!i)return Oe(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 Oe(e,404,{error:"no such file"});let d=await Lf(c.node,o);if(!d)return Oe(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(),Mf),g;try{let h=new URLSearchParams({agent:c.agent,file:c.path});g=await fetch(`${d.url}${br}?${h}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return Oe(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(g.status!==200&&g.status!==206){let h=await g.json().then(f=>f?.error).catch(()=>""),u=[403,404,413,415,416].includes(g.status)?g.status:502;return Oe(e,u,{error:h||`The computer that made this file answered HTTP ${g.status}.`})}let _=Number(g.headers.get("content-length")||0);if(_>de.bytes)return p.abort(),Oe(e,413,{error:"the file is too large"});let b=g.headers.get("content-range");if(e.writeHead(g.status,{...vr(c.mime,c.name,c.kind),...g.headers.get("content-length")?{"Content-Length":String(_)}:{},...g.status===206&&b?{"Content-Range":b}:{}}),n==="HEAD"||!g.body)return e.end(),!0;let S=0,T=Cf.fromWeb(g.body);return T.on("data",h=>{S+=h.length,S>de.bytes&&(T.destroy(),e.destroy())}),T.on("error",()=>e.destroy()),T.pipe(e),!0}async function Lf(t,e){if(t==="local")return{url:ml(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ml(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ml(t){return t.replace(/\/+$/,"")}function Oe(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 gl=8e3;async function xl(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Y(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let g=String(t.headers["content-type"]||"");if(!Cr(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let _=Ar(t.headers["x-audio-duration-ms"]);if(_)return t.resume(),Y(e,_.status,{error:_.error});let b=await Te(t,Tr.bytes);if(!b)return Y(e,413,{error:Ir()});if(!b.length)return Y(e,400,{error:"The recording is empty."});let S={"Content-Type":g,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return hl(e,o.daemon,"/voice/transcribe",b,S,18e4)}let s,i=await Te(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Y(e,404,{error:"no such conversation"});let d=typeof s?.text=="string"?s.text.slice(0,gl):"";if(!d.trim())return Y(e,400,{error:"text is required"});if(!Pf(c.messages,d))return Y(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 hl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function hl(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(Rf(l)?.endpoints)?Y(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 Y(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function Rf(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Pf(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===gl&&a.content.startsWith(e)))}var $f=new Set(["ring","offer","answer","ice","hangup"]),Je=/^[A-Za-z0-9_-]{4,64}$/,jf=128*1024,Of=24,Nf=2*1024*1024,Ne=new Map;async function vl(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=Ze(r.nodeName),p=(Array.isArray(c.peers)?c.peers:[]).filter(g=>Ze(String(g?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(g=>g&&typeof g.id=="string").map(g=>({id:g.id,name:typeof g.name=="string"&&g.name?g.name:g.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 Te(t,jf);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=Hf(c,r.nodeName);if(typeof d=="string")return M(e,400,{error:d});let p=yl(d.to);if(p&&d.kind==="ring"){let m=await De(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)}),g=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:g?.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 Je.test(l)?Bf(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 Te(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(!Je.test(d))return M(e,400,{error:"callId is required"});let p=typeof c?.note=="string"?c.note:"",m=await De(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 bl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Je.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 De(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 bl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Je.test(c))return M(e,400,{error:"callId is required"});let d=await De(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??""),g=JSON.stringify([c,p.at,m,p.text]),_=Ne.get(g);return _?(Ne.delete(g),Ne.set(g,_),wl(e,_.type,_.bytes)):Df(e,o,s,{agent:m,text:p.text},(b,S)=>{if(!(S.length>Nf))for(Ne.set(g,{type:b,bytes:S});Ne.size>Of;)Ne.delete(Ne.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await De(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 De(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(!Je.test(l))return M(e,400,{error:"callId is required"});let c=await De(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 yl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function De(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 bl(t,e){let a=await Te(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 Df(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),wl(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 wl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function Hf(t,e){let a=String(t?.kind??"");if(!$f.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Je.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:")&&!yl(r))return"to must be bot:<agent id> for an agent";if(Ze(r)===Ze(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 Bf(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 zf,readFileSync as qf,renameSync as Ff,writeFileSync as Uf}from"fs";import{dirname as Wf,isAbsolute as Gf,resolve as Xf}from"path";import{randomBytes as Kf}from"crypto";var kl=60,_l=500,Jf=200,Tl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Vf=/^[A-Za-z0-9_-]{8,64}$/,Yf=/^[A-Za-z0-9._-]{1,64}$/;function Al(t,e){return Gf(e)?e:Xf(t,e)}function Sl(t){return`${t}_${Kf(6).toString("hex")}`}function El(){return{places:[],rules:[],seen:[]}}function Cl(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>kl)return{ok:!1,error:`Keep the name under ${kl} 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 Il(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!Tl.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>_l)return{ok:!1,error:`Keep it under ${_l} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Yf.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 Ml(t){let e=typeof t.id=="string"?t.id:"";if(!Vf.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!Tl.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 ia=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(qf(this.path,"utf-8"));return!e||typeof e!="object"?El():{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 El()}}write(e){zf(Wf(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Uf(a,JSON.stringify(e,null,2)+`
|
|
16711
|
-
`,{mode:384}),
|
|
16712
|
-
`)}async function
|
|
16813
|
+
`}async function mn(t,e,a){try{let n=Ke(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Ke(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ke(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 Ke(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 Mf}from"stream";var Lf=/^\/api\/app\/files\/([^/]+)$/,Rf=15e3;async function gl(t,e,a,n,r,o){let s=Lf.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Oe(e,405,{error:"GET only"});let i=o.store();if(!i)return Oe(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let d=i.getFile(r.id,l);if(!d)return Oe(e,404,{error:"no such file"});let c=await Pf(d.node,o);if(!c)return Oe(e,502,{error:`${d.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(),Rf),g;try{let h=new URLSearchParams({agent:d.agent,file:d.path});g=await fetch(`${c.url}${br}?${h}`,{method:n,headers:{...c.token?{Authorization:`Bearer ${c.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return Oe(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(g.status!==200&&g.status!==206){let h=await g.json().then(f=>f?.error).catch(()=>""),u=[403,404,413,415,416].includes(g.status)?g.status:502;return Oe(e,u,{error:h||`The computer that made this file answered HTTP ${g.status}.`})}let _=Number(g.headers.get("content-length")||0);if(_>ce.bytes)return p.abort(),Oe(e,413,{error:"the file is too large"});let y=g.headers.get("content-range");if(e.writeHead(g.status,{...vr(d.mime,d.name,d.kind),...g.headers.get("content-length")?{"Content-Length":String(_)}:{},...g.status===206&&y?{"Content-Range":y}:{}}),n==="HEAD"||!g.body)return e.end(),!0;let S=0,T=Mf.fromWeb(g.body);return T.on("data",h=>{S+=h.length,S>ce.bytes&&(T.destroy(),e.destroy())}),T.on("error",()=>e.destroy()),T.pipe(e),!0}async function Pf(t,e){if(t==="local")return{url:hl(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=hl(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function hl(t){return t.replace(/\/+$/,"")}function Oe(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 bl=8e3;async function vl(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Y(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let g=String(t.headers["content-type"]||"");if(!Cr(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let _=Ar(t.headers["x-audio-duration-ms"]);if(_)return t.resume(),Y(e,_.status,{error:_.error});let y=await Te(t,Tr.bytes);if(!y)return Y(e,413,{error:Ir()});if(!y.length)return Y(e,400,{error:"The recording is empty."});let S={"Content-Type":g,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return xl(e,o.daemon,"/voice/transcribe",y,S,18e4)}let s,i=await Te(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let d=l.get(r.id,String(s?.conversationId??""));if(!d)return Y(e,404,{error:"no such conversation"});let c=typeof s?.text=="string"?s.text.slice(0,bl):"";if(!c.trim())return Y(e,400,{error:"text is required"});if(!jf(d.messages,c))return Y(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${d.agentName||d.agent}: ${c}`:c,m={agent:d.agent,text:p,...d.node!=="local"?{peer:d.node}:{}};return xl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function xl(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)?Y(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 Y(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Y(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 jf(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===bl&&a.content.startsWith(e)))}var Of=new Set(["ring","offer","answer","ice","hangup"]),Je=/^[A-Za-z0-9_-]{4,64}$/,Nf=128*1024,Df=24,Hf=2*1024*1024,Ne=new Map;async function wl(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 d=await l.json(),c=Ze(r.nodeName),p=(Array.isArray(d.peers)?d.peers:[]).filter(g=>Ze(String(g?.name??""))!==c),m=(Array.isArray(d.agents)?d.agents:[]).filter(g=>g&&typeof g.id=="string").map(g=>({id:g.id,name:typeof g.name=="string"&&g.name?g.name:g.id}));return M(e,200,{node:r.nodeName,iceServers:d.iceServers??[],peers:p,agents:m,camera:d.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 Te(t,Nf);if(!l)return M(e,413,{error:"signal too large"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let c=qf(d,r.nodeName);if(typeof c=="string")return M(e,400,{error:c});let p=kl(c.to);if(p&&c.kind==="ring"){let m=await De(o,s,"POST","/webrtc/camera/watch",{callId:c.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(c),signal:AbortSignal.timeout(15e3)}),g=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:g?.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 Je.test(l)?zf(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 Te(t,4096);if(!l)return M(e,413,{error:"note too long"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let c=String(d?.callId??"");if(!Je.test(c))return M(e,400,{error:"callId is required"});let p=typeof d?.note=="string"?d.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/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 yl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Je.test(d))return M(e,400,{error:"callId is required"});let c=Number(l.seconds??0);if(!Number.isFinite(c)||c<0)return M(e,400,{error:"seconds must be 0 or more"});let p=typeof l.note=="string"?l.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/stream`,{seconds:c,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 yl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Je.test(d))return M(e,400,{error:"callId is required"});let c=await De(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(d)}`);if(c.status>=300)return M(e,c.status,{error:c.body.error});let p=(Array.isArray(c.body.watch?.replies)?c.body.watch.replies:[]).find(y=>y&&y.at===l.at);if(!p||typeof p.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(c.body.watch.agentId??""),g=JSON.stringify([d,p.at,m,p.text]),_=Ne.get(g);return _?(Ne.delete(g),Ne.set(g,_),_l(e,_.type,_.bytes)):Bf(e,o,s,{agent:m,text:p.text},(y,S)=>{if(!(S.length>Hf))for(Ne.set(g,{type:y,bytes:S});Ne.size>Df;)Ne.delete(Ne.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await De(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let d=(Array.isArray(l.body.calls)?l.body.calls:[]).map(c=>({id:c.id,agentId:c.agentId,reason:c.reason,createdAt:c.createdAt}));return M(e,200,{asks:d,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 De(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(!Je.test(l))return M(e,400,{error:"callId is required"});let d=await De(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,d.status,d.status<300?{watch:d.body.watch}:{error:d.body.error})}return M(e,404,{error:"not found"})}function kl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function De(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 yl(t,e){let a=await Te(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 Bf(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),_l(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 _l(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function qf(t,e){let a=String(t?.kind??"");if(!Of.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Je.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:")&&!kl(r))return"to must be bot:<agent id> for an agent";if(Ze(r)===Ze(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 zf(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 Ff,readFileSync as Uf,renameSync as Wf,writeFileSync as Gf}from"fs";import{dirname as Xf,isAbsolute as Kf,resolve as Jf}from"path";import{randomBytes as Vf}from"crypto";var Sl=60,El=500,Yf=200,Cl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Qf=/^[A-Za-z0-9_-]{8,64}$/,Zf=/^[A-Za-z0-9._-]{1,64}$/;function Il(t,e){return Kf(e)?e:Jf(t,e)}function Tl(t){return`${t}_${Vf(6).toString("hex")}`}function Al(){return{places:[],rules:[],seen:[]}}function Ml(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>Sl)return{ok:!1,error:`Keep the name under ${Sl} 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 Ll(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!Cl.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>El)return{ok:!1,error:`Keep it under ${El} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Zf.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 Rl(t){let e=typeof t.id=="string"?t.id:"";if(!Qf.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!Cl.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 ia=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(Uf(this.path,"utf-8"));return!e||typeof e!="object"?Al():{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 Al()}}write(e){Ff(Xf(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Gf(a,JSON.stringify(e,null,2)+`
|
|
16814
|
+
`,{mode:384}),Wf(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:Tl("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:Tl("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(-Yf);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(d=>d.placeId===o.id&&d.on===e.transition&&d.enabled&&!(d.lastFiredAt&&Date.parse(d.lastFiredAt)>r-i));for(let d of l)d.lastFiredAt=new Date(r).toISOString(),d.repeat||(d.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(d=>({...d}))}:{status:"no-rules"}}return this.write(n),s}};Dn();function eh(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function th(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(`
|
|
16815
|
+
`)}async function Pl(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=eh(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,th(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
|
|
16713
16816
|
|
|
16714
|
-
(${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
|
|
16715
|
-
${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?{[Nn]: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
|
|
16817
|
+
(${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 $l(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}
|
|
16818
|
+
${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?{[Nn]: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 jl(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Nl(t,e,a.slice(15),n,o,r)}async function Ol(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Nl(t,e,a.slice(11),n,r,null)}async function Nl(t,e,a,n,r,o){if(n==="GET"&&a===""){let i=r.enabled?r.store.read():{places:[],rules:[]};return q(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 q(e,404,{error:"not found"});if(!r.enabled)return q(e,403,{error:"Place reminders are off on this computer (app.places.enabled)."});let s;try{s=await yt(t,4096)}catch(i){return q(e,400,{error:i.message})}if(a==="/event"){if(!o)return q(e,404,{error:"not found"});let i=Rl(s);if(!i.ok)return q(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?Pl(o.id,l.place,l.rules,i.value.time,r.fire).catch(d=>r.log(`[places] delivery failed: ${d?.message||d}`)):r.log(`[places] ${l.rules.length} reminder(s) not sent: ${r.pushReason??"this computer doesn't send pushes"}`)),q(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=Ml(s,r.limits);if(!i.ok)return q(e,400,{error:i.error});let l=r.store.addPlace(i.value,r.limits);return l.ok?q(e,200,{ok:!0,place:l.place}):q(e,409,{error:l.error})}if(a==="/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removePlace(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such place."})}if(a==="/rules/add"){let i=new Set(r.agents()),l=Ll(s,c=>i.has(c));if(!l.ok)return q(e,400,{error:l.error});let d=r.store.addRule(l.value,r.limits);return d.ok?q(e,200,{ok:!0,rule:d.rule}):q(e,409,{error:d.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return q(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?q(e,200,{ok:!0,rule:i}):q(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such reminder."})}return q(e,404,{error:"not found"})}function Dl(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new ia(Il(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function Hl(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 q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Bl=`
|
|
16716
16819
|
:root {
|
|
16717
16820
|
--ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
|
|
16718
16821
|
--ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
|
|
@@ -16726,7 +16829,7 @@ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15
|
|
|
16726
16829
|
--ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
|
|
16727
16830
|
--phone-bubble: #1d2f52; --phone-green: #3dbe74;
|
|
16728
16831
|
}
|
|
16729
|
-
`,
|
|
16832
|
+
`,ql=`
|
|
16730
16833
|
[hidden] { display: none !important; }
|
|
16731
16834
|
main > .sw-peek[hidden] { display: block !important; }
|
|
16732
16835
|
main > #panel-chat.sw-peek[hidden] { display: flex !important; }
|
|
@@ -16832,7 +16935,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
|
|
|
16832
16935
|
@media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
|
|
16833
16936
|
@media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
|
|
16834
16937
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
|
|
16835
|
-
`;var
|
|
16938
|
+
`;var zl=`
|
|
16836
16939
|
window.AXSheet = function (sheet, onClose) {
|
|
16837
16940
|
var handle = document.createElement('button');
|
|
16838
16941
|
handle.type = 'button'; handle.className = 'sheet-handle';
|
|
@@ -16861,7 +16964,7 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
16861
16964
|
handle.addEventListener('pointercancel', reset);
|
|
16862
16965
|
sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
|
|
16863
16966
|
};
|
|
16864
|
-
`;var
|
|
16967
|
+
`;var Fl=`
|
|
16865
16968
|
(function () {
|
|
16866
16969
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
16867
16970
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -17152,7 +17255,7 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
17152
17255
|
setInterval(refresh, 15000);
|
|
17153
17256
|
refresh();
|
|
17154
17257
|
})();
|
|
17155
|
-
`;var
|
|
17258
|
+
`;var Ul=`
|
|
17156
17259
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
17157
17260
|
.fx-head h2 { margin: 4px 0 0; }
|
|
17158
17261
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -17217,7 +17320,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17217
17320
|
.fx-opt em { font-style: normal; font-size: 12px; color: var(--ax-ok); white-space: nowrap; }
|
|
17218
17321
|
.fx-error:empty { display: none; }
|
|
17219
17322
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
17220
|
-
`;var
|
|
17323
|
+
`;var Wl=`
|
|
17221
17324
|
(function () {
|
|
17222
17325
|
var panel = document.getElementById('panel-alerts');
|
|
17223
17326
|
if (!panel) return;
|
|
@@ -17428,7 +17531,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17428
17531
|
refresh();
|
|
17429
17532
|
loadRecent();
|
|
17430
17533
|
})();
|
|
17431
|
-
`;var
|
|
17534
|
+
`;var Gl=`
|
|
17432
17535
|
(function () {
|
|
17433
17536
|
var panel = document.getElementById('panel-alerts');
|
|
17434
17537
|
if (!panel) return;
|
|
@@ -17580,7 +17683,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17580
17683
|
document.addEventListener('visibilitychange', function () { if (!document.hidden && state) load(); });
|
|
17581
17684
|
load();
|
|
17582
17685
|
})();
|
|
17583
|
-
`,
|
|
17686
|
+
`,Xl=`
|
|
17584
17687
|
.pl-card { margin-top: 12px; }
|
|
17585
17688
|
.pl-list { margin-top: 8px; }
|
|
17586
17689
|
.pl-rules { list-style: none; margin: 6px 0 0; padding: 0; }
|
|
@@ -17599,7 +17702,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17599
17702
|
.pl-check { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); }
|
|
17600
17703
|
.pl-check input { width: 20px; height: 20px; }
|
|
17601
17704
|
#pl-here { justify-self: start; }
|
|
17602
|
-
`;function
|
|
17705
|
+
`;function Kl(t,e,a){return t!==1?"Could not find where you are. Try again outdoors, or type the coordinates.":e&&a!=="denied"?"The location was refused. If you tapped Don\u2019t allow, allow location for AgentX in the phone\u2019s settings. Otherwise Chrome hasn\u2019t linked the AgentX app yet: Force stop Chrome once (Settings \u203A Apps \u203A Chrome \u203A Force stop), then open AgentX again. Or type the coordinates.":"Location is blocked for this app. Allow it in the phone\u2019s settings, or type the coordinates."}var Jl=`
|
|
17603
17706
|
(function () {
|
|
17604
17707
|
var panel = document.getElementById('panel-alerts');
|
|
17605
17708
|
if (!panel) return;
|
|
@@ -17712,7 +17815,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17712
17815
|
}
|
|
17713
17816
|
load();
|
|
17714
17817
|
})();
|
|
17715
|
-
`;var
|
|
17818
|
+
`;var Vl=`
|
|
17716
17819
|
(function () {
|
|
17717
17820
|
var panel = document.getElementById('panel-chat');
|
|
17718
17821
|
var V = window.AXChatView;
|
|
@@ -17995,7 +18098,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17995
18098
|
var last = recall('ax-chat-conv');
|
|
17996
18099
|
if (!fromHash() && last) openConversation(last);
|
|
17997
18100
|
})();
|
|
17998
|
-
`;var
|
|
18101
|
+
`;var Yl=`
|
|
17999
18102
|
window.AXChatView = (function () {
|
|
18000
18103
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
18001
18104
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -18276,7 +18379,7 @@ window.AXChatView = (function () {
|
|
|
18276
18379
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
18277
18380
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
18278
18381
|
})();
|
|
18279
|
-
`;var
|
|
18382
|
+
`;var Ql=`
|
|
18280
18383
|
window.AXChatSheets = function (o) {
|
|
18281
18384
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
18282
18385
|
function loadPicker() {
|
|
@@ -18322,7 +18425,7 @@ window.AXChatSheets = function (o) {
|
|
|
18322
18425
|
});
|
|
18323
18426
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
18324
18427
|
};
|
|
18325
|
-
`;var
|
|
18428
|
+
`;var Zl=`
|
|
18326
18429
|
window.AXChatLog = function (o) {
|
|
18327
18430
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
18328
18431
|
function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
|
|
@@ -18385,7 +18488,7 @@ window.AXChatLog = function (o) {
|
|
|
18385
18488
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
18386
18489
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
18387
18490
|
};
|
|
18388
|
-
`;var
|
|
18491
|
+
`;var ed=`
|
|
18389
18492
|
(function () {
|
|
18390
18493
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
18391
18494
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -18535,7 +18638,7 @@ window.AXChatLog = function (o) {
|
|
|
18535
18638
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
18536
18639
|
poll();
|
|
18537
18640
|
})();
|
|
18538
|
-
`;var
|
|
18641
|
+
`;var td=`
|
|
18539
18642
|
.cs { margin: 0 -2px; }
|
|
18540
18643
|
.cs[hidden] { display: none; }
|
|
18541
18644
|
.cs-list {
|
|
@@ -18591,7 +18694,7 @@ window.AXChatLog = function (o) {
|
|
|
18591
18694
|
@media (prefers-reduced-motion: reduce) {
|
|
18592
18695
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
18593
18696
|
}
|
|
18594
|
-
`;function
|
|
18697
|
+
`;function ad(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 nd(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var rd=`
|
|
18595
18698
|
body { height: 100dvh; }
|
|
18596
18699
|
main { min-height: 0; }
|
|
18597
18700
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -18701,7 +18804,7 @@ main { min-height: 0; }
|
|
|
18701
18804
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
18702
18805
|
}
|
|
18703
18806
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
18704
|
-
`;var
|
|
18807
|
+
`;var od=`
|
|
18705
18808
|
window.AXOrb = (function () {
|
|
18706
18809
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
18707
18810
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -18818,7 +18921,7 @@ window.AXOrb = (function () {
|
|
|
18818
18921
|
}
|
|
18819
18922
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
18820
18923
|
})();
|
|
18821
|
-
`;var
|
|
18924
|
+
`;var sd=`
|
|
18822
18925
|
window.AXVoiceIO = (function () {
|
|
18823
18926
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
18824
18927
|
var ac = null, playing = null;
|
|
@@ -18936,7 +19039,7 @@ window.AXVoiceIO = (function () {
|
|
|
18936
19039
|
|
|
18937
19040
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
18938
19041
|
})();
|
|
18939
|
-
`;var
|
|
19042
|
+
`;var id=`
|
|
18940
19043
|
(function () {
|
|
18941
19044
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
18942
19045
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -19149,7 +19252,7 @@ window.AXVoiceIO = (function () {
|
|
|
19149
19252
|
idle();
|
|
19150
19253
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
19151
19254
|
})();
|
|
19152
|
-
`;var
|
|
19255
|
+
`;var ld=`
|
|
19153
19256
|
.vx {
|
|
19154
19257
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
19155
19258
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -19185,7 +19288,7 @@ window.AXVoiceIO = (function () {
|
|
|
19185
19288
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
19186
19289
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
19187
19290
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
19188
|
-
`;var
|
|
19291
|
+
`;var dd=`
|
|
19189
19292
|
<main class="card">
|
|
19190
19293
|
<h1>This phone isn't paired</h1>
|
|
19191
19294
|
<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>
|
|
@@ -19199,7 +19302,7 @@ window.AXVoiceIO = (function () {
|
|
|
19199
19302
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
19200
19303
|
</form>
|
|
19201
19304
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
19202
|
-
</main>`,
|
|
19305
|
+
</main>`,cd=`
|
|
19203
19306
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
19204
19307
|
.pair-form label { font-weight: 600; }
|
|
19205
19308
|
.pair-form input {
|
|
@@ -19221,7 +19324,7 @@ window.AXVoiceIO = (function () {
|
|
|
19221
19324
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
19222
19325
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
19223
19326
|
}
|
|
19224
|
-
`,
|
|
19327
|
+
`,pd=`
|
|
19225
19328
|
(function () {
|
|
19226
19329
|
var form = document.getElementById('pair-form');
|
|
19227
19330
|
var input = document.getElementById('pair-code');
|
|
@@ -19313,7 +19416,7 @@ window.AXVoiceIO = (function () {
|
|
|
19313
19416
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
19314
19417
|
}
|
|
19315
19418
|
})();
|
|
19316
|
-
`;var
|
|
19419
|
+
`;var ud=`
|
|
19317
19420
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
19318
19421
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
19319
19422
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -19322,7 +19425,7 @@ window.AXVoiceIO = (function () {
|
|
|
19322
19425
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
19323
19426
|
</div>
|
|
19324
19427
|
<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>
|
|
19325
|
-
</div>`,
|
|
19428
|
+
</div>`,md=`
|
|
19326
19429
|
.pair-form .scan-btn {
|
|
19327
19430
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
19328
19431
|
}
|
|
@@ -19351,7 +19454,7 @@ window.AXVoiceIO = (function () {
|
|
|
19351
19454
|
}
|
|
19352
19455
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
19353
19456
|
body.scanning { overflow: hidden; }
|
|
19354
|
-
`,
|
|
19457
|
+
`,fd=`
|
|
19355
19458
|
(function () {
|
|
19356
19459
|
var openBtn = document.getElementById('scan-btn');
|
|
19357
19460
|
var box = document.getElementById('scan');
|
|
@@ -19576,7 +19679,7 @@ body.scanning { overflow: hidden; }
|
|
|
19576
19679
|
@keyframes cam-pulse { 50% { opacity: .3; } }
|
|
19577
19680
|
@media (prefers-reduced-motion: reduce) { .cam-live.is-stream .cam-dot { animation: none; } }
|
|
19578
19681
|
#cam-stream[aria-pressed="true"] { border-color: var(--ax-red); color: var(--ax-red-ink); }
|
|
19579
|
-
`;var
|
|
19682
|
+
`;var hd='<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>',gd=`
|
|
19580
19683
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
19581
19684
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
19582
19685
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -19605,7 +19708,7 @@ body.scanning { overflow: hidden; }
|
|
|
19605
19708
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
19606
19709
|
</div>
|
|
19607
19710
|
</div>
|
|
19608
|
-
</div>`,
|
|
19711
|
+
</div>`,xd=`
|
|
19609
19712
|
(function () {
|
|
19610
19713
|
var btn = document.getElementById('cam-btn');
|
|
19611
19714
|
var sheet = document.getElementById('cam');
|
|
@@ -20079,7 +20182,7 @@ body.scanning { overflow: hidden; }
|
|
|
20079
20182
|
});
|
|
20080
20183
|
window.addEventListener('pagehide', function () { stop(); });
|
|
20081
20184
|
})();
|
|
20082
|
-
`;var
|
|
20185
|
+
`;var bd=`
|
|
20083
20186
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
20084
20187
|
<div class="cam-askbar-text">
|
|
20085
20188
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -20089,7 +20192,7 @@ body.scanning { overflow: hidden; }
|
|
|
20089
20192
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
20090
20193
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
20091
20194
|
</div>
|
|
20092
|
-
</div>`,
|
|
20195
|
+
</div>`,vd=`
|
|
20093
20196
|
.cam-askbar[hidden] { display: none; }
|
|
20094
20197
|
.cam-askbar {
|
|
20095
20198
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -20104,7 +20207,7 @@ body.scanning { overflow: hidden; }
|
|
|
20104
20207
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
20105
20208
|
}
|
|
20106
20209
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
20107
|
-
`,
|
|
20210
|
+
`,yd=`
|
|
20108
20211
|
(function () {
|
|
20109
20212
|
var bar = document.getElementById('cam-ask-bar');
|
|
20110
20213
|
if (!bar) return;
|
|
@@ -20174,7 +20277,7 @@ body.scanning { overflow: hidden; }
|
|
|
20174
20277
|
setInterval(poll, 5000);
|
|
20175
20278
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
20176
20279
|
})();
|
|
20177
|
-
`;function
|
|
20280
|
+
`;function wd(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 kd(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 _d(t){return t>=400?"send":"listen"}function Sd(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var Ed=`
|
|
20178
20281
|
(function () {
|
|
20179
20282
|
var main = document.querySelector('main');
|
|
20180
20283
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
@@ -20293,7 +20396,7 @@ body.scanning { overflow: hidden; }
|
|
|
20293
20396
|
main.addEventListener('touchend', function () { end(false); });
|
|
20294
20397
|
main.addEventListener('touchcancel', function () { end(true); });
|
|
20295
20398
|
})();
|
|
20296
|
-
`,
|
|
20399
|
+
`,Td=`
|
|
20297
20400
|
main { position: relative; }
|
|
20298
20401
|
main.sw-on { overflow: hidden; }
|
|
20299
20402
|
.sw-on > [role=tabpanel] { will-change: transform; }
|
|
@@ -20304,8 +20407,8 @@ main > .sw-peek {
|
|
|
20304
20407
|
}
|
|
20305
20408
|
main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
|
|
20306
20409
|
@media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
|
|
20307
|
-
`;function
|
|
20308
|
-
${
|
|
20410
|
+
`;function Ad(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 Cd(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Id(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Md(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 gn=`
|
|
20411
|
+
${z({afterUnauthorized:$o})}
|
|
20309
20412
|
var CACHE = 'agentx-app-v3';
|
|
20310
20413
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
20311
20414
|
self.addEventListener('install', function (e) {
|
|
@@ -20396,7 +20499,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
20396
20499
|
return self.clients.openWindow(target);
|
|
20397
20500
|
}));
|
|
20398
20501
|
});
|
|
20399
|
-
`;var
|
|
20502
|
+
`;var ah="<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 xn(t){return`<meta charset="utf-8">
|
|
20400
20503
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
20401
20504
|
<meta name="theme-color" content="#2979FF">
|
|
20402
20505
|
<meta name="referrer" content="no-referrer">
|
|
@@ -20407,40 +20510,40 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
20407
20510
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
20408
20511
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
20409
20512
|
<title>${t}</title>
|
|
20410
|
-
${
|
|
20411
|
-
<style>${
|
|
20513
|
+
${ah}
|
|
20514
|
+
<style>${qe}${Bl}${sh}</style>`}var nh={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"},Ld=[{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 Rd(){let t=Ld.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="${nh[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=Ld.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
20412
20515
|
<h2>${a.label}</h2>
|
|
20413
20516
|
<p class="soon">${a.soon}</p>
|
|
20414
20517
|
</section>`).join("");return`<!doctype html>
|
|
20415
20518
|
<html lang="en">
|
|
20416
|
-
<head>${xn("AgentX")}<style>${
|
|
20519
|
+
<head>${xn("AgentX")}<style>${ih}${Ul}${rd}${td}${ld}${hn}${vd}${Td}${Xl}${ql}</style></head>
|
|
20417
20520
|
<body>
|
|
20418
20521
|
<header class="bar">
|
|
20419
20522
|
<div>
|
|
20420
20523
|
<h1>AgentX</h1>
|
|
20421
20524
|
<p id="who" class="who">Connecting\u2026</p>
|
|
20422
20525
|
</div>
|
|
20423
|
-
<div class="bar-btns">${
|
|
20526
|
+
<div class="bar-btns">${hd}<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>
|
|
20424
20527
|
</header>
|
|
20425
20528
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
20426
|
-
${
|
|
20529
|
+
${bd}
|
|
20427
20530
|
<main>${e}</main>
|
|
20428
20531
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
20429
|
-
${
|
|
20430
|
-
<script>${
|
|
20431
|
-
<script>${
|
|
20432
|
-
<script>${Bl}</script>
|
|
20532
|
+
${gd}
|
|
20533
|
+
<script>${rh}</script>
|
|
20534
|
+
<script>${z({swipeMayStart:Ad,swipeAxis:Cd,swipeOffset:Id,swipeLanding:Md})}${Ed}</script>
|
|
20433
20535
|
<script>${zl}</script>
|
|
20434
20536
|
<script>${Fl}</script>
|
|
20435
|
-
<script>${
|
|
20436
|
-
<script>${
|
|
20437
|
-
<script>${
|
|
20438
|
-
<script>${
|
|
20439
|
-
<script>${
|
|
20440
|
-
<script>${
|
|
20441
|
-
<script>${
|
|
20537
|
+
<script>${Wl}</script>
|
|
20538
|
+
<script>${z({locationErrorText:Kl})}${Gl}</script>
|
|
20539
|
+
<script>${Jl}</script>
|
|
20540
|
+
<script>${z({markdownToHtml:hr})}${Yl}${Zl}${Ql}${Vl}</script>
|
|
20541
|
+
<script>${z({queueSpeech:ad,nextSpeech:nd})}${od}${sd}${id}</script>
|
|
20542
|
+
<script>${ed}</script>
|
|
20543
|
+
<script>${z({cameraConstraints:wd,shareClock:kd,streamLabel:Sd,talkRelease:_d})}${xd}</script>
|
|
20544
|
+
<script>${yd}</script>
|
|
20442
20545
|
</body>
|
|
20443
|
-
</html>`}function
|
|
20546
|
+
</html>`}function Pd(){return`<!doctype html>
|
|
20444
20547
|
<html lang="en">
|
|
20445
20548
|
<head>${xn("Pair \xB7 AgentX")}</head>
|
|
20446
20549
|
<body>
|
|
@@ -20448,17 +20551,17 @@ ${fc}
|
|
|
20448
20551
|
<h1>Pairing this phone\u2026</h1>
|
|
20449
20552
|
<p id="msg" role="status">One moment.</p>
|
|
20450
20553
|
</main>
|
|
20451
|
-
<script>${
|
|
20554
|
+
<script>${oh}</script>
|
|
20452
20555
|
</body>
|
|
20453
|
-
</html>`}function
|
|
20556
|
+
</html>`}function $d(){return`<!doctype html>
|
|
20454
20557
|
<html lang="en">
|
|
20455
|
-
<head>${xn("Not paired \xB7 AgentX")}<style>${
|
|
20456
|
-
<body>${
|
|
20457
|
-
<script>${
|
|
20458
|
-
<script>${
|
|
20459
|
-
<script>${
|
|
20558
|
+
<head>${xn("Not paired \xB7 AgentX")}<style>${cd}${md}</style></head>
|
|
20559
|
+
<body>${dd}${ud}
|
|
20560
|
+
<script>${z({mayBounce:jo,formatPairInput:Ft,parsePairScan:Oo})}</script>
|
|
20561
|
+
<script>${pd}</script>
|
|
20562
|
+
<script>${fd}</script>
|
|
20460
20563
|
</body>
|
|
20461
|
-
</html>`}function
|
|
20564
|
+
</html>`}function jd(){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 rh=`
|
|
20462
20565
|
(function () {
|
|
20463
20566
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
20464
20567
|
function select(tab, focus, keepHash) {
|
|
@@ -20530,7 +20633,7 @@ ${fc}
|
|
|
20530
20633
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
20531
20634
|
}
|
|
20532
20635
|
})();
|
|
20533
|
-
`,
|
|
20636
|
+
`,oh=`
|
|
20534
20637
|
(function () {
|
|
20535
20638
|
var msg = document.getElementById('msg');
|
|
20536
20639
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -20547,7 +20650,7 @@ ${fc}
|
|
|
20547
20650
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
20548
20651
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
20549
20652
|
})();
|
|
20550
|
-
`,
|
|
20653
|
+
`,sh=`
|
|
20551
20654
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
20552
20655
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
20553
20656
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -20559,7 +20662,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
20559
20662
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
20560
20663
|
.muted { color: var(--ax-text-2); }
|
|
20561
20664
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
20562
|
-
`,
|
|
20665
|
+
`,ih=`
|
|
20563
20666
|
body { display: flex; flex-direction: column; }
|
|
20564
20667
|
.bar {
|
|
20565
20668
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -20597,8 +20700,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20597
20700
|
}
|
|
20598
20701
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
20599
20702
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
20600
|
-
`;var la="agentx_app",
|
|
20601
|
-
`;rt=Buffer.concat([Buffer.from(a),
|
|
20703
|
+
`;var la="agentx_app",ch=400*86400,ph=new At,uh=new Ie;async function Od(t,e,a,n,r={}){if(a==="/.well-known/assetlinks.json"&&n==="GET"){let i=r.assetLinks?.()??null;return i?me(e,200,"application/json",JSON.stringify(i),"public, max-age=300"):_e(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 me(e,200,"application/manifest+json",jd());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),me(e,200,"text/javascript; charset=utf-8",gn);if(a==="/app/icon-192.png")return me(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/app/icon-512.png")return me(e,200,"image/png",Fe(512),"public, max-age=86400");if(a==="/app/pair")return me(e,200,"text/html; charset=utf-8",Pd());if(a==="/app/qr.js"){let i=mh();return i?me(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):_e(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=bn(ot(t),o);return i?(e.setHeader("Set-Cookie",vn(ot(t))),_e(e,200,{device:i.name})):_e(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await fr(t,{codes:r.pairCodes??new kt,limiter:r.pairLimiter??ph,verify:l=>bn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",vn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),_e(e,i.status,i.body)}let s=bn(fh(t),o);if(!s){let i=ot(t);return(r.rejectLog??uh).record(a.slice(0,120),Bt(t,ze(yn(t,la),o),i?ze(i,o):null)),a==="/app"?me(e,401,"text/html; charset=utf-8",$d()):_e(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=yn(t,la);return i&&!ot(t)&&e.setHeader("Set-Cookie",vn(i)),me(e,200,"text/html; charset=utf-8",Rd())}return n==="GET"&&a==="/api/app/me"?_e(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await ir(t,e,a,n,s.name,r.fleet)||r.push&&await lr(t,e,a,n,s,r.push)||r.announce&&await tl(t,e,a,n,s,r.announce)||r.chat&&await ul(t,e,a,n,s,r.chat)||r.chat&&await gl(t,e,a,n,s,r.chat)||r.voice&&await vl(t,e,a,n,s,r.voice)||r.camera&&await wl(t,e,a,n,r.camera)||r.places&&await jl(t,e,a,n,s,r.places)?!0:_e(e,404,{error:"not found"})}var rt;function mh(){if(rt!==void 0)return rt;try{let t=dh(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
20704
|
+
`;rt=Buffer.concat([Buffer.from(a),lh(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),rt=null}return rt}function bn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ee(a,"app")?a:null}function vn(t){return`${la}=${t}; Path=/; Max-Age=${ch}; HttpOnly; Secure; SameSite=Lax`}function fh(t){return ot(t)??yn(t,la)}function ot(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function yn(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 me(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 me(t,e,"application/json",JSON.stringify(a))}function Nd(t){let e=pe({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."})+`
|
|
20602
20705
|
<div class="pl-wrap">
|
|
20603
20706
|
<div id="pl-msg" class="pl-msg" role="status" aria-live="polite"></div>
|
|
20604
20707
|
<form id="pl-add" class="pl-form" autocomplete="off">
|
|
@@ -20610,7 +20713,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20610
20713
|
<button type="submit" class="ax-btn ax-btn--primary">Add place</button>
|
|
20611
20714
|
</form>
|
|
20612
20715
|
<ol id="pl-list" class="pl-list" aria-label="Places"><li class="pl-empty">Loading\u2026</li></ol>
|
|
20613
|
-
</div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:
|
|
20716
|
+
</div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:hh,scripts:`<script>${gh}</script>`})}var hh=`
|
|
20614
20717
|
.pl-wrap { max-width: 1040px; margin: 0 auto; padding: 0 24px 96px; box-sizing: border-box; }
|
|
20615
20718
|
.pl-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
20616
20719
|
.pl-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -20633,7 +20736,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20633
20736
|
.pl-rule-form { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
20634
20737
|
.pl-rule-form input[name=text] { flex: 1 1 240px; }
|
|
20635
20738
|
.pl-btns { margin-left: auto; display: flex; gap: 8px; }
|
|
20636
|
-
`,
|
|
20739
|
+
`,gh=`
|
|
20637
20740
|
(function () {
|
|
20638
20741
|
var list = document.getElementById('pl-list');
|
|
20639
20742
|
var msg = document.getElementById('pl-msg');
|
|
@@ -20712,7 +20815,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20712
20815
|
});
|
|
20713
20816
|
load();
|
|
20714
20817
|
})();
|
|
20715
|
-
`;import{randomBytes as
|
|
20818
|
+
`;import{randomBytes as Dd}from"crypto";var He={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ce.perMessage},xh=/^[a-f0-9]{32}$/,bh=/^c[a-z0-9]{8,32}$/,vh=/^#[0-9a-fA-F]{6}$/;function wn(t){return bh.test(t)}var st=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
20716
20819
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
20717
20820
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
20718
20821
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -20725,39 +20828,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
20725
20828
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
20726
20829
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
20727
20830
|
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 (
|
|
20728
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return wn(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)}${
|
|
20729
|
-
(id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,
|
|
20831
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return wn(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)}${Dd(4).toString("hex")}`,{color:s,...i}=a,l=s&&vh.test(s)?s:void 0,d={id:o,title:wh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
20832
|
+
(id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,d.title,d.node,d.nodeName,d.agent,d.agentName??null,l??null,r,r,r),this.pruneDevice(e),d}get(e,a){if(!wn(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(yh);return{...Hd(n),messages:r}}list(e,a=He.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
20730
20833
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
20731
20834
|
(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
|
|
20732
|
-
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{...
|
|
20835
|
+
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{...Hd(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){wn(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,
|
|
20733
20836
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
20734
20837
|
FROM app_chat_conversations c
|
|
20735
20838
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
20736
20839
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
20737
20840
|
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>He.content?n.content.slice(0,He.content)+`
|
|
20738
20841
|
|
|
20739
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,He.toolsPerMessage),l=[];for(let m of r){if(l.length>=He.filesPerMessage)break;let g=m.filename.trim(),_=Yn(g);if(!_||!g||g.length>
|
|
20740
|
-
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,
|
|
20741
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)p.run(m.id,a,Number(
|
|
20842
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,He.toolsPerMessage),l=[];for(let m of r){if(l.length>=He.filesPerMessage)break;let g=m.filename.trim(),_=Yn(g);if(!_||!g||g.length>ce.pathChars||g.includes("\0"))continue;let y=(g.split(/[\\/]/).pop()||g).slice(0,120);l.push({id:Dd(16).toString("hex"),name:y,mime:_.mime,kind:_.kind,path:g})}let d=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),c=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
20843
|
+
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,d.length?JSON.stringify(d):null,n.at),p=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
|
|
20844
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)p.run(m.id,a,Number(c.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
|
|
20742
20845
|
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,He.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
|
|
20743
|
-
(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),
|
|
20846
|
+
(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),d}getFile(e,a){if(!xh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
20744
20847
|
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 = ?
|
|
20745
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,He.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
|
|
20848
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,He.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 Hd(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 yh(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 wh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var kh=4e3,kn=100,_h=15,Bd=t=>t.replace(/\/+$/,""),da=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=kh){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,kn);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??_h)-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>=kn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${kn}); 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||Bd(l)!==Bd(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 d=Sh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,d.row,d.declared)===null)return"skip";let p=d.row.status,m=!!this.deps.finishAlerts?.(s),g={status:p,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&oa(g)&&this.deps.notifyFinish(sa(s,i,p,d.row.content,d.row.error)).catch(()=>{}),"filed"}};function Sh(t,e){let a=t.plain?{text:xt(t.text,!1),artifacts:[]}:gt(t.text,ce.perMessage,!1),{cleanText:n,ui:r}=vt(a.text),o=t.plain?void 0:ln(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Eh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Eh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}On();function Ve(){let t=ut();return t&&ke(t,"dashboard"),t}function U0(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let g of a)try{s.set(g.id,Nh(g,t))}catch(_){console.error(` Board "${g.id}" failed to initialize: ${_.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?it(process.cwd(),t.workflows.dir):void 0,d=new Wn(l?{baseDir:l}:void 0),c=new Gn(l?{baseDir:l,nodeId:i}:{nodeId:i}),p=new Xn(l?{baseDir:l}:void 0);vi(t),Ve(),kr({business:t.business?.enabled===!0});let m=Th(async(g,_)=>{try{await Ph(g,_,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:c,workflowLayouts:p})}catch(y){w(_,500,{error:y.message||"internal error"})}});eg(t).start(),m.listen(n,r,()=>{let g=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
20746
20849
|
Live dashboard: http://${g}:${n}
|
|
20747
20850
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
20748
20851
|
Kanban dashboard: http://${g}:${n}
|
|
20749
|
-
`),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 Mh=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 Lh(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){w(e,404,{error:"not found"});return}if(yr(t.headers)==="foreign"&&wr(o)){w(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await rs(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>tt(a.config.people),members:Bc(a.config.members.logRetentionDays),db:()=>Ve(),linkFor:(u,f)=>To(u,f,{gitlab:a.config.channels.gitlab?.host})})||await $c(t,e,r,o,{nodeName:a.config.node?.name,fleet:Wc(a.config),push:An(a.config),announce:el(a.config),chat:Gc(a.config),voice:Zh(a.config),camera:eg(a.config),places:Hc(a.config),assetLinks:()=>Nl(a.config)}))return;let s=o==="GET"?_o(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"&&Mh.has(r)&&to("page",r),o==="GET"&&r==="/"){let u=zr();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(on({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fi({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(on({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Se(a.config);if(!u){w(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let E="";t.on("data",x=>E+=x),t.on("end",()=>v(E)),t.on("error",()=>v(""))}),y=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:f||"{}"});e.writeHead(y.status,{"Content-Type":"application/json"}),e.end(await y.text())}catch(u){w(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 Se(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),y=o==="POST"?await le(t):void 0,v=y?.node??f,E=v?u.find(R=>R.url===v):u[0];if(!E){w(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(E.url+r+x,{method:o,headers:{"Content-Type":"application/json",...E.token?{Authorization:`Bearer ${E.token}`}:{}},...o==="POST"?{body:JSON.stringify({...y,node:void 0})}:{}});w(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){w(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 le(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let y=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${y}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Se(a.config);if(!u){w(e,200,{configured:!1,workflows:[]});return}let f=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});w(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{w(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fo({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mo({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(lo({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,f=setTimeout(()=>u.abort(),8e3);try{let y=Zn(await Se(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(y.map(async k=>{try{let L=await fetch(k.url+"/monitor",{headers:k.token?{Authorization:`Bearer ${k.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:k.name,url:k.url,ok:!0,data:await L.json()}}catch(L){return{name:k.name,url:k.url,ok:!1,error:L.message}}}));w(e,200,{nodes:R});return}let v=y.find(R=>R.url===n.searchParams.get("node"));if(!v){w(e,400,{error:"Select a known node"});return}let E=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(E)||o==="POST"&&["register","ended","action","retry","clear"].includes(E))){w(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Qn(t)):void 0,A=await fetch(v.url+"/monitor/"+E+(E==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):E==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:u.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});w(e,A.status,await A.json())}catch(y){w(e,502,{error:y.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Di({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(jc({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hi({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 f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=o==="POST"?await le(t).catch(()=>({})):void 0,v=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...y!==void 0?{body:JSON.stringify(y??{})}:{}});w(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(u){w(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(Ui({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gi({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Br({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",f=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(Xi({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:f,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(Ki({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"){qr(t,e);return}if(o==="POST"&&r==="/api/setup"){await Fr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ur(t,e);return}if(o==="GET"&&r==="/admin"){hs(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Rs(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){_s(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}qs(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 sg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await nn(t,e,r,y=>Kc(y,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let y=decodeURIComponent(f[1]),v=y.indexOf("::");if(v>0){let E=y.slice(0,v),x=y.slice(v+2),A=a.config.node?.id||a.config.node?.name||"local";if(E===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let R=(a.config.dashboard?.daemons||[]).find(k=>(k.name||k.url)===E);if(R){let k=lt(R.url.replace(/\/+$/,""),a.config);if(k){await qc(t,e,k,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}w(e,404,{error:`unknown node "${E}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let f=lt(u,a.config);if(!f){w(e,404,{error:`unknown peer: ${u}`});return}let y=(n.search||"").replace(/[?&]peer=[^&]*/g,E=>E.startsWith("?")?"?":"");await qc(t,e,f,r+(y==="?"?"":y));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Fs(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await ig(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-NBWYG743.js"),y=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await u({running:y});w(e,200,v)}catch(u){w(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(Xs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Gs(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ks({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Js({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 Dh(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 bi(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await nn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await yi(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){_i(t,e,d[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let y=new G,v=f?y.verify(f):null;if(!v||!Ee(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await gs(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,Er()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Ps(t,e,r,n);return}if(await js(t,e,r,{people:()=>tt(a.config.people),members:Bc(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ve(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Ss(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Si(t,e,r);return}if(r.startsWith("/api/admin/")){await xs(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(os);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){w(e,400,{error:"invalid asset name"});return}let f=rg("web/"+u);try{let y=await og(f),v=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",E=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":E?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(y)}catch{w(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Ye(a.config);w(e,200,u)}catch(u){w(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),f=n.searchParams.get("timezone")||"UTC",y=await Ye(a.config,{date:u,timezone:f});w(e,200,y)}catch(u){w(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(f,y,v,E)=>{let x=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(x)?Math.max(v,Math.min(E,x)):y};try{let f=await Se(a.config);w(e,200,await Bi(f,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(f){w(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){w(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(y,v,E,x)=>{let A=parseInt(n.searchParams.get(y)||"",10);return Number.isFinite(A)?Math.max(E,Math.min(x,A)):v};try{let y=await Se(a.config);w(e,200,await qi(y,{day:u,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(y){w(e,502,{error:y.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){w(e,400,{error:"node query param required"});return}let f=n.searchParams,y;if(r==="/api/mesh/thread"){let[v,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}y=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,E]=[f.get("kind"),f.get("key")];if(!v||!E){w(e,400,{error:"kind and key required"});return}y=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(E)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}y=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){w(e,400,{error:"task required"});return}y=`/analytics/run/${encodeURIComponent(v)}`}try{await zi(e,await Se(a.config),u,y)}catch(v){w(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Wh(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),y=u.searchParams.get("agent"),v=u.searchParams.get("task");if(!f||!y||!v){w(e,400,{error:"node, agent, task query params required"});return}await Gh(t,e,a,f,y,v);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),y=u.searchParams.get("agent"),v=u.searchParams.get("task"),E=u.searchParams.get("limit")||"50";if(!f||!y){w(e,400,{error:"node and agent query params required"});return}await Jh(e,a,f,y,v,E);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),y=u.searchParams.get("task"),v=u.searchParams.get("kind");if(!f||!y||v!=="cancel"&&v!=="followup"){w(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Vh(t,e,a,f,y,v);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!f.ok)throw new Error(`HTTP ${f.status}`);let y=await f.json();w(e,200,y)}catch(u){w(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!f.ok){w(e,f.status,{error:`HTTP ${f.status}`});return}w(e,200,await f.json())}catch(u){w(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await le(t);try{let f=await ag(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!Xh(t,e,[`agent:${u}`]))return;await Kh(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);w(e,200,Sr(await f.json()))}catch(u){w(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let y=new G,v=f?y.verify(f):null;if(!v||!Ee(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Hh(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){w(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(r==="/api/wiki/curate"||r==="/api/wiki/curate/restore"){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=o==="POST"?JSON.stringify(await le(t)??{}):void 0,v=await fetch(`${f}${r}${n.search}`,{method:o,headers:u,...y?{body:y}:{}});w(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(u){w(e,502,{error:"daemon unreachable",message:u?.message||String(u)})}return}if(await $l(t,e,r,o,Hc(a.config)))return;if(o==="POST"&&(r==="/api/signals/stop"||r==="/api/signals/resume")){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,r);return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let y=[{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}))],v={flag:!1},E=[];t.on("close",()=>{v.flag=!0;for(let A of E)try{A.abort()}catch{}});let x=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
20852
|
+
`),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 Rh=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 Ph(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){w(e,404,{error:"not found"});return}if(yr(t.headers)==="foreign"&&wr(o)){w(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ss(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>tt(a.config.people),members:zd(a.config.members.logRetentionDays),db:()=>Ve(),linkFor:(u,f)=>Co(u,f,{gitlab:a.config.channels.gitlab?.host})})||await Od(t,e,r,o,{nodeName:a.config.node?.name,fleet:Xd(a.config),push:An(a.config),announce:al(a.config),chat:Kd(a.config),voice:tg(a.config),camera:ag(a.config),places:qd(a.config),assetLinks:()=>Hl(a.config)}))return;let s=o==="GET"?Eo(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"&&Rh.has(r)&&to("page",r),o==="GET"&&r==="/"){let u=qr();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(on({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wi({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(on({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Se(a.config);if(!u){w(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let E="";t.on("data",x=>E+=x),t.on("end",()=>v(E)),t.on("error",()=>v(""))}),b=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:f||"{}"});e.writeHead(b.status,{"Content-Type":"application/json"}),e.end(await b.text())}catch(u){w(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 Se(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),b=o==="POST"?await re(t):void 0,v=b?.node??f,E=v?u.find(R=>R.url===v):u[0];if(!E){w(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(E.url+r+x,{method:o,headers:{"Content-Type":"application/json",...E.token?{Authorization:`Bearer ${E.token}`}:{}},...o==="POST"?{body:JSON.stringify({...b,node:void 0})}:{}});w(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){w(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 re(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let b=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${b}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Se(a.config);if(!u){w(e,200,{configured:!1,workflows:[]});return}let f=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});w(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{w(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(go({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ho({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(po({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,f=setTimeout(()=>u.abort(),8e3);try{let b=Zn(await Se(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(b.map(async k=>{try{let L=await fetch(k.url+"/monitor",{headers:k.token?{Authorization:`Bearer ${k.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:k.name,url:k.url,ok:!0,data:await L.json()}}catch(L){return{name:k.name,url:k.url,ok:!1,error:L.message}}}));w(e,200,{nodes:R});return}let v=b.find(R=>R.url===n.searchParams.get("node"));if(!v){w(e,400,{error:"Select a known node"});return}let E=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(E)||o==="POST"&&["register","ended","action","retry","clear"].includes(E))){w(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Qn(t)):void 0,A=await fetch(v.url+"/monitor/"+E+(E==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):E==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:u.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});w(e,A.status,await A.json())}catch(b){w(e,502,{error:b.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bi({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nd({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qi({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 f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=o==="POST"?await re(t).catch(()=>({})):void 0,v=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...b!==void 0?{body:JSON.stringify(b??{})}:{}});w(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(u){w(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(Gi({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ki({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Br({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",f=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(Ji({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:f,peers:D(a.config)}));return}let d=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(d){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vi({agentId:decodeURIComponent(d[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"){zr(t,e);return}if(o==="POST"&&r==="/api/setup"){await Fr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ur(t,e);return}if(o==="GET"&&r==="/admin"){xs(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"){Es(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}Us(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 lg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await nn(t,e,r,b=>Vd(b,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let b=decodeURIComponent(f[1]),v=b.indexOf("::");if(v>0){let E=b.slice(0,v),x=b.slice(v+2),A=a.config.node?.id||a.config.node?.name||"local";if(E===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let R=(a.config.dashboard?.daemons||[]).find(k=>(k.name||k.url)===E);if(R){let k=lt(R.url.replace(/\/+$/,""),a.config);if(k){await Ud(t,e,k,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}w(e,404,{error:`unknown node "${E}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let f=lt(u,a.config);if(!f){w(e,404,{error:`unknown peer: ${u}`});return}let b=(n.search||"").replace(/[?&]peer=[^&]*/g,E=>E.startsWith("?")?"?":"");await Ud(t,e,f,r+(b==="?"?"":b));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ws(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await dg(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-ROKIYJRT.js"),b=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await u({running:b});w(e,200,v)}catch(u){w(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(Js({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Ks(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vs({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ys({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 Bh(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 yi(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await nn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ki(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Ei(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let b=new G,v=f?b.verify(f):null;if(!v||!Ee(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await bs(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,Er()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await js(t,e,r,n);return}if(await Ns(t,e,r,{people:()=>tt(a.config.people),members:zd(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ve(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Ts(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Ti(t,e,r);return}if(r.startsWith("/api/admin/")){await vs(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(is);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){w(e,400,{error:"invalid asset name"});return}let f=sg("web/"+u);try{let b=await ig(f),v=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",E=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":E?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(b)}catch{w(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Ye(a.config);w(e,200,u)}catch(u){w(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),f=n.searchParams.get("timezone")||"UTC",b=await Ye(a.config,{date:u,timezone:f});w(e,200,b)}catch(u){w(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(f,b,v,E)=>{let x=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(x)?Math.max(v,Math.min(E,x)):b};try{let f=await Se(a.config);w(e,200,await zi(f,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(f){w(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){w(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(b,v,E,x)=>{let A=parseInt(n.searchParams.get(b)||"",10);return Number.isFinite(A)?Math.max(E,Math.min(x,A)):v};try{let b=await Se(a.config);w(e,200,await Ui(b,{day:u,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(b){w(e,502,{error:b.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){w(e,400,{error:"node query param required"});return}let f=n.searchParams,b;if(r==="/api/mesh/thread"){let[v,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}b=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,E]=[f.get("kind"),f.get("key")];if(!v||!E){w(e,400,{error:"kind and key required"});return}b=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(E)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}b=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){w(e,400,{error:"task required"});return}b=`/analytics/run/${encodeURIComponent(v)}`}try{await Fi(e,await Se(a.config),u,b)}catch(v){w(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Xh(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),b=u.searchParams.get("agent"),v=u.searchParams.get("task");if(!f||!b||!v){w(e,400,{error:"node, agent, task query params required"});return}await Kh(t,e,a,f,b,v);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),b=u.searchParams.get("agent"),v=u.searchParams.get("task"),E=u.searchParams.get("limit")||"50";if(!f||!b){w(e,400,{error:"node and agent query params required"});return}await Yh(e,a,f,b,v,E);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),b=u.searchParams.get("task"),v=u.searchParams.get("kind");if(!f||!b||v!=="cancel"&&v!=="followup"){w(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Qh(t,e,a,f,b,v);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!f.ok)throw new Error(`HTTP ${f.status}`);let b=await f.json();w(e,200,b)}catch(u){w(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!f.ok){w(e,f.status,{error:`HTTP ${f.status}`});return}w(e,200,await f.json())}catch(u){w(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await re(t);try{let f=await rg(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!Jh(t,e,[`agent:${u}`]))return;await Vh(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);w(e,200,Sr(await f.json()))}catch(u){w(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let b=new G,v=f?b.verify(f):null;if(!v||!Ee(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await qh(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){w(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(r==="/api/wiki/curate"||r==="/api/wiki/curate/restore"){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=o==="POST"?JSON.stringify(await re(t)??{}):void 0,v=await fetch(`${f}${r}${n.search}`,{method:o,headers:u,...b?{body:b}:{}});w(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(u){w(e,502,{error:"daemon unreachable",message:u?.message||String(u)})}return}if(await Ol(t,e,r,o,qd(a.config)))return;if(o==="POST"&&(r==="/api/signals/stop"||r==="/api/signals/resume")){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,r);return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let b=[{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}))],v={flag:!1},E=[];t.on("close",()=>{v.flag=!0;for(let A of E)try{A.abort()}catch{}});let x=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
20750
20853
|
|
|
20751
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let A of
|
|
20854
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let A of b)(async()=>{let R={Accept:"text/event-stream"};A.token&&(R.Authorization=`Bearer ${A.token}`);let k=new AbortController;E.push(k);try{let L=await fetch(`${A.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:R,signal:k.signal});if(!L.ok||!L.body)return;let j=L.body.getReader(),$=new TextDecoder,O="";for(;!v.flag;){let{done:W,value:de}=await j.read();if(W)break;O+=$.decode(de,{stream:!0});let Q;for(;(Q=O.indexOf(`
|
|
20752
20855
|
|
|
20753
|
-
`))>=0;){let
|
|
20856
|
+
`))>=0;){let oe=O.slice(0,Q);if(O=O.slice(Q+2),v.flag)break;try{e.write(oe+`
|
|
20754
20857
|
|
|
20755
|
-
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/follow-ups"){let u=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))],f=[],y=await Promise.all(u.map(async x=>{let A={};x.token&&(A.Authorization=`Bearer ${x.token}`);try{let R=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs?limit=500&summary=1`,{headers:A,signal:AbortSignal.timeout(5e3)});if(!R.ok)return f.push(x.url),[];let k=await R.json();return Array.isArray(k.runs)?k.runs:[]}catch{return f.push(x.url),[]}})),v=new Map;for(let x of a.workflowRuns.list({limit:500}))v.set(x.id,x);for(let x of y)for(let A of x)v.set(A.id,{...A,history:A.history??[],pending:A.pending??[]});let E=new Map(a.workflowStore.list().map(x=>[x.id,x.title]));w(e,200,{groups:Vn([...v.values()],x=>E.get(x)),unreachable:f});return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),y=u.searchParams.get("workflowId")||void 0,v=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",E=a.workflowRuns.list({limit:f,workflowId:y}),x=`?limit=${f}${y?`&workflowId=${encodeURIComponent(y)}`:""}${v?"&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 W=new AbortController,ce=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let re=await Q.json();return Array.isArray(re.runs)?re.runs:[]}finally{clearTimeout(ce)}}catch{return[]}})),k=new Map;for(let $ of E)k.set($.id,$);for(let $ of R)for(let O of $)k.set(O.id,O);let L=Array.from(k.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,f),j=v?L.map($=>$h($)):L;w(e,200,{runs:j})}catch(u){w(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let g=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(g){let u=decodeURIComponent(g[1]),f=a.workflowRuns.get(u);if(f){w(e,200,{run:f});return}let y=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of y)try{let E={};v.token&&(E.Authorization=`Bearer ${v.token}`);let x=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:E});if(x.ok){w(e,200,await x.json());return}}catch{}w(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 f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${f}/api/actions/builtin`,{headers:u}),v=await y.json().catch(()=>({error:`HTTP ${y.status}`}));w(e,y.status,v)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let _=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(_){try{let u=await le(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let y=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${y}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(r.startsWith("/api/workflows")&&Vi(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,y,v)=>{if(a.token)return!0;let E=Sa(f);if(!E)return!0;let x=new G().verify(E);if(!x)return w(y,401,{error:"invalid or revoked token"}),!1;for(let A of v)if(!Ee(x,A))return w(y,403,{error:`token missing scope: ${A}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){w(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){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMembers=="function"?await u.listMembers():[];w(e,200,f)}catch(f){w(e,502,{error:f.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){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMilestones=="function"?await u.listMilestones():[];w(e,200,f)}catch(f){w(e,502,{error:f.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),h=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(T&&o==="PATCH"){let[,u,f]=T,y=decodeURIComponent(f),v=a.boards.find(k=>k.id===u);if(!v){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}let x=await le(t),A=v.columns.find(k=>k.id===x.to),R=v.columns.find(k=>k.id===x.from);if(!A){w(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await Ph(E,y,R,A),_n({actor:Sn(t),action:"move",boardId:u,itemId:y,payload:{from:x.from,to:x.to}}),w(e,200,{ok:!0})}catch(k){w(e,502,{error:k.message||"transition failed"})}return}if(h){let[,u,f]=h,y=f?decodeURIComponent(f):void 0,v=a.boards.find(x=>x.id===u);if(!v){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!y){let{columns:x,totals:A}=await Rh(v,E,n.searchParams);w(e,200,{columns:x,totals:A});return}if(o==="GET"&&y){try{let x=typeof E.getItem=="function"?await E.getItem(y):null;if(!x){w(e,404,{error:"not found"});return}w(e,200,x)}catch(x){w(e,502,{error:x.message})}return}if(o==="PATCH"&&y){let x=await le(t);try{let A=typeof E.updateItem=="function"?await E.updateItem(y,x):null;if(!A){w(e,501,{error:"update unsupported"});return}_n({actor:Sn(t),action:"update",boardId:u,itemId:y,payload:x}),w(e,200,A)}catch(A){w(e,502,{error:A.message})}return}if(o==="POST"&&!y){let x=await le(t);if(!x.title){w(e,400,{error:"title required"});return}if(!E.capabilities.create||!E.create){w(e,400,{error:`source ${E.type} does not support create`});return}try{let A=await E.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});_n({actor:Sn(t),action:"create",boardId:u,itemId:A.id,payload:{title:x.title}}),w(e,201,A)}catch(A){w(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),y={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(y){e.writeHead(302,{Location:y}),e.end();return}}w(e,404,{error:"not found",path:r})}async function Rh(t,e,a){if(!e.capabilities.listAll||!e.listAll){let h={};for(let u of t.columns)h[u.id]=[];return{columns:h,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(h=>h.kind!=="closed"),p=t.columns.some(h=>h.kind==="closed"),m=d?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],g=p?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let h of t.columns)_[h.id]=[];let b=t.columns.find(h=>h.kind==="closed");for(let h of g)b&&_[b.id].push({...h,stage:b.id});let S=t.columns.filter(h=>h.kind!=="closed");for(let h of m){let u=Mn(h,S);if(!u)continue;let f=_[u];f&&f.push({...h,stage:u})}if(i)for(let h of Object.keys(_))_[h]=_[h].filter(u=>u.assignee===i);for(let h of Object.keys(_))_[h].sort((u,f)=>{let y=(u.priority??99)-(f.priority??99);return y!==0?y:(f.updatedAt||"").localeCompare(u.updatedAt||"")});let T=Object.fromEntries(Object.entries(_).map(([h,u])=>[h,u.length]));return{columns:_,totals:T}}async function Ph(t,e,a,n){let r=Ln(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 $h(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,...t.meta?{meta:t.meta}:{},...t.pausedAt?{pausedAt:Jn(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function jh(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 Mr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function _n(t){try{let e=it(process.cwd(),".agentx");Fc(e)||Th(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
20756
|
-
`;
|
|
20757
|
-
data: ${JSON.stringify(
|
|
20858
|
+
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/follow-ups"){let u=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))],f=[],b=await Promise.all(u.map(async x=>{let A={};x.token&&(A.Authorization=`Bearer ${x.token}`);try{let R=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs?limit=500&summary=1`,{headers:A,signal:AbortSignal.timeout(5e3)});if(!R.ok)return f.push(x.url),[];let k=await R.json();return Array.isArray(k.runs)?k.runs:[]}catch{return f.push(x.url),[]}})),v=new Map;for(let x of a.workflowRuns.list({limit:500}))v.set(x.id,x);for(let x of b)for(let A of x)v.set(A.id,{...A,history:A.history??[],pending:A.pending??[]});let E=new Map(a.workflowStore.list().map(x=>[x.id,x.title]));w(e,200,{groups:Vn([...v.values()],x=>E.get(x)),unreachable:f});return}if(r==="/api/workflows/required"){let u=()=>({settings:io(),agents:Object.keys(a.config.agents??{}).sort()});if(o==="GET"){w(e,200,u());return}if(o!=="POST"){w(e,405,{error:"Method not allowed"});return}if(a.config.workflows?.editor!=="edit"){w(e,403,{error:"the workflow editor is read-only on this node (workflows.editor)"});return}let f=await re(t).catch(()=>({})),b={};if(typeof f.enabled=="boolean"&&(b.enabled=f.enabled),typeof f.exemptQuestions=="boolean"&&(b.exemptQuestions=f.exemptQuestions),typeof f.agentId=="string"&&f.agentId){if(!Object.prototype.hasOwnProperty.call(a.config.agents??{},f.agentId)){w(e,400,{error:`no agent "${f.agentId}" on this node`});return}let E=f.agentRequired;if(E!=="on"&&E!=="off"&&E!=="default"){w(e,400,{error:"agentRequired is on, off or default"});return}b.agent={id:f.agentId,value:E==="default"?null:E==="on"}}if(b.enabled===void 0&&b.exemptQuestions===void 0&&!b.agent){w(e,400,{error:"nothing to change"});return}let v=await lo(b);if(!v.success){w(e,400,{error:v.error});return}w(e,200,{ok:!0,reloaded:!!v.reloaded,...u()});return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),b=u.searchParams.get("workflowId")||void 0,v=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",E=a.workflowRuns.list({limit:f,workflowId:b}),x=`?limit=${f}${b?`&workflowId=${encodeURIComponent(b)}`:""}${v?"&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 W=new AbortController,de=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let oe=await Q.json();return Array.isArray(oe.runs)?oe.runs:[]}finally{clearTimeout(de)}}catch{return[]}})),k=new Map;for(let $ of E)k.set($.id,$);for(let $ of R)for(let O of $)k.set(O.id,O);let L=Array.from(k.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,f),j=v?L.map($=>Oh($)):L;w(e,200,{runs:j})}catch(u){w(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let g=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(g){let u=decodeURIComponent(g[1]),f=a.workflowRuns.get(u);if(f){w(e,200,{run:f});return}let b=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of b)try{let E={};v.token&&(E.Authorization=`Bearer ${v.token}`);let x=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:E});if(x.ok){w(e,200,await x.json());return}}catch{}w(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 f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${f}/api/actions/builtin`,{headers:u}),v=await b.json().catch(()=>({error:`HTTP ${b.status}`}));w(e,b.status,v)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let _=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(_){try{let u=await re(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let b=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${b}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,E)}catch(u){w(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:(f,b,v)=>{if(a.token)return!0;let E=Sa(f);if(!E)return!0;let x=new G().verify(E);if(!x)return w(b,401,{error:"invalid or revoked token"}),!1;for(let A of v)if(!Ee(x,A))return w(b,403,{error:`token missing scope: ${A}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){w(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 y=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(y&&o==="GET"){let u=a.sources.get(y[1]);if(!u){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMembers=="function"?await u.listMembers():[];w(e,200,f)}catch(f){w(e,502,{error:f.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){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMilestones=="function"?await u.listMilestones():[];w(e,200,f)}catch(f){w(e,502,{error:f.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),h=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(T&&o==="PATCH"){let[,u,f]=T,b=decodeURIComponent(f),v=a.boards.find(k=>k.id===u);if(!v){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}let x=await re(t),A=v.columns.find(k=>k.id===x.to),R=v.columns.find(k=>k.id===x.from);if(!A){w(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await jh(E,b,R,A),_n({actor:Sn(t),action:"move",boardId:u,itemId:b,payload:{from:x.from,to:x.to}}),w(e,200,{ok:!0})}catch(k){w(e,502,{error:k.message||"transition failed"})}return}if(h){let[,u,f]=h,b=f?decodeURIComponent(f):void 0,v=a.boards.find(x=>x.id===u);if(!v){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!b){let{columns:x,totals:A}=await $h(v,E,n.searchParams);w(e,200,{columns:x,totals:A});return}if(o==="GET"&&b){try{let x=typeof E.getItem=="function"?await E.getItem(b):null;if(!x){w(e,404,{error:"not found"});return}w(e,200,x)}catch(x){w(e,502,{error:x.message})}return}if(o==="PATCH"&&b){let x=await re(t);try{let A=typeof E.updateItem=="function"?await E.updateItem(b,x):null;if(!A){w(e,501,{error:"update unsupported"});return}_n({actor:Sn(t),action:"update",boardId:u,itemId:b,payload:x}),w(e,200,A)}catch(A){w(e,502,{error:A.message})}return}if(o==="POST"&&!b){let x=await re(t);if(!x.title){w(e,400,{error:"title required"});return}if(!E.capabilities.create||!E.create){w(e,400,{error:`source ${E.type} does not support create`});return}try{let A=await E.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});_n({actor:Sn(t),action:"create",boardId:u,itemId:A.id,payload:{title:x.title}}),w(e,201,A)}catch(A){w(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),b={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(b){e.writeHead(302,{Location:b}),e.end();return}}w(e,404,{error:"not found",path:r})}async function $h(t,e,a){if(!e.capabilities.listAll||!e.listAll){let h={};for(let u of t.columns)h[u.id]=[];return{columns:h,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),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),c=t.columns.some(h=>h.kind!=="closed"),p=t.columns.some(h=>h.kind==="closed"),m=c?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],g=p?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let h of t.columns)_[h.id]=[];let y=t.columns.find(h=>h.kind==="closed");for(let h of g)y&&_[y.id].push({...h,stage:y.id});let S=t.columns.filter(h=>h.kind!=="closed");for(let h of m){let u=Mn(h,S);if(!u)continue;let f=_[u];f&&f.push({...h,stage:u})}if(i)for(let h of Object.keys(_))_[h]=_[h].filter(u=>u.assignee===i);for(let h of Object.keys(_))_[h].sort((u,f)=>{let b=(u.priority??99)-(f.priority??99);return b!==0?b:(f.updatedAt||"").localeCompare(u.updatedAt||"")});let T=Object.fromEntries(Object.entries(_).map(([h,u])=>[h,u.length]));return{columns:_,totals:T}}async function jh(t,e,a,n){let r=Ln(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 Oh(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,...t.meta?{meta:t.meta}:{},...t.pausedAt?{pausedAt:Jn(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function Nh(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 Mr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function _n(t){try{let e=it(process.cwd(),".agentx");Wd(e)||Ch(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
20859
|
+
`;Ah(it(e,"board-audit.jsonl"),a)}catch{}}function Sn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Dh=2e3;async function Hh(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=h=>{let u=new AbortController,f=setTimeout(()=>u.abort(),Dh),b=()=>u.abort();return a?.addEventListener("abort",b,{once:!0}),fetch(t+h,{headers:r,signal:u.signal}).then(async v=>{let E=v.ok?await v.json().catch(()=>{}):void 0;return{ok:E!==void 0,json:async()=>E}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",b)})},[l,d,c,p,m,g,_,y,S]=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"),i("/api/signals/stopped?limit=20")]);if(!d||!d.ok)return o.error=d?`HTTP ${d.status}`:"unreachable",o;let T=await d.json();if(o.agents=T.map(h=>({id:h.id,name:h.name,tier:h.tier,model:h.model,...typeof h.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(h.color)?{color:h.color}:{},skillCount:Number.isFinite(h.skillCount)?h.skillCount:void 0,active:h.active||0,total:h.total||0,errors:h.errors||0,lastActive:h.lastActive,lastSummary:h.lastSummary,hourlyTasks:Array.isArray(h.hourlyTasks)?h.hourlyTasks:void 0,runningTasks:Array.isArray(h.runningTasks)?h.runningTasks:[]})),l&&l.ok){let h=await l.json().catch(()=>({}));o.uptimeSec=h.uptime,typeof h.inflight?.total=="number"&&(o.inflight=h.inflight.total),h.restart&&typeof h.restart.state=="string"&&(o.restart=h.restart),o.name=h.node?.name||h.node?.id||t,o.id=h.node?.id||t,h.usage&&(o.usage=h.usage)}if(S&&S.ok){let h=await S.json().catch(()=>({})),u=Array.isArray(h?.tasks)?h.tasks:[];o.stoppedTasks=u.filter(f=>f&&f.state!=="resumed").slice(0,10).map(f=>({id:String(f.id),agentId:String(f.agentId),channel:String(f.channel??""),chatId:String(f.chatId??""),state:String(f.state),stoppedAt:String(f.stoppedAt),stoppedBy:String(f.stoppedBy??""),reason:typeof f.reason=="string"?f.reason:void 0,request:String(f.request??""),plan:f.plan&&typeof f.plan.text=="string"?{author:String(f.plan.author),text:f.plan.text,note:f.plan.note}:void 0,resumable:f.resumable===!0}))}if(p&&p.ok){let h=await p.json().then(u=>Array.isArray(u)?u:[],()=>[]);o.crons=h.map(u=>({id:u.id,enabled:u.enabled===!0,schedule:String(u.schedule||""),timezone:u.timezone,agent:String(u.agent||""),kind:typeof u.command=="string"&&u.command.trim()?"command":"agent",model:u.model,nextRun:u.nextRun,retryPending:u.retryPending===!0,consecutiveErrors:Number(u.consecutiveErrors)||0}))}if(m&&m.ok){let h=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(h.runs)?h.runs:[]}if(_&&_.ok){let h=await _.json().catch(()=>null);h&&Array.isArray(h.routines)&&(o.routines=h.routines.slice(0,ar.routines))}if(g&&g.ok){let h=await g.json().catch(()=>null);h?.active&&h.kind==="lesson"&&(o.lesson={agentId:h.agentId??null,mode:String(h.mode||"teach"),goal:String(h.goal||""),step:Number(h.step)||0,saying:String(h.saying||""),startedAt:String(h.startedAt||"")})}if(y&&y.ok){let h=await y.json().catch(()=>null);h&&Array.isArray(h.sessions)&&Gh(o,h.sessions,h.saved??{})}o.reachable=!0,o._peers=Array.isArray(c?.ok?await c.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var ca=null;function Bh(t){if(ca)return ca;let e=it(process.cwd(),".agentx/wiki");return ca=so({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph",curator:!0,curatorToken:()=>t.token}),ca}async function ma(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 qh(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){w(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();w(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){w(t,502,{error:s.message||"daemon unreachable"})}}async function Se(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await ma(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var zh=3e3,Fh=6e3,Uh=5*6e4,Tn=new Map,pa=new Map;function Ye(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=pa.get(a);if(n)return n;let r=(async()=>{let o=await Se(t,AbortSignal.timeout(zh)),s=await Promise.all(o.map(async i=>{let l=await Hh(i.url,i.token,AbortSignal.timeout(Fh),e);return e?l:Wh(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>pa.delete(a));return pa.set(a,r),r}function Wh(t,e,a=Date.now()){if(e.reachable&&!e.error)return Tn.set(t,{node:e,at:a}),e;let n=Tn.get(t);return!n||a-n.at>Uh?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function W0(){Tn.clear(),pa.clear()}function Gh(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 Xh(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,d)=>{n||e.write(`event: ${l}
|
|
20860
|
+
data: ${JSON.stringify(d)}
|
|
20758
20861
|
|
|
20759
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ye(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
|
|
20760
|
-
${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
|
|
20862
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ye(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 Kh(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 ma(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let y of _)i.add(y.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let c=new AbortController,p;try{p=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:c.signal})}catch(_){w(e,502,{error:_.message||"upstream connect failed"});return}if(!p.ok||!p.body){w(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:y}=await m.read();if(y)break;_&&e.write(_)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{c.abort();try{e.end()}catch{}})}function Jh(t,e,a){let n=Sa(t);if(!n)return w(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new G().verify(n);if(!r)return w(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!Ee(r,o))return w(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Vh(t,e,a,n){let r=a.agents?.[n];if(!r){w(e,404,{error:"unknown agent"});return}if(r.access!=="public"){w(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await re(t)}catch{w(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){w(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=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||{}}})}),c=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(c)}catch(d){w(e,502,{error:d.message||"upstream call failed"})}}async function Yh(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 ma(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of p)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let c=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let p=await fetch(`${s}${c}`,{headers:d}),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){w(t,502,{error:p.message||"upstream fetch failed"})}}async function Qh(t,e,a,n,r,o){await ua(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function ua(t,e,a,n,r){let o={};try{o=await re(t)??{}}catch{}let s=await Gd(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Gd(t,e,a,n){let r=(d,c)=>({status:d,text:JSON.stringify(c),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await ma(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let c of d)s.add(c.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function An(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){let r=t.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(t.dashboard,r);return wt(),{...a(`Can't reach ${e.relayTo}, the computer that sends notifications`),async forward(s){let i=await fetch(`${r}/push/app`,{method:"POST",headers:{"Content-Type":"application/json",...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify({op:"app",call:s}),signal:AbortSignal.timeout(2e4)}),l=await i.json().catch(()=>({}));if(!i.ok||typeof l.status!="number")throw new Error(l.error||`the daemon answered ${i.status}`);return{status:l.status,body:l.body??{}}}}}let n=cr(e.keysFile);return{store:()=>{let r=Ve();return r?new Or(r):null},publicKey:()=>pr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function qd(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?$l({url:a,token:U(t.dashboard,a),operatorKey:va(process.cwd())??void 0}):null,r=e.relayTo?`this computer relays notifications to ${e.relayTo}; place reminders work on a phone paired with ${e.relayTo}.`:An(t).reason;return Dl(t,process.cwd(),n,r)}function Xd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ye(t,n),async nodePost(n,r,o){let s=await Gd(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=Et({root:process.cwd()}).items.map(Fd)}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=lt(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 d=await l.json();s.items=(d.items??[]).map(Fd)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s,i={}){let l=n.replace(/\/+$/,"");if(l===e){let c=Ae(),p=await Tt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s,...i});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let d=lt(l,t);if(!d)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let c=await fetch(`${d.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:JSON.stringify({key:r,action:o,...i}),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 En=null;function zd(t){return En?.days!==t&&(En={days:t,store:new ht(process.cwd(),Date.now,t)}),En.store}function Kd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Xd(t);return{store:()=>{let r=Ve();return r?new st(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:va(process.cwd())??void 0},snapshot:()=>Ye(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s),tokenFor:r=>U(t.dashboard,r.replace(/\/+$/,"")),...Zh(t,e,a)}}function Zh(t,e,a){let n=An(t);return{finishAlerts:r=>{if(n.forward)return dr.finishOn(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}
|
|
20863
|
+
${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 eg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Kd(t);return new da({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 d=await l.json();return{events:Array.isArray(d.events)?d.events:[],gap:d.gap===!0}},nodeUrl:async o=>{let i=(await Ye(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:pl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function tg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ve();return a?new st(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function ag(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function Fd(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,...t.choices?{choices:t.choices}:{},...t.draft?{draft:t.draft}:{}}}var ng=`
|
|
20761
20864
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
20762
20865
|
|
|
20763
20866
|
Title pattern:
|
|
@@ -20789,16 +20892,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
20789
20892
|
Shape:
|
|
20790
20893
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
20791
20894
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
20792
|
-
`;async function
|
|
20895
|
+
`;async function rg(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):
|
|
20793
20896
|
- ${r.knownLabels.slice(0,60).join(`
|
|
20794
20897
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
20795
|
-
`),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:
|
|
20898
|
+
`),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:ng}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let c=(d.content||"").toString(),p=og(c);if(!p||typeof p.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+c.slice(0,400));let m=Array.isArray(p.labels)?p.labels.filter(g=>typeof g=="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:c}}function og(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 sg(t){let e=Lh(Mh(import.meta.url));return it(e,t)}async function ig(t){return Ih(t)}function w(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function re(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 Jd(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:Jd(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 lg(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;w(e,200,await ta(await Vd(r,a.config)))}async function Vd(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=an(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=lt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,c=setTimeout(()=>d.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:d.signal});return p.ok?{nodeId:i.name||i.url,snap:await p.json()}:null}finally{clearTimeout(c)}}catch{return null}}));for(let i of s)i&&n.push(i);return xi(n)}async function dg(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),g=m.find(_=>Wd(_));if(!g){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",g]}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}
|
|
20796
20899
|
|
|
20797
20900
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=p=>{i+=p.toString("utf8");let m;for(;(m=i.indexOf(`
|
|
20798
20901
|
`))>=0;){let g=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
|
|
20799
20902
|
data: ${g.replace(/\n/g," ")}
|
|
20800
20903
|
|
|
20801
|
-
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let
|
|
20904
|
+
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
|
|
20802
20905
|
|
|
20803
|
-
`)}catch{}},15e3),
|
|
20804
|
-
//# sourceMappingURL=board-dashboard-
|
|
20906
|
+
`)}catch{}},15e3),c=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",c),s.on("exit",c),s.on("error",c)}async function Ud(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 g=[];t.on("data",_=>g.push(_)),t.on("end",()=>p(Buffer.concat(g))),t.on("error",m)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let c=t.headers["x-requested-with"];c&&(l["X-Requested-With"]=Array.isArray(c)?c[0]:c),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){w(e,502,{error:`proxy to peer failed: ${p?.message||p}`,target:r})}}function lt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Jd(n),token:n.dashboardToken||n.token}:null}export{Gh as applyAttachSessions,Hh as fetchDaemonAgents,Ph as handleBoardRequest,W0 as resetLiveCaches,Se as resolveNodeTargets,U0 as startBoardDashboard,Wh as withLastGood};
|
|
20907
|
+
//# sourceMappingURL=board-dashboard-GKE4KWJH.js.map
|