agentix-cli 0.110.0 → 0.111.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/apps/mac-voice/Sources/AgentXVoice/Panel.swift +77 -30
- package/apps/mac-voice/Sources/AgentXVoice/PanelAnswer.swift +3 -2
- package/apps/mac-voice/Sources/AgentXVoice/PillForm.swift +55 -0
- package/apps/mac-voice/Sources/AgentXVoice/PillMenu.swift +8 -7
- package/apps/mac-voice/Sources/AgentXVoice/SettingsLook.swift +2 -2
- package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +5 -6
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +7 -6
- package/dist/{App-4VWAQOVA.js → App-T4Q7SW6M.js} +2 -2
- package/dist/{ChatApp-KOTGUDZH.js → ChatApp-BKUJUIDL.js} +2 -2
- package/dist/{agent-CGRHC2IS.js → agent-YZVEXFE7.js} +2 -2
- package/dist/{board-dashboard-SAYBNLZW.js → board-dashboard-3TVUCOSI.js} +411 -257
- package/dist/board-dashboard-3TVUCOSI.js.map +1 -0
- package/dist/{chunk-UVMCAZL7.js → chunk-4FU4BFCH.js} +2 -2
- package/dist/{chunk-NIW75USA.js → chunk-4NFDDTGA.js} +2 -2
- package/dist/{chunk-2VGYRETU.js → chunk-53OS4TDU.js} +2 -2
- package/dist/{chunk-J32LSOBJ.js → chunk-7UNS34CN.js} +2 -2
- package/dist/chunk-AV7T3SYT.js +111 -0
- package/dist/chunk-AV7T3SYT.js.map +1 -0
- package/dist/chunk-DTQQ4DAY.js +154 -0
- package/dist/chunk-DTQQ4DAY.js.map +1 -0
- package/dist/{chunk-SFPMS55Z.js → chunk-DUBCOGQB.js} +49 -48
- package/dist/chunk-DUBCOGQB.js.map +1 -0
- package/dist/{chunk-BFOB6ERR.js → chunk-DXWDVKMX.js} +2 -2
- package/dist/{chunk-BZKGQMU2.js → chunk-FBODSJU6.js} +2 -2
- package/dist/{chunk-UTV4DRAW.js → chunk-GQMUFSKB.js} +14 -14
- package/dist/{chunk-UTV4DRAW.js.map → chunk-GQMUFSKB.js.map} +1 -1
- package/dist/{chunk-4UCDWEC4.js → chunk-HCTWKWS3.js} +2 -2
- package/dist/{chunk-EC6DKMR5.js → chunk-KDD6FPQ6.js} +238 -238
- package/dist/chunk-KDD6FPQ6.js.map +1 -0
- package/dist/{chunk-5O6PIO7F.js → chunk-LWYKS5JU.js} +2 -2
- package/dist/{chunk-QQAZ6EJP.js → chunk-M2L6S3Z5.js} +2 -2
- package/dist/{chunk-6F2E5NQA.js → chunk-QJP37VVA.js} +2 -2
- package/dist/{chunk-QFP4YZII.js → chunk-RS2T53EC.js} +2 -2
- package/dist/{chunk-E5OV6RTG.js → chunk-RXLU6HJ6.js} +3 -3
- package/dist/chunk-RXLU6HJ6.js.map +1 -0
- package/dist/{chunk-D7M4WQFU.js → chunk-SIOWVLZG.js} +4 -4
- package/dist/chunk-SIOWVLZG.js.map +1 -0
- package/dist/{chunk-BG6SOGKT.js → chunk-U52IS3AF.js} +2 -2
- package/dist/{chunk-RJ7DASOU.js → chunk-UIBUZ2N3.js} +25 -10
- package/dist/chunk-UIBUZ2N3.js.map +1 -0
- package/dist/{chunk-MJWJ3JVA.js → chunk-WSKQUKCF.js} +2 -2
- package/dist/{chunk-S4NZUPIN.js → chunk-WXQQO2PD.js} +2 -2
- package/dist/{chunk-FHI5WPFO.js → chunk-WYSNRZV4.js} +4 -4
- package/dist/chunk-WYSNRZV4.js.map +1 -0
- package/dist/{chunk-CJR26JUI.js → chunk-XEOT2F4C.js} +2 -2
- package/dist/{chunk-3Z5P2CWS.js → chunk-XF26QNAW.js} +2 -2
- package/dist/{chunk-CJL5OPNQ.js → chunk-Z7L74GGT.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-VYMTUZKN.js → client-O7SPKO5X.js} +2 -2
- package/dist/config-ZHQYXFOJ.js +2 -0
- package/dist/config-mutator-RS2NTDNO.js +2 -0
- package/dist/{doctor-GHUPUBET.js → doctor-XP7O45RC.js} +2 -2
- package/dist/{grants-Y667GZAU.js → grants-M4K6WXOO.js} +2 -2
- package/dist/index.d.ts +68 -15
- package/dist/index.js +1 -1
- package/dist/{program-V2JEVJAD.js → program-EZLJIVQX.js} +187 -182
- package/dist/program-EZLJIVQX.js.map +1 -0
- package/dist/{promote-KY3Y2PVU.js → promote-UGWANGI2.js} +2 -2
- package/dist/{query-BYCRYDM3.js → query-ZET7Z5FT.js} +2 -2
- package/dist/registry-UXWOY52B.js +2 -0
- package/dist/request-planner-W5YLKCGG.js +6 -0
- package/dist/request-planner-W5YLKCGG.js.map +1 -0
- package/dist/{review-candidates-56ZPJNXW.js → review-candidates-GU4S5VQH.js} +2 -2
- package/dist/{routing-WKS2CZYF.js → routing-GJ4VXKIC.js} +2 -2
- package/dist/schedule-tool-HD4LWKVC.js +2 -0
- package/dist/scheduler-3LEHZHWJ.js +2 -0
- package/dist/seat-L6XJ2BFA.js +2 -0
- package/dist/select-T7CKKLC2.js +2 -0
- package/dist/{select-73JC2YBN.js.map → select-T7CKKLC2.js.map} +1 -1
- package/dist/{set-enabled-WQAO4BFF.js → set-enabled-U2HGNY2O.js} +2 -2
- package/dist/{surface-usage-CH3SHO77.js → surface-usage-HCJTUS6Z.js} +2 -2
- package/dist/{tool-QDU6MY6B.js → tool-2FMWZB4N.js} +2 -2
- package/dist/{tool-GCPMPPUE.js → tool-TX622HEB.js} +2 -2
- package/dist/wiki-MYJBOJSM.js +2 -0
- package/dist/workspace-setup-HAV4CQV7.js +2 -0
- package/package.json +2 -1
- package/dist/board-dashboard-SAYBNLZW.js.map +0 -1
- package/dist/chunk-3TY6YJHO.js +0 -153
- package/dist/chunk-3TY6YJHO.js.map +0 -1
- package/dist/chunk-D7M4WQFU.js.map +0 -1
- package/dist/chunk-E5OV6RTG.js.map +0 -1
- package/dist/chunk-EC6DKMR5.js.map +0 -1
- package/dist/chunk-FHI5WPFO.js.map +0 -1
- package/dist/chunk-RJ7DASOU.js.map +0 -1
- package/dist/chunk-SFPMS55Z.js.map +0 -1
- package/dist/chunk-UDJAODAB.js +0 -100
- package/dist/chunk-UDJAODAB.js.map +0 -1
- package/dist/config-J6CNV23P.js +0 -2
- package/dist/config-mutator-RGC72OEU.js +0 -2
- package/dist/program-V2JEVJAD.js.map +0 -1
- package/dist/registry-NDFYNQG4.js +0 -2
- package/dist/request-planner-YOUVO3BR.js +0 -2
- package/dist/request-planner-YOUVO3BR.js.map +0 -1
- package/dist/schedule-tool-4L6QAILN.js +0 -2
- package/dist/scheduler-65SE3WJJ.js +0 -2
- package/dist/seat-EO3EVBH3.js +0 -2
- package/dist/select-73JC2YBN.js +0 -2
- package/dist/wiki-CQZE5Z5C.js +0 -2
- package/dist/workspace-setup-EA3G42NY.js +0 -2
- /package/dist/{App-4VWAQOVA.js.map → App-T4Q7SW6M.js.map} +0 -0
- /package/dist/{ChatApp-KOTGUDZH.js.map → ChatApp-BKUJUIDL.js.map} +0 -0
- /package/dist/{agent-CGRHC2IS.js.map → agent-YZVEXFE7.js.map} +0 -0
- /package/dist/{chunk-UVMCAZL7.js.map → chunk-4FU4BFCH.js.map} +0 -0
- /package/dist/{chunk-NIW75USA.js.map → chunk-4NFDDTGA.js.map} +0 -0
- /package/dist/{chunk-2VGYRETU.js.map → chunk-53OS4TDU.js.map} +0 -0
- /package/dist/{chunk-J32LSOBJ.js.map → chunk-7UNS34CN.js.map} +0 -0
- /package/dist/{chunk-BFOB6ERR.js.map → chunk-DXWDVKMX.js.map} +0 -0
- /package/dist/{chunk-BZKGQMU2.js.map → chunk-FBODSJU6.js.map} +0 -0
- /package/dist/{chunk-4UCDWEC4.js.map → chunk-HCTWKWS3.js.map} +0 -0
- /package/dist/{chunk-5O6PIO7F.js.map → chunk-LWYKS5JU.js.map} +0 -0
- /package/dist/{chunk-QQAZ6EJP.js.map → chunk-M2L6S3Z5.js.map} +0 -0
- /package/dist/{chunk-6F2E5NQA.js.map → chunk-QJP37VVA.js.map} +0 -0
- /package/dist/{chunk-QFP4YZII.js.map → chunk-RS2T53EC.js.map} +0 -0
- /package/dist/{chunk-BG6SOGKT.js.map → chunk-U52IS3AF.js.map} +0 -0
- /package/dist/{chunk-MJWJ3JVA.js.map → chunk-WSKQUKCF.js.map} +0 -0
- /package/dist/{chunk-S4NZUPIN.js.map → chunk-WXQQO2PD.js.map} +0 -0
- /package/dist/{chunk-CJR26JUI.js.map → chunk-XEOT2F4C.js.map} +0 -0
- /package/dist/{chunk-3Z5P2CWS.js.map → chunk-XF26QNAW.js.map} +0 -0
- /package/dist/{chunk-CJL5OPNQ.js.map → chunk-Z7L74GGT.js.map} +0 -0
- /package/dist/{client-VYMTUZKN.js.map → client-O7SPKO5X.js.map} +0 -0
- /package/dist/{config-J6CNV23P.js.map → config-ZHQYXFOJ.js.map} +0 -0
- /package/dist/{config-mutator-RGC72OEU.js.map → config-mutator-RS2NTDNO.js.map} +0 -0
- /package/dist/{doctor-GHUPUBET.js.map → doctor-XP7O45RC.js.map} +0 -0
- /package/dist/{grants-Y667GZAU.js.map → grants-M4K6WXOO.js.map} +0 -0
- /package/dist/{promote-KY3Y2PVU.js.map → promote-UGWANGI2.js.map} +0 -0
- /package/dist/{query-BYCRYDM3.js.map → query-ZET7Z5FT.js.map} +0 -0
- /package/dist/{registry-NDFYNQG4.js.map → registry-UXWOY52B.js.map} +0 -0
- /package/dist/{review-candidates-56ZPJNXW.js.map → review-candidates-GU4S5VQH.js.map} +0 -0
- /package/dist/{routing-WKS2CZYF.js.map → routing-GJ4VXKIC.js.map} +0 -0
- /package/dist/{schedule-tool-4L6QAILN.js.map → schedule-tool-HD4LWKVC.js.map} +0 -0
- /package/dist/{scheduler-65SE3WJJ.js.map → scheduler-3LEHZHWJ.js.map} +0 -0
- /package/dist/{seat-EO3EVBH3.js.map → seat-L6XJ2BFA.js.map} +0 -0
- /package/dist/{set-enabled-WQAO4BFF.js.map → set-enabled-U2HGNY2O.js.map} +0 -0
- /package/dist/{surface-usage-CH3SHO77.js.map → surface-usage-HCJTUS6Z.js.map} +0 -0
- /package/dist/{tool-QDU6MY6B.js.map → tool-2FMWZB4N.js.map} +0 -0
- /package/dist/{tool-GCPMPPUE.js.map → tool-TX622HEB.js.map} +0 -0
- /package/dist/{wiki-CQZE5Z5C.js.map → wiki-MYJBOJSM.js.map} +0 -0
- /package/dist/{workspace-setup-EA3G42NY.js.map → workspace-setup-HAV4CQV7.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{A as Dr,B as Hr,C as Br,a as A,b as _r,c as Sr,d as Er,e as Tr,f as Se,g as Ar,h as Cr,i as Rt,k as Ir,q as Mr,r as Lr,s as Rr,t as $r,u as Pr,y as jr,z as Or}from"./chunk-DUBCOGQB.js";import{a as Nr}from"./chunk-4FU4BFCH.js";import{a as kr}from"./chunk-QAIYUMHW.js";import{a as He,b as B,c as M,h as be,i as Mt,j as re,k as K,l as Lt,m as br,n as yr,o as wr}from"./chunk-N7HKIMMR.js";import{a as vr}from"./chunk-2NYP4OQU.js";import{a as ce,b as xr}from"./chunk-JWDJMFU6.js";import{$a as gr,A as kt,B as Yn,E as Qn,F as Zn,Fa as dr,G as er,Ha as Ne,Ma as pr,N as U,O as tr,Oa as De,P as ar,Pa as Et,Qa as Tt,Ra as At,Sa as Ct,Ta as ur,Ua as mr,Va as fr,Wa as It,Ya as hr,a as Hn,c as gt,d as ha,e as Bn,i as xt,l as Je,n as zn,ta as sr,va as ir,w as bt,wa as lr,x as Xn,xa as cr,y as yt,z as wt}from"./chunk-WYSNRZV4.js";import{g as Nn,h as Dn}from"./chunk-U52IS3AF.js";import{p as qn,t as Fn}from"./chunk-S2GAEH2F.js";import"./chunk-GTJIKXDB.js";import{a as Vn,b as N,c as nr,d as rr,h as or}from"./chunk-DG5I6PPM.js";import"./chunk-LWYKS5JU.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as _e,d as Un,e as ga}from"./chunk-ACFQBLPX.js";import{g as vt}from"./chunk-LQE73AZR.js";import{b as Wn,c as Gn}from"./chunk-2D3RYIDU.js";import{m as Kn,n as _t,o as St,q as Jn}from"./chunk-RXLU6HJ6.js";import{a as Mn,f as Ln,g as ma,h as fa,l as Rn,m as $n,n as Pn,u as mt,v as ft,w as ht,x as le,y as On}from"./chunk-53OS4TDU.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import"./chunk-SHEUCITK.js";import"./chunk-Y4CYQV7G.js";import"./chunk-WXQQO2PD.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-M2L6S3Z5.js";import{a as jn}from"./chunk-QJP37VVA.js";import"./chunk-DXWDVKMX.js";import"./chunk-Z7L74GGT.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as In}from"./chunk-RS2T53EC.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-GQMUFSKB.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{A as rc,J as En,M as oc,O as pt,P as Tn,R as An,T as Cn,X as ua,a as vn,b as bn,c as tc,ia as X,la as ut,u as lt,v as ac,w as da,x as pa}from"./chunk-SIOWVLZG.js";import{d as _n,e as nc,f as dt,n as Sn}from"./chunk-UIBUZ2N3.js";import{a as yn,b as ct,c as ca,d as wn,h as kn}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function xa(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function zr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:xa(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Ee=(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>",$t=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Ee(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function qr(t={}){return M({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
|
|
2
2
|
|
|
3
3
|
<div class="bf-head">
|
|
4
4
|
<div>
|
|
@@ -7,8 +7,8 @@ import{a as A,b as mr,c as fr,d as hr,e as gr,f as _e,g as xr,h as vr,i as Mt,k
|
|
|
7
7
|
</div>
|
|
8
8
|
<div class="bf-sync">
|
|
9
9
|
<span class="bf-sync__t" id="synced">Gathering…</span>
|
|
10
|
-
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${
|
|
11
|
-
<button class="ax-btn" id="refresh" title="Refresh now">${
|
|
10
|
+
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${Ee(oe.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${Ee(oe.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{a as A,b as mr,c as fr,d as hr,e as gr,f as _e,g as xr,h as vr,i as Mt,k
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${$t(oe.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
|
|
25
25
|
<div id="you" class="bf-col"></div>
|
|
26
26
|
|
|
27
|
-
${
|
|
27
|
+
${$t(oe.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed — not yet automatic</span>')}
|
|
28
28
|
<div id="agents" class="bf-col"></div>
|
|
29
29
|
<button class="ax-btn ax-btn--sm" id="more-actions" hidden></button>
|
|
30
30
|
|
|
31
31
|
<div id="handled"></div>
|
|
32
32
|
</section>
|
|
33
33
|
<aside class="bf-col">
|
|
34
|
-
${
|
|
34
|
+
${$t(oe.pulse,"In motion","run-count")}
|
|
35
35
|
<div id="running" class="bf-col"></div>
|
|
36
36
|
</aside>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
${
|
|
39
|
+
${$t(oe.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${
|
|
41
|
+
<div class="bf-search">${Ee(oe.search)}
|
|
42
42
|
<input id="search" type="search" placeholder="Search sessions…" aria-label="Search sessions">
|
|
43
43
|
</div>
|
|
44
44
|
<div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
|
|
@@ -46,15 +46,15 @@ ${Lt(oe.file,"Session briefings","brief-count")}
|
|
|
46
46
|
<div id="reviews" class="bf-col"></div>
|
|
47
47
|
|
|
48
48
|
<section class="ax-panel bf-connect">
|
|
49
|
-
<div class="bf-connect__head">${
|
|
49
|
+
<div class="bf-connect__head">${Ee(oe.plug,17)}<h2>Connect a CLI session</h2>
|
|
50
50
|
<span class="bf-connect__note">Daemon-owned processes only</span></div>
|
|
51
51
|
<div class="bf-discover">
|
|
52
52
|
<div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
|
|
53
|
-
<button class="ax-btn" id="discover">${
|
|
53
|
+
<button class="ax-btn" id="discover">${Ee(oe.search)} Discover CLIs</button>
|
|
54
54
|
</div>
|
|
55
55
|
<div class="bf-cli" id="discovered"></div>
|
|
56
56
|
<details class="bf-manual">
|
|
57
|
-
<summary>${
|
|
57
|
+
<summary>${Ee(oe.chev,12)} Register manually</summary>
|
|
58
58
|
<div class="bf-forms">
|
|
59
59
|
<form id="register" class="bf-form">
|
|
60
60
|
<div class="ax-sec-label"><h3>Register a session</h3></div>
|
|
@@ -85,7 +85,7 @@ ${Lt(oe.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:sc,scripts:`<script>${B({decayOf:xa,rankByDecay:zr})}const ICON = ${JSON.stringify(oe)};${ic}</script>`})}var sc=`
|
|
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
|
+
}`,ic=String.raw`
|
|
365
365
|
(function(){
|
|
366
366
|
const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
367
367
|
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
@@ -776,22 +776,22 @@ if(document.querySelector('form :focus'))return;
|
|
|
776
776
|
if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
|
|
777
777
|
refresh();
|
|
778
778
|
},15000);
|
|
779
|
-
})();`;function
|
|
779
|
+
})();`;function va(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function ba(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 Fr(t,e=[],a){let{bands:n,gaps:r}=va(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(v=>l.startedAt>=v.from&&l.startedAt<=v.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,m=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),_=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};_.runs.push({...l,band:c,track:0,left:m,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,_)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>ba(l.runs.filter(u=>u.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as lc}from"crypto";import{readFileSync as cc,statSync as dc}from"fs";import{resolve as pc,dirname as uc}from"path";import{fileURLToPath as mc}from"url";var Ur=new Map;function Pt(t){let e=Ur.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=uc(mc(import.meta.url)),r=pc(n,"web",t),o=dc(r),s=o.size<8e6?lc("sha1").update(cc(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Ur.set(t,a),a}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},jt=(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>",fc=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["person","Person",se.user],["node","Node",se.mesh]],Wr={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 Gr(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return M({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
|
|
780
780
|
|
|
781
781
|
<div class="ac-head">
|
|
782
782
|
<div>
|
|
783
783
|
<div class="ac-kicker">Operations</div>
|
|
784
784
|
<h1>What ran, where, and what it decided</h1>
|
|
785
|
-
<p class="ac-sub" id="sub">${
|
|
785
|
+
<p class="ac-sub" id="sub">${Wr[e]}</p>
|
|
786
786
|
</div>
|
|
787
787
|
<div class="ac-tools">
|
|
788
788
|
<div class="ac-seg" id="view" role="radiogroup" aria-label="View">
|
|
789
|
-
${[["timeline","Timeline",se.timeline],["map","Map",se.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${
|
|
789
|
+
${[["timeline","Timeline",se.timeline],["map","Map",se.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${jt(o,13)}${r}</button>`).join("")}
|
|
790
790
|
</div>
|
|
791
791
|
<div class="ac-seg" id="hours" role="radiogroup" aria-label="Window">
|
|
792
792
|
${[["6","6h"],["24","24h"],["72","3d"],["168","7d"]].map(([n,r],o)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${o===1}"${o===1?' class="is-on"':""}>${r}</button>`).join("")}
|
|
793
793
|
</div>
|
|
794
|
-
<button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${
|
|
794
|
+
<button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${jt(se.refresh,13)} Refresh</button>
|
|
795
795
|
</div>
|
|
796
796
|
</div>
|
|
797
797
|
|
|
@@ -799,14 +799,14 @@ refresh();
|
|
|
799
799
|
<div class="ac-bar">
|
|
800
800
|
<span class="ac-lbl">Lanes by</span>
|
|
801
801
|
<div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
|
|
802
|
-
${
|
|
802
|
+
${fc.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${jt(o,13)}${r}</button>`).join("")}
|
|
803
803
|
</div>
|
|
804
804
|
<div class="ac-key">
|
|
805
805
|
<span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
|
|
806
806
|
<span class="ac-k"><i class="ac-d ac-d--warning"></i>warning</span>
|
|
807
807
|
<span class="ac-k"><i class="ac-d ac-d--recommendation"></i>friction</span>
|
|
808
808
|
<span class="ac-k"><i class="ac-d ac-d--later"></i>do later</span>
|
|
809
|
-
<span class="ac-k">${
|
|
809
|
+
<span class="ac-k">${jt(se.x,11)}canceled</span>
|
|
810
810
|
</div>
|
|
811
811
|
</div>
|
|
812
812
|
|
|
@@ -816,10 +816,10 @@ refresh();
|
|
|
816
816
|
</div>
|
|
817
817
|
|
|
818
818
|
<div id="view-map" class="ac-map"${a?"":" hidden"}>
|
|
819
|
-
<div id="ax-fleet-root" data-hours="24" data-src="${
|
|
819
|
+
<div id="ax-fleet-root" data-hours="24" data-src="${Pt("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:hc,scripts:`<script>${B({computeBands:va,packTracks:ba,buildTimeline:Fr})}const ICON = ${JSON.stringify(se)};const SUB = ${JSON.stringify(Wr)};${gc}</script>`})}var hc=`
|
|
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
|
+
`,gc=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 Xr(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return M({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:xc,scripts:`<script src="${Pt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var xc=`
|
|
1028
1028
|
/* Preload the fonts the redesign's CSS references. Placed in the shell so
|
|
1029
1029
|
* they start fetching while the React bundle is still parsing. */
|
|
1030
1030
|
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
|
|
@@ -1045,11 +1045,11 @@ body { margin: 0; overflow: hidden; }
|
|
|
1045
1045
|
font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1046
1046
|
text-align: center;
|
|
1047
1047
|
}
|
|
1048
|
-
`;import{createServer as
|
|
1049
|
-
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...
|
|
1050
|
-
WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${
|
|
1048
|
+
`;import{createServer as lf}from"http";import{appendFileSync as cf,existsSync as Wl,mkdirSync as df}from"fs";import{readFile as pf}from"fs/promises";import{fileURLToPath as uf}from"url";import{dirname as mf,resolve as ot}from"path";oc();function Be(t,e){if(!t)return"absent";let a=Un(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Te=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 Ot(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Kr(t.headers["sec-fetch-mode"]),n.site=Kr(t.headers["sec-fetch-site"]),n}function Kr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as vc}from"zlib";var bc=[41,121,255],yc=[255,255,255],Jr=new Map;function ze(t){let e=Jr.get(t);return e||(e=kc(t,wc(t)),Jr.set(t,e)),e}function wc(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,c=i*i+l*l<=r*r?yc:bc;a.set(c,o*e+1+s*3)}return a}function kc(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),ya("IHDR",a),ya("IDAT",vc(e)),ya("IEND",Buffer.alloc(0))])}function ya(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}ut();rc();var Nt=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 qe(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 Vr(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 Yr(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(v=>v.name==="person"),i=v=>({id:v.id,state:v.state,agentId:v.agent_id,text:v.text,channel:v.channel,chatId:v.chat_id,createdAt:v.created_at,updatedAt:v.updated_at,closedAt:v.closed_at??null,question:v.question??null,attentionReason:v.attention_reason??null,evidence:v.evidence??null,where:{label:qe(v.channel,v.chat_id),url:a.linkFor?.(v.channel,v.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${da.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...da).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${pa.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1049
|
+
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...pa,n-Nt*864e5).map(i):[],p=[];try{p=Rt(t,e,50).filter(v=>v.startedAt>=n-Nt*864e5)}catch{}let u=new Map;if(s&&p.length){let v=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 (${p.map(()=>"?").join(",")})`).all(e,...p.map(S=>S.taskId));for(let S of v)u.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=p.map(v=>({...v,where:v.channel?{label:qe(v.channel,v.chatId??""),url:a.linkFor?.(v.channel,v.chatId??"")??null}:null,request:u.get(v.taskId)??null})),h=new Set(m.map(v=>v.request?.id).filter(Boolean)),_=[...l.filter(v=>!Ec.includes(v.state)),...c].filter(v=>!h.has(v.id));return{open:l,recent:c,runs:m,other:_}}ua();nc();var Qr={waiting:0,yours:0,ahead:null};function Zr(t,e,a={}){let n=_n(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,c=s.get(l)??0;s.set(l,c+1);let p=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};p.waiting++,i.person===e&&(p.yours++,p.ahead===null&&(p.ahead=c),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:qe(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:c})),r.set(i.agentId,p)}return{byAgent:r,mine:o}}var Ac=4e3;function eo(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-Nt*864e5).map(r=>r.agent_id)}function to(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(pt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let c=n.queue?.get(l)??Qr,p=s.get(l),u=p??i.get(l);if(!u)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:c};let m=o(u.person??null),h=u.status==="error"||u.status==="timeout",_=p?"working":h&&m==="you"?"blocked":"free",v=m==="you"&&u.channel!=="a2a",S=v&&u.channel;return{agentId:l,state:_,by:m,at:p?u.started_at:u.finished_at??u.started_at,text:p||v?u.message_preview??null:null,fullText:v&&p&&String(u.original_message??u.message_preview??"").slice(0,Ac)||null,where:S?{label:qe(u.channel,u.chat_id??""),url:n.linkFor?.(u.channel,u.chat_id??"")??null}:null,queue:c}})}function ao(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function no(t,e){return!t||e-t>=3e4||t>e}function Dt(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 ro(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 Ht(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 Bt(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 oo(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 so(t){let e=t.request?t.request.state:"";return e==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:e==="needs_attention"?{label:"Stuck",tone:"stuck"}:t.status==="queued"?{label:"In line",tone:"wait"}:t.status==="in-flight"?{label:"Running",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function io(t){return t==="in_progress"?{label:"In progress",tone:"work"}:t==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:t==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:t==="needs_attention"?{label:"Stuck",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Declined",tone:"off"}:t==="dropped"?{label:"Dropped",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function lo(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 co(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 po=`
|
|
1053
1053
|
(function () {
|
|
1054
1054
|
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1055
1055
|
var who = document.getElementById('who');
|
|
@@ -1130,7 +1130,11 @@ body { margin: 0; overflow: hidden; }
|
|
|
1130
1130
|
function clock(at) { return new Date(at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); }
|
|
1131
1131
|
function agent(a, now, stale) {
|
|
1132
1132
|
var v = agentLine(a);
|
|
1133
|
-
|
|
1133
|
+
// The full text comes only with the person's own request (agents.ts).
|
|
1134
|
+
var mine = a.state === 'working' && a.by === 'you' && !!a.fullText;
|
|
1135
|
+
var q = a.queue || { waiting: 0, yours: 0 };
|
|
1136
|
+
var line = !q.waiting ? 'Nothing waits behind this.' :
|
|
1137
|
+
q.waiting + (q.waiting === 1 ? ' message waits' : ' messages wait') + ' behind this' + (q.yours ? ', ' + (q.yours === q.waiting ? (q.yours === 1 ? 'yours' : 'all yours') : q.yours + ' of them yours') : '') + '.';
|
|
1134
1138
|
var id = 'd-' + esc(a.agentId).replace(/[^A-Za-z0-9_-]/g, '_');
|
|
1135
1139
|
var moved = a.at ? (a.state === 'working' ? '' : a.state === 'blocked' ? 'stopped ' : 'finished ') + ageText(a.at, now) + ' ago' : '';
|
|
1136
1140
|
var meta = (v.by ? '<span>started by ' + esc(v.by) + '</span>' : '') + (moved ? '<span class="moved">' + moved + '</span>' : '') + (a.where ? '<span>from ' + where(a) + '</span>' : '');
|
|
@@ -1143,10 +1147,11 @@ body { margin: 0; overflow: hidden; }
|
|
|
1143
1147
|
html += '<button type="button" class="more" data-agent="' + esc(a.agentId) + '" aria-expanded="' + (opened[a.agentId] ? 'true' : 'false') + '" aria-controls="' + id + '">' + (opened[a.agentId] ? 'Hide' : 'Show') + ' this request</button>' +
|
|
1144
1148
|
'<div class="detail" id="' + id + '">' +
|
|
1145
1149
|
'<ol class="steps" aria-label="Where this request is"><li class="done"><span class="sr">Done: </span>Received</li><li class="now" aria-current="step">Working</li><li>Finished</li></ol>' +
|
|
1146
|
-
'<p class="full">' + esc(a.fullText
|
|
1150
|
+
'<p class="full">' + esc(a.fullText) + '</p><dl>' +
|
|
1147
1151
|
'<dt>Started by</dt><dd>you</dd>' +
|
|
1148
1152
|
'<dt>Sent</dt><dd>' + clock(a.at) + ', ' + ageText(a.at, now) + ' ago</dd>' +
|
|
1149
1153
|
(a.where ? '<dt>Asked on</dt><dd>' + where(a) + '</dd><dt>Answer</dt><dd>It arrives on ' + where(a) + ' when the agent finishes.</dd>' : '') +
|
|
1154
|
+
'<dt>In line</dt><dd>' + line + '</dd>' +
|
|
1150
1155
|
'</dl></div>';
|
|
1151
1156
|
}
|
|
1152
1157
|
return html + '</li>';
|
|
@@ -1172,6 +1177,14 @@ body { margin: 0; overflow: hidden; }
|
|
|
1172
1177
|
'<p class="meta"><span>' + esc(r.agentId) + '</span>' + (r.where ? '<span>from ' + where(r) + '</span>' : '') + '</p>' +
|
|
1173
1178
|
'<p class="side"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span class="moved">' + moved + '</span></p></li>';
|
|
1174
1179
|
}
|
|
1180
|
+
// One of the person's messages still waiting behind a busy agent.
|
|
1181
|
+
function queued(r, now) {
|
|
1182
|
+
var st = sentState({ status: 'queued' });
|
|
1183
|
+
var place = r.ahead === 0 ? 'next when the agent is free' : r.ahead + (r.ahead === 1 ? ' message' : ' messages') + ' ahead of it';
|
|
1184
|
+
return '<li class="row"><p class="text">' + esc(plainPreview(r.messagePreview)) + '</p>' +
|
|
1185
|
+
'<p class="meta"><span>' + esc(r.agentId) + '</span>' + (r.where ? '<span>from ' + where(r) + '</span>' : '') + '</p>' +
|
|
1186
|
+
'<p class="side"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span class="moved">' + place + '</span><span class="moved">sent ' + ageText(r.queuedAt, now) + ' ago</span></p></li>';
|
|
1187
|
+
}
|
|
1175
1188
|
// A request no turn of the list stands for: its turn is older, or it has none.
|
|
1176
1189
|
function request(r, now) {
|
|
1177
1190
|
var st = requestState(r.state);
|
|
@@ -1181,14 +1194,15 @@ body { margin: 0; overflow: hidden; }
|
|
|
1181
1194
|
'<p class="side"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span class="moved">' + ageText(r.closedAt || r.updatedAt || r.createdAt, now) + ' ago</span></p></li>';
|
|
1182
1195
|
}
|
|
1183
1196
|
function show(w, now) {
|
|
1184
|
-
var agents = w.agents || [];
|
|
1185
|
-
sum.textContent = summaryLine(agents, w.runs.length);
|
|
1197
|
+
var agents = w.agents || [], waiting = w.queued || [];
|
|
1198
|
+
sum.textContent = summaryLine(agents, w.runs.length + waiting.length);
|
|
1186
1199
|
agentsBox.hidden = !agents.length;
|
|
1187
1200
|
agentsList.innerHTML = agents.map(function (a) { return agent(a, now, false); }).join('');
|
|
1188
1201
|
var asks = w.open.filter(function (r) { return r.state === 'waiting_owner' || r.state === 'needs_attention'; });
|
|
1189
1202
|
need.hidden = !asks.length;
|
|
1190
1203
|
document.getElementById('need-list').innerHTML = asks.map(function (r) { return needRow(r, now); }).join('');
|
|
1191
|
-
document.getElementById('sent').innerHTML =
|
|
1204
|
+
document.getElementById('sent').innerHTML = waiting.map(function (r) { return queued(r, now); }).join('') +
|
|
1205
|
+
w.runs.map(function (r) { return sent(r, now); }).join('') +
|
|
1192
1206
|
(w.other || []).map(function (r) { return request(r, now); }).join('') ||
|
|
1193
1207
|
'<li class="blank"><p>Ask an agent for something on WhatsApp, Telegram, GitLab or GitHub. It shows up here as soon as the agent starts on it.</p><p>You see when it is running, when it is finished, and when the agent is free again.</p></li>';
|
|
1194
1208
|
}
|
|
@@ -1221,7 +1235,7 @@ body { margin: 0; overflow: hidden; }
|
|
|
1221
1235
|
showConn();
|
|
1222
1236
|
load();
|
|
1223
1237
|
})();
|
|
1224
|
-
`;var
|
|
1238
|
+
`;var zt=`
|
|
1225
1239
|
:root { --link: var(--ax-blue-d); --ring: var(--ax-blue); --tick: var(--ax-green-d); }
|
|
1226
1240
|
[data-theme="dark"] { --link: var(--ax-blue); --tick: var(--ax-green); }
|
|
1227
1241
|
* { box-sizing: border-box; }
|
|
@@ -1249,7 +1263,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1249
1263
|
.card h2 { font-size: 24px; font-weight: 700; line-height: 1.2; margin-bottom: 8px; }
|
|
1250
1264
|
.card p { color: var(--ax-text-2); }
|
|
1251
1265
|
.help { margin-top: 20px; font-size: 14px; color: var(--ax-text-2); }
|
|
1252
|
-
`,
|
|
1266
|
+
`,qt=`
|
|
1253
1267
|
.icon-btn { min-width: 44px; min-height: 44px; font-size: 20px; line-height: 1; border: var(--ax-border-w) solid var(--ax-border-2); border-radius: var(--ax-radius-pill); background: var(--ax-surface); color: var(--ax-text); cursor: pointer; }
|
|
1254
1268
|
.strip, .install { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 10px 20px; font-size: 14px; background: var(--ax-amber-t); color: var(--ax-amber-ink); border-bottom: var(--ax-border-w) solid var(--ax-amber-e); }
|
|
1255
1269
|
.strip[hidden], .install[hidden] { display: none; }
|
|
@@ -1324,7 +1338,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1324
1338
|
.blank { padding: 28px 24px; border: var(--ax-border-w) dashed var(--ax-border-2); border-radius: var(--ax-radius-lg); }
|
|
1325
1339
|
.blank p + p { margin-top: 8px; color: var(--ax-text-2); }
|
|
1326
1340
|
.foot { margin-top: 28px; font-size: 14px; color: var(--ax-text-2); }
|
|
1327
|
-
`,
|
|
1341
|
+
`,uo=`
|
|
1328
1342
|
.pair-form { display: grid; gap: 8px; margin-top: 20px; }
|
|
1329
1343
|
.pair-form label { font-weight: 600; margin-top: 8px; }
|
|
1330
1344
|
.pair-form input { width: 100%; min-height: 52px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: var(--ax-border-w) solid var(--ax-text-2); border-radius: var(--ax-radius-sm); }
|
|
@@ -1336,22 +1350,22 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1336
1350
|
.card .pair-msg.bad { color: var(--ax-red-ink); }
|
|
1337
1351
|
[data-theme="dark"] .card .pair-msg.bad { color: var(--ax-red); }
|
|
1338
1352
|
.card .pair-offline { padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: 14px; background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
|
|
1339
|
-
`,
|
|
1353
|
+
`,mo=`
|
|
1340
1354
|
.pulse { display: inline-block; width: 12px; height: 12px; margin-right: 10px; border-radius: 50%; border: 3px solid var(--ax-amber-ink); box-sizing: border-box; animation: breathe 2.4s ease-in-out infinite; }
|
|
1341
1355
|
@keyframes breathe { 50% { opacity: 0.35; } }
|
|
1342
1356
|
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }
|
|
1343
|
-
`;var
|
|
1357
|
+
`;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 wa(t,e={}){return`<meta charset="utf-8">
|
|
1344
1358
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1345
1359
|
<meta name="theme-color" content="#2979FF">
|
|
1346
1360
|
<meta name="referrer" content="no-referrer">
|
|
1347
1361
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
1348
|
-
<meta name="apple-mobile-web-app-title" content="My work">
|
|
1349
|
-
<link rel="manifest" href="/member/manifest.webmanifest">
|
|
1362
|
+
<meta name="apple-mobile-web-app-title" content="${e.appTitle??"My work"}">
|
|
1363
|
+
<link rel="manifest" href="${e.manifest??"/member/manifest.webmanifest"}">
|
|
1350
1364
|
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1351
1365
|
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1352
1366
|
<title>${t}</title>
|
|
1353
|
-
${
|
|
1354
|
-
<style>${
|
|
1367
|
+
${Cc}
|
|
1368
|
+
<style>${He}${zt}</style>`}function fo(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var ho=`
|
|
1355
1369
|
var CACHE = 'agentx-member-v1';
|
|
1356
1370
|
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
1357
1371
|
self.addEventListener('install', function (e) {
|
|
@@ -1381,14 +1395,14 @@ self.addEventListener('fetch', function (e) {
|
|
|
1381
1395
|
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
1382
1396
|
}
|
|
1383
1397
|
});
|
|
1384
|
-
`;function
|
|
1398
|
+
`;function ka(t,e="",a="My work"){return`<header class="bar">
|
|
1385
1399
|
<img class="mark" src="/member/icon-192.png" alt="" width="36" height="36">
|
|
1386
|
-
<div class="grow"><h1
|
|
1387
|
-
</header>`}function
|
|
1400
|
+
<div class="grow"><h1>${a}</h1><p id="who" class="who">${t}</p></div>${e}
|
|
1401
|
+
</header>`}var _a=wa,Sa=ka;function go(t){return`<ol class="steps" aria-label="Steps">${["Type the code","The owner says yes","Your work opens"].map((a,n)=>n<t?`<li class="done"><span class="sr">Done: </span>${a}</li>`:n===t?`<li class="now" aria-current="step">${a}</li>`:`<li>${a}</li>`).join("")}</ol>`}function xo(){return`<!doctype html>
|
|
1388
1402
|
<html lang="en">
|
|
1389
|
-
<head>${
|
|
1403
|
+
<head>${_a("My work \xB7 AgentX")}<style>${qt}</style></head>
|
|
1390
1404
|
<body>
|
|
1391
|
-
${
|
|
1405
|
+
${Sa("Connecting\u2026",`
|
|
1392
1406
|
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`)}
|
|
1393
1407
|
<p id="offline" class="strip" role="status" hidden><span id="offline-text"></span><button type="button" id="retry" hidden>Try now</button></p>
|
|
1394
1408
|
<p id="install" class="install" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</p>
|
|
@@ -1399,15 +1413,15 @@ ${xa("Connecting\u2026",`
|
|
|
1399
1413
|
<section aria-labelledby="h-sent"><h2 id="h-sent">What you sent <span class="n">(last 7 days)</span></h2><ul id="sent" class="rows"></ul></section>
|
|
1400
1414
|
<p id="updated" class="foot"></p>
|
|
1401
1415
|
</main>
|
|
1402
|
-
<script>${
|
|
1416
|
+
<script>${B({workState:Ic,ageText:Ea,connectionNote:Ht,plainPreview:Bt,agentLine:oo,sentState:so,requestState:io,summaryLine:lo,freedAgents:co})}${po}</script>
|
|
1403
1417
|
</body>
|
|
1404
|
-
</html>`}function
|
|
1418
|
+
</html>`}function vo(){return`<!doctype html>
|
|
1405
1419
|
<html lang="en">
|
|
1406
|
-
<head>${
|
|
1420
|
+
<head>${_a("Pair this machine \xB7 AgentX")}<style>${uo}</style></head>
|
|
1407
1421
|
<body>
|
|
1408
|
-
${
|
|
1422
|
+
${Sa("This machine is not paired yet")}
|
|
1409
1423
|
<main class="narrow">
|
|
1410
|
-
${
|
|
1424
|
+
${go(0)}
|
|
1411
1425
|
<div class="card">
|
|
1412
1426
|
<h2>Pair this machine</h2>
|
|
1413
1427
|
<p>The owner sent you a pairing code. Type it with a name for this machine. The owner then approves the machine, and your work page opens.</p>
|
|
@@ -1421,27 +1435,27 @@ ${xa("This machine is not paired yet")}
|
|
|
1421
1435
|
<p id="pair-offline" class="pair-offline" role="status" hidden>You're offline. Pairing needs a connection to the private network.</p>
|
|
1422
1436
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
1423
1437
|
</form>
|
|
1424
|
-
<p class="help">No code? Ask the
|
|
1438
|
+
<p class="help">No code? Ask the person who invited you for one. A code works once, for 10 minutes.</p>
|
|
1425
1439
|
</div>
|
|
1426
1440
|
</main>
|
|
1427
|
-
<script>${
|
|
1441
|
+
<script>${B({formatPairInput:Dt})}${Mc}</script>
|
|
1428
1442
|
</body>
|
|
1429
|
-
</html>`}function
|
|
1443
|
+
</html>`}function bo(){return`<!doctype html>
|
|
1430
1444
|
<html lang="en">
|
|
1431
|
-
<head>${
|
|
1445
|
+
<head>${_a("Waiting for the owner \xB7 AgentX")}<style>${mo}</style></head>
|
|
1432
1446
|
<body>
|
|
1433
|
-
${
|
|
1447
|
+
${Sa("This machine is paired")}
|
|
1434
1448
|
<main class="narrow">
|
|
1435
|
-
${
|
|
1449
|
+
${go(1)}
|
|
1436
1450
|
<div class="card">
|
|
1437
1451
|
<h2><span class="pulse" aria-hidden="true"></span>Waiting for the owner</h2>
|
|
1438
1452
|
<p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens your work by itself when they do.</p>
|
|
1439
1453
|
<p class="help">If they say no, this page asks for a new code.</p>
|
|
1440
1454
|
</div>
|
|
1441
1455
|
</main>
|
|
1442
|
-
<script>${
|
|
1456
|
+
<script>${Lc}</script>
|
|
1443
1457
|
</body>
|
|
1444
|
-
</html>`}function
|
|
1458
|
+
</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 Ea(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min":Math.floor(r/24)+" d "+r%24+" h"}var Mc=`
|
|
1445
1459
|
(function () {
|
|
1446
1460
|
var form = document.getElementById('pair-form');
|
|
1447
1461
|
var machine = document.getElementById('machine');
|
|
@@ -1485,21 +1499,151 @@ ${xa("This machine is paired")}
|
|
|
1485
1499
|
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1486
1500
|
});
|
|
1487
1501
|
})();
|
|
1488
|
-
`,
|
|
1502
|
+
`,Lc=`
|
|
1489
1503
|
(function () {
|
|
1490
1504
|
var msg = document.getElementById('msg');
|
|
1491
1505
|
function check() {
|
|
1492
1506
|
fetch('/api/member/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) {
|
|
1493
1507
|
if (r.status === 200) { location.replace('/member'); return; }
|
|
1494
|
-
if (r.status === 401) { msg.textContent = 'The owner did not approve this machine. Ask
|
|
1508
|
+
if (r.status === 401) { msg.textContent = 'The owner did not approve this machine. Ask the person who invited you for a new code.'; setTimeout(function () { location.replace('/member'); }, 4000); return; }
|
|
1495
1509
|
}).catch(function () {});
|
|
1496
1510
|
}
|
|
1497
1511
|
setInterval(check, 5000);
|
|
1498
1512
|
})();
|
|
1499
|
-
`;var Dt="agentx_member",vc=90*86400,bc=new wt,ho=t=>t.replace(/^\[app\]/,"[member]"),yc=new Ee(t=>console.log(ho(t))),uo=new WeakMap;function wc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return yc;let e=uo.get(t.log);return e||uo.set(t.log,e=new Ee(a=>t.log(ho(a)))),e}var mo=null;function Ke(t,e=X){try{return mo=e().people}catch{return mo??t}}async function go(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new dt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ht(r.root),limiter:r.pairLimiter??bc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",oo());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",so);if(a==="/member/icon-192.png")return be(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/member/icon-512.png")return be(e,200,"image/png",Be(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let d=await wr(t,i);return d.status===200&&e.setHeader("Set-Cookie",fo(d.token)),d.status===429&&e.setHeader("Retry-After",String(d.retryAfter)),Te(e,d.status,d.body)}let l=_r(kc(t),i,yr(t));if(!l.ok){if(l.status===401){let d=va(t);return wc(r).record(a.slice(0,120),Pt(t,He(ba(t,Dt),o),d?He(d,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",co()):Te(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?be(e,202,"text/html; charset=utf-8",po()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(d=>d.id===l.personId);if(n==="GET"&&a==="/member"){let d=ba(t,Dt);return d&&!va(t)&&e.setHeader("Set-Cookie",fo(d)),be(e,200,"text/html; charset=utf-8",lo())}if(n==="GET"&&a==="/api/member/me")return Te(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let d=r.db?.()??null;if(!d)return Te(e,503,{error:"the work list needs the database"});let u=(r.now??Date.now)(),m=zr(d,l.personId,{now:u,linkFor:r.linkFor}),h=[];try{let k=qr(d,c??{id:l.personId},u);h=Fr(d,l.personId,k,{people:r.people(),linkFor:r.linkFor})}catch(k){let v=k instanceof Error?k.message:String(k);/no such table/i.test(v)||r.log?.(`[member] agent cards failed: ${v}`)}return Te(e,200,{...m,agents:h})}return Te(e,404,{error:"not found"})}function fo(t){return`${Dt}=${t}; Path=/; Max-Age=${vc}; HttpOnly; Secure; SameSite=Lax`}function kc(t){return va(t)??ba(t,Dt)}function va(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 be(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Te(t,e,a){return be(t,e,"application/json",JSON.stringify(a))}zl();var xo='/*! 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 Bt,readFileSync as Eo,writeFileSync as To,rmSync as jh,mkdirSync as Cc,copyFileSync as Ic,readdirSync as Mc}from"fs";import{resolve as ze}from"path";ql();function bo(t){let e=ot.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ot.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function Ht(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=ot.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var vo=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function yo(t){return Ht(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 wo(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ht((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:vo(t?.chats),senders:vo(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 ko(t){let e=String(t?.id??"");return Ht(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 _o(t){let e=String(t?.id??"");return Ht(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}"`})}ct();var de={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function So(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Ct([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Sc()+cr,css:Tc,scripts:`${e}<script>${dr}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1513
|
+
`;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 wo(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 ko(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 Ta="/member/client.webmanifest",Ve="Your project";function _o(){return JSON.stringify({id:"/member?client",name:`${Ve} \xB7 AgentX`,short_name:Ve,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=`
|
|
1514
|
+
.about { margin-top: 32px; padding: 16px 20px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-lg); background: var(--ax-surface); font-size: 15px; color: var(--ax-text-2); }
|
|
1515
|
+
.wrap .about h2 { margin: 0 0 6px; }
|
|
1516
|
+
.about p + p { margin-top: 6px; }
|
|
1517
|
+
`;function So(){return`<!doctype html>
|
|
1518
|
+
<html lang="en">
|
|
1519
|
+
<head>${wa(`${Ve} \xB7 AgentX`,{manifest:Ta,appTitle:Ve})}<style>${He}${zt}${qt}${Rc}</style></head>
|
|
1520
|
+
<body>
|
|
1521
|
+
${ka("Connecting\u2026",`
|
|
1522
|
+
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,Ve)}
|
|
1523
|
+
<p id="offline" class="strip" role="status" hidden><span id="offline-text"></span><button type="button" id="retry" hidden>Try now</button></p>
|
|
1524
|
+
<p id="install" class="install" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</p>
|
|
1525
|
+
<main class="wrap">
|
|
1526
|
+
<p id="sum" class="sum" aria-live="polite">Loading\u2026</p>
|
|
1527
|
+
<section aria-labelledby="h-asked"><h2 id="h-asked">What you asked for <span class="n">(last 7 days)</span></h2><ul id="asked" class="rows"></ul></section>
|
|
1528
|
+
<section class="about" aria-labelledby="h-about"><h2 id="h-about">About this page</h2>
|
|
1529
|
+
<p>This page shows what you asked us for and where it stands. Nothing else of yours is here, and nothing of yours is read through it.</p>
|
|
1530
|
+
<p>Something looks wrong? Ask the person who invited you.</p>
|
|
1531
|
+
</section>
|
|
1532
|
+
<p id="updated" class="foot"></p>
|
|
1533
|
+
</main>
|
|
1534
|
+
<script>${B({ageText:Ea,connectionNote:Ht,plainPreview:Bt,clientSentState:yo,clientRequestState:wo,clientSummary:ko})}${$c}</script>
|
|
1535
|
+
</body>
|
|
1536
|
+
</html>`}var $c=`
|
|
1537
|
+
(function () {
|
|
1538
|
+
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1539
|
+
var who = document.getElementById('who');
|
|
1540
|
+
var strip = document.getElementById('offline');
|
|
1541
|
+
var stripText = document.getElementById('offline-text');
|
|
1542
|
+
var retry = document.getElementById('retry');
|
|
1543
|
+
var install = document.getElementById('install');
|
|
1544
|
+
var updated = document.getElementById('updated');
|
|
1545
|
+
var theme = document.getElementById('theme');
|
|
1546
|
+
var sum = document.getElementById('sum');
|
|
1547
|
+
var asked = document.getElementById('asked');
|
|
1548
|
+
var failed = navigator.onLine === false, loaded = false, named = false, busy = false, timer = null;
|
|
1549
|
+
theme.addEventListener('click', function () {
|
|
1550
|
+
var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
1551
|
+
document.documentElement.setAttribute('data-theme', cur);
|
|
1552
|
+
try { localStorage.setItem('ax-theme', cur); } catch (e) {}
|
|
1553
|
+
});
|
|
1554
|
+
if ('serviceWorker' in navigator) { try { navigator.serviceWorker.register('/member/sw.js', { scope: '/member' }); } catch (e) {} }
|
|
1555
|
+
var standalone = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
|
|
1556
|
+
if (!standalone && /Windows|Macintosh|Linux/.test(navigator.userAgent) && !/Mobile/.test(navigator.userAgent)) install.hidden = false;
|
|
1557
|
+
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }
|
|
1558
|
+
function showConn() {
|
|
1559
|
+
var note = connectionNote(failed, navigator.onLine !== false, RETRY_S, loaded);
|
|
1560
|
+
strip.hidden = !note;
|
|
1561
|
+
if (!note) return;
|
|
1562
|
+
if (stripText.textContent !== note.text) stripText.textContent = note.text;
|
|
1563
|
+
retry.hidden = !note.retry;
|
|
1564
|
+
}
|
|
1565
|
+
window.addEventListener('online', function () { failed = false; showConn(); load(); });
|
|
1566
|
+
window.addEventListener('offline', function () { failed = true; showConn(); });
|
|
1567
|
+
retry.addEventListener('click', function () { load(); });
|
|
1568
|
+
function get(url) {
|
|
1569
|
+
var ac = new AbortController();
|
|
1570
|
+
var giveUp = setTimeout(function () { ac.abort(); }, GIVE_UP_MS);
|
|
1571
|
+
return fetch(url, { credentials: 'same-origin', cache: 'no-store', signal: ac.signal }).then(function (r) {
|
|
1572
|
+
if (r.status === 401 || r.status === 403) { location.replace('/member'); return null; }
|
|
1573
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
1574
|
+
return r.json();
|
|
1575
|
+
}).then(function (j) { clearTimeout(giveUp); return j; }, function (e) { clearTimeout(giveUp); throw e; });
|
|
1576
|
+
}
|
|
1577
|
+
function where(r) {
|
|
1578
|
+
var label = esc(r.where && r.where.label || r.channel || '');
|
|
1579
|
+
if (!label) return '';
|
|
1580
|
+
return r.where && r.where.url ? '<a href="' + esc(r.where.url) + '" target="_blank" rel="noopener noreferrer">' + label + '</a>' : label;
|
|
1581
|
+
}
|
|
1582
|
+
function delivered(ev) {
|
|
1583
|
+
if (!ev) return '';
|
|
1584
|
+
var s = String(ev);
|
|
1585
|
+
var isLink = s.slice(0, 7).toLowerCase() === 'http://' || s.slice(0, 8).toLowerCase() === 'https://';
|
|
1586
|
+
return isLink
|
|
1587
|
+
? '<p class="note"><a href="' + esc(s) + '" target="_blank" rel="noopener noreferrer">What was delivered</a></p>'
|
|
1588
|
+
: '<p class="note"><b>What was delivered:</b> ' + esc(s) + '</p>';
|
|
1589
|
+
}
|
|
1590
|
+
function row(text, note, place, st, when) {
|
|
1591
|
+
return '<li class="row"><p class="text">' + esc(plainPreview(text)) + '</p>' + note +
|
|
1592
|
+
(place ? '<p class="meta"><span>asked on ' + place + '</span></p>' : '') +
|
|
1593
|
+
'<p class="side"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span class="moved">' + when + '</span></p></li>';
|
|
1594
|
+
}
|
|
1595
|
+
function sent(r, now) {
|
|
1596
|
+
var st = clientSentState(r);
|
|
1597
|
+
var when = st.tone === 'work' ? 'started ' + ageText(r.startedAt, now) + ' ago' : ageText(r.finishedAt || r.startedAt, now) + ' ago';
|
|
1598
|
+
return row(r.messagePreview, delivered(r.request && r.request.evidence), where(r), st, when);
|
|
1599
|
+
}
|
|
1600
|
+
function request(r, now) {
|
|
1601
|
+
var st = clientRequestState(r.state);
|
|
1602
|
+
return row(r.text, delivered(r.evidence), where(r), st, ageText(r.closedAt || r.updatedAt || r.createdAt, now) + ' ago');
|
|
1603
|
+
}
|
|
1604
|
+
function show(w, now) {
|
|
1605
|
+
var runs = w.runs || [];
|
|
1606
|
+
var covered = {};
|
|
1607
|
+
runs.forEach(function (r) { if (r.request && r.request.id) covered[r.request.id] = true; });
|
|
1608
|
+
// A request waiting on the owner's side with no turn of the list: shown here, not in a section of its own.
|
|
1609
|
+
var asks = (w.open || []).filter(function (r) { return (r.state === 'waiting_owner' || r.state === 'needs_attention') && !covered[r.id]; });
|
|
1610
|
+
var others = (w.other || []).concat(asks);
|
|
1611
|
+
var tones = runs.map(function (r) { return clientSentState(r).tone; }).concat(others.map(function (r) { return clientRequestState(r.state).tone; }));
|
|
1612
|
+
sum.textContent = clientSummary(tones);
|
|
1613
|
+
asked.innerHTML = runs.map(function (r) { return sent(r, now); }).join('') + others.map(function (r) { return request(r, now); }).join('') ||
|
|
1614
|
+
'<li class="blank"><p>Nothing here yet. When you ask us for something on WhatsApp, Telegram, GitLab or GitHub, it appears here as soon as work on it starts.</p><p>You see when it is being worked on, when it waits on us, and when it is finished.</p></li>';
|
|
1615
|
+
}
|
|
1616
|
+
function loadName() {
|
|
1617
|
+
if (named) return;
|
|
1618
|
+
get('/api/member/me').then(function (me) {
|
|
1619
|
+
if (!me) return;
|
|
1620
|
+
named = true;
|
|
1621
|
+
who.textContent = me.name + ' \xB7 ' + me.device;
|
|
1622
|
+
}).catch(function () { /* the next round asks again */ });
|
|
1623
|
+
}
|
|
1624
|
+
function load() {
|
|
1625
|
+
if (busy) return;
|
|
1626
|
+
busy = true; retry.disabled = true; clearTimeout(timer);
|
|
1627
|
+
loadName();
|
|
1628
|
+
get('/api/member/work').then(function (w) {
|
|
1629
|
+
if (!w) return;
|
|
1630
|
+
failed = false;
|
|
1631
|
+
var now = Date.now();
|
|
1632
|
+
show(w, now);
|
|
1633
|
+
updated.textContent = 'Updated ' + new Date(now).toLocaleTimeString() + '. This page refreshes by itself.';
|
|
1634
|
+
loaded = true;
|
|
1635
|
+
}).catch(function () { failed = true; }).then(function () {
|
|
1636
|
+
busy = false; retry.disabled = false; showConn();
|
|
1637
|
+
timer = setTimeout(load, (failed ? RETRY_S : POLL_S) * 1000);
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
showConn();
|
|
1641
|
+
load();
|
|
1642
|
+
})();
|
|
1643
|
+
`;var Ft="agentx_member",Pc=90*86400,jc=new St,Co=t=>t.replace(/^\[app\]/,"[member]"),Oc=new Te(t=>console.log(Co(t))),Eo=new WeakMap;function Nc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Oc;let e=Eo.get(t.log);return e||Eo.set(t.log,e=new Te(a=>t.log(Co(a)))),e}var To=null;function Ye(t,e=X){try{return To=e().people}catch{return To??t}}async function Io(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new mt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new vt(r.root),limiter:r.pairLimiter??jc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return ue(e,200,"application/manifest+json",fo());if(a===Ta)return ue(e,200,"application/manifest+json",_o());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),ue(e,200,"text/javascript; charset=utf-8",ho);if(a==="/member/icon-192.png")return ue(e,200,"image/png",ze(192),"public, max-age=86400");if(a==="/member/icon-512.png")return ue(e,200,"image/png",ze(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let u=await Lr(t,i);return u.status===200&&e.setHeader("Set-Cookie",Ao(u.token)),u.status===429&&e.setHeader("Retry-After",String(u.retryAfter)),ye(e,u.status,u.body)}let l=$r(Hc(t),i,Mr(t));if(!l.ok){if(l.status===401){let u=Aa(t);return Nc(r).record(a.slice(0,120),Ot(t,Be(Ca(t,Ft),o),u?Be(u,o):null)),a==="/member"?ue(e,401,"text/html; charset=utf-8",vo()):ye(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?ue(e,202,"text/html; charset=utf-8",bo()):ye(e,403,{error:l.error,waiting:!0})}let c=r.people().find(u=>u.id===l.personId),p=c?.role==="client";if(n==="GET"&&a==="/member"){let u=Ca(t,Ft);return u&&!Aa(t)&&e.setHeader("Set-Cookie",Ao(u)),ue(e,200,"text/html; charset=utf-8",p?So():xo())}if(n==="GET"&&a==="/api/member/me")return ye(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 u=r.db?.()??null;if(!u)return ye(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),h=Yr(u,l.personId,{now:m,linkFor:r.linkFor}),_=(g,d)=>{let f=d instanceof Error?d.message:String(d);/no such table/i.test(f)||r.log?.(`[member] ${g} failed: ${f}`)},v={byAgent:new Map,mine:[]};try{v=Zr(u,l.personId,{linkFor:r.linkFor})}catch(g){_("the line",g)}let S=[];if(p)return ye(e,200,{...Dc(h),agents:S});try{let g=eo(u,c??{id:l.personId},m);S=to(u,l.personId,g,{people:r.people(),linkFor:r.linkFor,queue:v.byAgent})}catch(g){_("agent cards",g)}return ye(e,200,{...h,agents:S,queued:v.mine})}return ye(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 Ao(t){return`${Ft}=${t}; Path=/; Max-Age=${Pc}; HttpOnly; Secure; SameSite=Lax`}function Hc(t){return Aa(t)??Ca(t,Ft)}function Aa(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ca(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 ue(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function ye(t,e,a){return ue(t,e,"application/json",JSON.stringify(a))}tc();var Mo='/*! 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 Wt,readFileSync as Do,writeFileSync as Ho,rmSync as ug,mkdirSync as Wc,copyFileSync as Gc,readdirSync as Xc}from"fs";import{resolve as Fe}from"path";ac();function Ro(t){let e=lt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:lt.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 Ut(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=lt.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 Lo=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function $o(t){return Ut(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 Po(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ut((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:Lo(t?.chats),senders:Lo(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 jo(t){let e=String(t?.id??"");return Ut(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 Oo(t){let e=String(t?.id??"");return Ut(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}"`})}ut();var de={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function No(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=be({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Mt([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+zc()+br,css:Fc,scripts:`${e}<script>${yr}
|
|
1644
|
+
${wr}
|
|
1645
|
+
${Bc}
|
|
1646
|
+
${Uc}</script>`})}var Bc=`
|
|
1503
1647
|
(function(){
|
|
1504
1648
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1505
1649
|
async function voiceMissing() {
|
|
@@ -1593,8 +1737,8 @@ ${Ac}</script>`})}var _c=`
|
|
|
1593
1737
|
refresh();
|
|
1594
1738
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1595
1739
|
document.addEventListener('ax-config-saved', refresh);
|
|
1596
|
-
})();`;function
|
|
1597
|
-
`:"";return
|
|
1740
|
+
})();`;function zc(){let t=rr().business?`<button data-tab="business">Business</button>
|
|
1741
|
+
`:"";return qc.replace("__BUSINESS_TABS__",t)}var qc=`
|
|
1598
1742
|
<div id="peer-banner" class="peer-banner">
|
|
1599
1743
|
<span class="label">Managing</span>
|
|
1600
1744
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -1846,10 +1990,10 @@ ${Ac}</script>`})}var _c=`
|
|
|
1846
1990
|
</div>
|
|
1847
1991
|
</details>
|
|
1848
1992
|
|
|
1849
|
-
<div id="ch-chatapps-label">${
|
|
1993
|
+
<div id="ch-chatapps-label">${Lt({label:"Chat apps"})}</div>
|
|
1850
1994
|
<div class="ax-connectors" id="ch-chatapps"></div>
|
|
1851
1995
|
|
|
1852
|
-
<div id="ch-devtools-label">${
|
|
1996
|
+
<div id="ch-devtools-label">${Lt({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
|
|
1853
1997
|
<div class="ax-connectors" id="ch-devtools"></div>
|
|
1854
1998
|
|
|
1855
1999
|
<!-- Active-channel configuration panes. One shows at a time; clicking
|
|
@@ -2010,7 +2154,7 @@ ${Ac}</script>`})}var _c=`
|
|
|
2010
2154
|
${K({icon:de.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
|
|
2011
2155
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
2012
2156
|
${re({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
|
|
2013
|
-
${
|
|
2157
|
+
${Lt({label:"Connected peers"})}
|
|
2014
2158
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
2015
2159
|
<div class="add-form">
|
|
2016
2160
|
<h3>Add a peer</h3>
|
|
@@ -2253,7 +2397,7 @@ ${Ac}</script>`})}var _c=`
|
|
|
2253
2397
|
<div class="hint-block">Every setting is documented in the <code>docs/reference/config.md</code> reference. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
|
|
2254
2398
|
</section>
|
|
2255
2399
|
</main>
|
|
2256
|
-
`,
|
|
2400
|
+
`,Fc=`
|
|
2257
2401
|
|
|
2258
2402
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
2259
2403
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2461,7 +2605,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2461
2605
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2462
2606
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2463
2607
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2464
|
-
`,
|
|
2608
|
+
`,Uc=`
|
|
2465
2609
|
const $ = (id) => document.getElementById(id);
|
|
2466
2610
|
let state = null;
|
|
2467
2611
|
|
|
@@ -5345,11 +5489,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
5345
5489
|
})();
|
|
5346
5490
|
|
|
5347
5491
|
refresh();
|
|
5348
|
-
`;function Ao(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(So({peers:a,localToken:n}))}async function Co(t,e){let a=ka();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Io(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Uc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Lc(t),r={"GET /api/admin/state":()=>$c(),"POST /api/admin/agents":()=>Hc(n),"PATCH /api/admin/agents":()=>Bc(n),"DELETE /api/admin/agents":()=>zc(n),"POST /api/admin/agents/access":()=>Pc(n),"POST /api/admin/channels/telegram":()=>qc(n),"DELETE /api/admin/channels/telegram":()=>ud(n),"POST /api/admin/channels/telegram/toggle":()=>md(n),"POST /api/admin/crons":()=>fd(n),"DELETE /api/admin/crons":()=>hd(n),"POST /api/admin/config/raw":()=>gd(n),"GET /api/admin/tokens":()=>jc(),"POST /api/admin/tokens":()=>Oc(n),"DELETE /api/admin/tokens":()=>Nc(n),"POST /api/admin/agents/test":()=>Dc(n),"POST /api/admin/agents/integrations":()=>Vc(n),"DELETE /api/admin/agents/integrations":()=>Yc(n),"PATCH /api/admin/agents/integrations":()=>Qc(n),"PATCH /api/admin/channels/telegram":()=>Fc(n),"POST /api/admin/channels/slack":()=>od(n),"POST /api/admin/channels/slack/toggle":()=>sd(n),"POST /api/admin/channels/discord":()=>id(n),"POST /api/admin/channels/discord/toggle":()=>ld(n),"POST /api/admin/channels/gitlab":()=>cd(n),"POST /api/admin/channels/gitlab/toggle":()=>dd(n),"POST /api/admin/channels/request-status":()=>Tr(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>Id(n),"DELETE /api/admin/actions":()=>Md(n),"POST /api/admin/actions/run":()=>Ld(n),"GET /api/admin/channels/whatsapp/chats":()=>Je("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Je("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ue("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>pd(n),"POST /api/admin/webhooks":()=>Zc(n),"PATCH /api/admin/webhooks":()=>ed(n),"DELETE /api/admin/webhooks":()=>rd(n),"POST /api/admin/whatsapp-triage":()=>yo(n),"POST /api/admin/whatsapp-triage/rules":()=>wo(n),"PATCH /api/admin/whatsapp-triage/rules":()=>ko(n),"DELETE /api/admin/whatsapp-triage/rules":()=>_o(n),"POST /api/admin/mesh/peers":()=>td(n),"DELETE /api/admin/mesh/peers":()=>ad(n),"POST /api/admin/mesh/toggle":()=>nd(n),"GET /api/admin/files":()=>Wc(t),"GET /api/admin/files/read":()=>Gc(t),"PUT /api/admin/files":()=>Xc(n),"POST /api/admin/files/skill":()=>Kc(n),"DELETE /api/admin/files/skill":()=>Jc(n),"POST /api/admin/business/orgchart":()=>xd(n),"DELETE /api/admin/business/orgchart":()=>vd(n),"POST /api/admin/business/project":()=>bd(n),"DELETE /api/admin/business/project":()=>kd(n),"POST /api/admin/business/client":()=>yd(n),"DELETE /api/admin/business/client":()=>wd(n),"POST /api/admin/business/contact":()=>_d(n),"DELETE /api/admin/business/contact":()=>Sd(n),"POST /api/admin/boards":()=>Ed(n),"DELETE /api/admin/boards":()=>Td(n),"POST /api/admin/boards/columns":()=>Ad(n),"DELETE /api/admin/boards/columns":()=>Cd(n),"POST /api/admin/notifications":()=>$d(n),"POST /api/admin/screen":()=>Pd(n),"POST /api/admin/webhooks/triggers":()=>jd(n),"POST /api/admin/mesh/health":()=>Rd(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ue("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ue("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ue("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ue("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ue("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ue("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ue("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ue("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ya(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ya(e,200,i)}catch(n){ya(e,400,{error:n.message||"admin op failed"})}}function ya(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Lc(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function Rc(t){let e=ze(process.cwd(),t);if(!Bt(e))return[];let a=[];for(let n of Mc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Eo(ze(e,n.name),"utf-8")))}catch{}return a}function ka(){let t=ze(process.cwd(),"agentx.json");return Bt(t)?JSON.parse(Eo(t,"utf-8")):null}function $c(){let t=ka();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([p,f])=>({id:p,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let b=x.credentials||{},_={};for(let[T,w]of Object.entries(b))typeof w=="string"&&/^[A-Z][A-Z0-9_]*$/.test(w)?_[T]=process.env[w]?"set":"unset":typeof w=="string"&&(_[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:b,credStatus:_,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([p,f])=>({id:p,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([p,f])=>({id:p,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(p=>({id:p.id,source:p.source,agentId:p.agentId,secretEnv:p.secretEnv||"",description:p.description||"",enabled:p.enabled!==!1,triggers:p.triggers&&typeof p.triggers=="object"?p.triggers:{},defaultWorkflow:p.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(p=>({url:p.url,name:p.name,hasToken:!!p.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},k=t.notifications||{},v={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:Rn(k.local),ntfy:Cr(t.channels?.ntfy)},S=[];try{S=Rc(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(p=>({id:p.id,name:p.name,source:p.source||{type:"gitlab",projects:[]},primaryToolLabel:p.primaryToolLabel||"",timeRangeDays:p.timeRangeDays??30,closedWindowDays:p.closedWindowDays??30,columns:Array.isArray(p.columns)?p.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Er(t),whatsappTriage:bo(t),crons:l,webhooks:c,mesh:d,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:v,screen:or(t.screen),actions:S}}function Pc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function jc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function Oc(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Nc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Dc(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 Hc(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=Lo(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ze(process.cwd(),"agents",e),{summary:l}=A(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),d.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Bt(c))try{Cc(i,{recursive:!0}),To(c,`# ${a}
|
|
5492
|
+
`;function Bo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(No({peers:a,localToken:n}))}async function zo(t,e){let a=La();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function qo(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await id(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":()=>ad(n),"PATCH /api/admin/agents":()=>nd(n),"DELETE /api/admin/agents":()=>rd(n),"POST /api/admin/agents/access":()=>Yc(n),"POST /api/admin/channels/telegram":()=>od(n),"DELETE /api/admin/channels/telegram":()=>Id(n),"POST /api/admin/channels/telegram/toggle":()=>Md(n),"POST /api/admin/crons":()=>Ld(n),"DELETE /api/admin/crons":()=>Rd(n),"POST /api/admin/config/raw":()=>$d(n),"GET /api/admin/tokens":()=>Qc(),"POST /api/admin/tokens":()=>Zc(n),"DELETE /api/admin/tokens":()=>ed(n),"POST /api/admin/agents/test":()=>td(n),"POST /api/admin/agents/integrations":()=>md(n),"DELETE /api/admin/agents/integrations":()=>fd(n),"PATCH /api/admin/agents/integrations":()=>hd(n),"PATCH /api/admin/channels/telegram":()=>sd(n),"POST /api/admin/channels/slack":()=>kd(n),"POST /api/admin/channels/slack/toggle":()=>_d(n),"POST /api/admin/channels/discord":()=>Sd(n),"POST /api/admin/channels/discord/toggle":()=>Ed(n),"POST /api/admin/channels/gitlab":()=>Td(n),"POST /api/admin/channels/gitlab/toggle":()=>Ad(n),"POST /api/admin/channels/request-status":()=>Or(n),"GET /api/admin/channels/whatsapp/state":()=>Qe("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Qe("/webrtc/history"),"POST /api/admin/actions":()=>Gd(n),"DELETE /api/admin/actions":()=>Xd(n),"POST /api/admin/actions/run":()=>Kd(n),"GET /api/admin/channels/whatsapp/chats":()=>Qe("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Qe("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Cd(n),"POST /api/admin/webhooks":()=>gd(n),"PATCH /api/admin/webhooks":()=>xd(n),"DELETE /api/admin/webhooks":()=>wd(n),"POST /api/admin/whatsapp-triage":()=>$o(n),"POST /api/admin/whatsapp-triage/rules":()=>Po(n),"PATCH /api/admin/whatsapp-triage/rules":()=>jo(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Oo(n),"POST /api/admin/mesh/peers":()=>vd(n),"DELETE /api/admin/mesh/peers":()=>bd(n),"POST /api/admin/mesh/toggle":()=>yd(n),"GET /api/admin/files":()=>ld(t),"GET /api/admin/files/read":()=>cd(t),"PUT /api/admin/files":()=>dd(n),"POST /api/admin/files/skill":()=>pd(n),"DELETE /api/admin/files/skill":()=>ud(n),"POST /api/admin/business/orgchart":()=>Pd(n),"DELETE /api/admin/business/orgchart":()=>jd(n),"POST /api/admin/business/project":()=>Od(n),"DELETE /api/admin/business/project":()=>Hd(n),"POST /api/admin/business/client":()=>Nd(n),"DELETE /api/admin/business/client":()=>Dd(n),"POST /api/admin/business/contact":()=>Bd(n),"DELETE /api/admin/business/contact":()=>zd(n),"POST /api/admin/boards":()=>qd(n),"DELETE /api/admin/boards":()=>Fd(n),"POST /api/admin/boards/columns":()=>Ud(n),"DELETE /api/admin/boards/columns":()=>Wd(n),"POST /api/admin/notifications":()=>Vd(n),"POST /api/admin/screen":()=>Yd(n),"POST /api/admin/webhooks/triggers":()=>Qd(n),"POST /api/admin/mesh/health":()=>Jd(n),"GET /api/admin/projects":()=>Qe("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Ia(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Ia(e,200,i)}catch(n){Ia(e,400,{error:n.message||"admin op failed"})}}function Ia(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=Fe(process.cwd(),t);if(!Wt(e))return[];let a=[];for(let n of Xc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Do(Fe(e,n.name),"utf-8")))}catch{}return a}function La(){let t=Fe(process.cwd(),"agentx.json");return Wt(t)?JSON.parse(Do(t,"utf-8")):null}function Vc(){let t=La();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,f])=>({id:d,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let b=x.credentials||{},k={};for(let[T,w]of Object.entries(b))typeof w=="string"&&/^[A-Z][A-Z0-9_]*$/.test(w)?k[T]=process.env[w]?"set":"unset":typeof w=="string"&&(k[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:b,credStatus:k,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,f])=>({id:d,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,f])=>({id:d,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},_=t.notifications||{},v={longTaskThreshold:_.longTaskThreshold??30,destination:_.destination||null,on:{taskComplete:_.on?.taskComplete!==!1,taskError:_.on?.taskError!==!1,taskQueued:!!_.on?.taskQueued},local:qn(_.local),ntfy:Dr(t.channels?.ntfy)},S=[];try{S=Jc(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:jr(t),whatsappTriage:Ro(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:v,screen:hr(t.screen),actions:S}}function Yc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function Qc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function 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 F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function ed(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function td(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function ad(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=Uo(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=Fe(process.cwd(),"agents",e),{summary:l}=A(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),c=Fe(i,"CLAUDE.md");if(!Wt(c))try{Wc(i,{recursive:!0}),Ho(c,`# ${a}
|
|
5349
5493
|
|
|
5350
5494
|
${s||"You are "+a+"."}
|
|
5351
|
-
`)}catch{}return{summary:l}}function Bc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=Lo(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function zc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function qc(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=A(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Fc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Je(t){let{url:e,headers:a}=_a(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ue(t,e){let{url:a,headers:n}=_a(),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 Uc(t,e){try{let{url:a,headers:n}=_a(),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 _a(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ve(t){let a=ka()?.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 wa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Wc(t){let e=wa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Gc(t){let e=wa(t,"agent").trim(),a=wa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return kt(Ve(e),a)}function Xc(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=_t(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Kc(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=St(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Jc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Et(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Vc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Yc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Qc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(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 Mo=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Zc(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(!Mo.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(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 ed(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Mo.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 td(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=A(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function ad(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function nd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function rd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function od(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function sd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function id(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=A(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function ld(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function cd(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=A(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function dd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function pd(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-65SE3WJJ.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 ud(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function md(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function fd(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=A(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function hd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function gd(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ze(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Bt(n))try{Ic(n,r)}catch{}To(n,JSON.stringify(a,null,2)+`
|
|
5352
|
-
`,"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 Lo(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function xd(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function vd(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function bd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=A(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function yd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=A(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function wd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function kd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function _d(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=A(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function Sd(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=A(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function Ed(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(u=>u.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...d,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function Td(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Ad(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=A(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let d=l.columns.findIndex(u=>u.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 Cd(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=A(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Id(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 Md(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function Ld(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function Rd(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=A(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function $d(t){let{summary:e}=A(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=$n(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=Ir(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function Pd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=sr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function jd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ct();import{resolve as Dd}from"path";function Ro(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5495
|
+
`)}catch{}return{summary:l}}function nd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=Uo(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function rd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function od(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=A(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function sd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Qe(t){let{url:e,headers:a}=Ra(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function me(t,e){let{url:a,headers:n}=Ra(),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 id(t,e){try{let{url:a,headers:n}=Ra(),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 Ra(){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 Ze(t){let a=La()?.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 Ma(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ld(t){let e=Ma(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ze(e));return{agentId:e,...a}}function cd(t){let e=Ma(t,"agent").trim(),a=Ma(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Et(Ze(e),a)}function dd(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=Tt(Ze(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function pd(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=At(Ze(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function ud(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=Ct(Ze(e),a);return{summary:`removed skill "${a}"`,...n}}function md(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function fd(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function hd(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Fo=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function gd(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(!Fo.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function xd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Fo.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 vd(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=A(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function bd(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function yd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function wd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function kd(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function _d(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function Sd(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=A(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Ed(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Td(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=A(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function Ad(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function Cd(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-3LEHZHWJ.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 Id(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function Md(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function Ld(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=A(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function Rd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function $d(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=Fe(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Wt(n))try{Gc(n,r)}catch{}Ho(n,JSON.stringify(a,null,2)+`
|
|
5496
|
+
`,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function Uo(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Pd(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function jd(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function Od(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=A(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function Nd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=A(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function Dd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function Hd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function Bd(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=A(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function zd(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=A(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function qd(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Fd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Ud(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=A(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Wd(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=A(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Gd(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 Xd(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 Kd(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 Jd(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=A(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function Vd(t){let{summary:e}=A(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=Fn(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=Hr(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function Yd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=gr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Qd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ut();import{resolve as tp}from"path";function Wo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5353
5497
|
|
|
5354
5498
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
5355
5499
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -5404,7 +5548,7 @@ ${s||"You are "+a+"."}
|
|
|
5404
5548
|
<h2>Recent classifications</h2>
|
|
5405
5549
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
5406
5550
|
<div id="recent"></div>
|
|
5407
|
-
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5551
|
+
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Zd,scripts:`${e}<script>${ep}</script>`})}var Zd=`
|
|
5408
5552
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
5409
5553
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
5410
5554
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5508,7 +5652,7 @@ details {
|
|
|
5508
5652
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5509
5653
|
}
|
|
5510
5654
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5511
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
5655
|
+
details[open] summary { margin-bottom: 8px; }`,ep=`
|
|
5512
5656
|
const $ = (id) => document.getElementById(id);
|
|
5513
5657
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5514
5658
|
|
|
@@ -5728,7 +5872,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5728
5872
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5729
5873
|
|
|
5730
5874
|
refresh();
|
|
5731
|
-
`;function
|
|
5875
|
+
`;function Xo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wo({peers:a,localToken:n}))}async function Ko(t,e,a){try{let n=t.method==="GET"?void 0:await dp(t),r=ap(),o={"GET /api/admin/graph/state":()=>np(r),"POST /api/admin/graph/classifications/approve":()=>rp(r,n),"POST /api/admin/graph/classifications/reject":()=>op(r,n),"POST /api/admin/graph/nodes":()=>sp(r,n),"PATCH /api/admin/graph/nodes":()=>ip(r,n),"DELETE /api/admin/graph/nodes":()=>lp(r,n),"PUT /api/admin/graph/schema":()=>cp(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){$a(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();$a(e,200,l)}catch(n){$a(e,400,{error:n?.message||"graph op failed"})}}function ap(){let t=X(),e=tp(process.cwd(),t.graph.baseDir);return new In({baseDir:e})}function np(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 rp(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Jo(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=Pa(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function op(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Jo(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Jo(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 sp(t,e){let a=Go(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Go(String(e.parentId)):null,o=Pa({[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 ip(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Pa({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function lp(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function cp(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 Pa(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 Go(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function $a(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function dp(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 Vo=`
|
|
5732
5876
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
5733
5877
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
5734
5878
|
<p class="apv__lead">What you asked agents for that is not finished, oldest first. Reply, hand it to an agent, close it as done, or drop it. Nothing leaves this list by getting old.</p>
|
|
@@ -5745,7 +5889,7 @@ refresh();
|
|
|
5745
5889
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5746
5890
|
</form>
|
|
5747
5891
|
</details>
|
|
5748
|
-
</section>`,
|
|
5892
|
+
</section>`,Yo=`
|
|
5749
5893
|
.apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
|
|
5750
5894
|
.apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
|
|
5751
5895
|
.apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
|
|
@@ -5767,7 +5911,7 @@ refresh();
|
|
|
5767
5911
|
.apv__req select { min-height: 40px; max-width: 100%; }
|
|
5768
5912
|
.apv__mic.is-on { border-color: var(--ax-err); color: var(--ax-err); }
|
|
5769
5913
|
.apv__acts + .apv__acts { margin-top: 8px; }
|
|
5770
|
-
`,
|
|
5914
|
+
`,Qo=`
|
|
5771
5915
|
(function(){
|
|
5772
5916
|
var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
|
|
5773
5917
|
function $(id){ return document.getElementById(id); }
|
|
@@ -5909,7 +6053,7 @@ function busy(){
|
|
|
5909
6053
|
}
|
|
5910
6054
|
setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
|
|
5911
6055
|
})();
|
|
5912
|
-
`;function
|
|
6056
|
+
`;function Zo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
5913
6057
|
<header class="apv__head">
|
|
5914
6058
|
<div>
|
|
5915
6059
|
<h1>Approvals</h1>
|
|
@@ -5931,7 +6075,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
|
|
|
5931
6075
|
<ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
|
|
5932
6076
|
<p id="apv-snoozed" class="apv__foot"></p>
|
|
5933
6077
|
|
|
5934
|
-
${
|
|
6078
|
+
${Vo}
|
|
5935
6079
|
|
|
5936
6080
|
<details class="apv__settings" id="apv-settings">
|
|
5937
6081
|
<summary>Settings: expiry, later, daily digest</summary>
|
|
@@ -5946,7 +6090,7 @@ ${No}
|
|
|
5946
6090
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5947
6091
|
</form>
|
|
5948
6092
|
</details>
|
|
5949
|
-
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
6093
|
+
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:pp+Yo,scripts:`${e}<script>${up}</script><script>${Qo}</script>`})}var pp=`
|
|
5950
6094
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
5951
6095
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
5952
6096
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -5995,7 +6139,7 @@ ${No}
|
|
|
5995
6139
|
@media (max-width: 560px) {
|
|
5996
6140
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
5997
6141
|
}
|
|
5998
|
-
`,
|
|
6142
|
+
`,up=`
|
|
5999
6143
|
(function(){
|
|
6000
6144
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
6001
6145
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -6062,7 +6206,7 @@ function item(i){
|
|
|
6062
6206
|
if (i.more) more.push('<p>Full record: <code>' + esc(i.more) + '</code></p>');
|
|
6063
6207
|
more.push('<p>Yes: ' + esc(i.yes) + '. No: ' + esc(i.no) + '.</p>');
|
|
6064
6208
|
return '<li class="apv__item" data-key="' + esc(i.key) + '">'
|
|
6065
|
-
+ '<div class="apv__meta"><span class="apv__kind">' + esc(LABEL[i.kind] || i.kind) + '</span><span>from ' + esc(i.raised_by) + '</span>'
|
|
6209
|
+
+ '<div class="apv__meta"><span class="apv__kind">' + esc(LABEL[i.kind] || i.kind) + '</span><span>from ' + esc(i.raised_by) + (i.node ? ' on ' + esc(i.node) : '') + '</span>'
|
|
6066
6210
|
+ (i.created_at ? '<span>' + esc(rel(i.created_at)) + '</span>' : '')
|
|
6067
6211
|
+ (i.snoozed_until ? '<span>put off until ' + esc(new Date(i.snoozed_until).toLocaleString()) + '</span>' : '') + '</div>'
|
|
6068
6212
|
+ '<h2 class="apv__title">' + esc(i.title) + '</h2>'
|
|
@@ -6163,20 +6307,20 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
6163
6307
|
load();
|
|
6164
6308
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
6165
6309
|
})();
|
|
6166
|
-
`;import{existsSync as
|
|
6310
|
+
`;import{existsSync as mp,readFileSync as fp}from"fs";var Ae="/api/admin/approvals/requests";function es(t){let e=jn(t);if(!mp(e))return[];try{let a=JSON.parse(fp(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 ts=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function as(t,e,a,n){try{return await hp(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function hp(t,e,a,n){if(t==="GET"&&e===Ae){let o=yt(n);return{status:200,body:{items:o?o.listOpen().map(s=>Yn(s,o)):[],agents:es(n.configPath),settings:bt(n.configPath)}}}let r=e===`${Ae}/reply`?"reply":e===`${Ae}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=yt(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",u=es(n.configPath).find(h=>h.id===p);if(r==="handoff"&&!u)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!bt(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,p,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=u?.name??p;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===`${Ae}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=yt(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Ae}/settings`){let o={},s=l=>{let c=a[l];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${l} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=ts(a.from),o.channels=ts(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i=await Xn(o,{configPath:n.configPath,reload:n.reload});return i.success?{status:200,body:{ok:!0,settings:bt(n.configPath)}}:{status:400,body:{error:i.error}}}return{status:404,body:{error:"Not found"}}}var gp=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Gt(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 ns(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Zo({peers:e,localToken:a}))}async function rs(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Ae)){let i=await as(o,a,o==="POST"?await Gt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=wt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:Se(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Gt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!gp.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Se(s.configPath),u=await kt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(te(e,200,{ok:!0,message:u.message}),!0):(te(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Gt(t),l=Qn(s,typeof i.key=="string"?i.key:"",!!Se(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 Gt(t),l={},c=u=>{let m=i[u];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${u} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let m=Ar(u);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await Cr(l,{configPath:s.configPath,reload:s.reload});return p.success?(te(e,200,{ok:!0,settings:Se(s.configPath)}),!0):(te(e,400,{error:p.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}ua();function os(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=be({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates, your clients and guests. Open a person to see the machines they paired and what they asked for."})+`
|
|
6167
6311
|
<div class="pp">
|
|
6168
6312
|
<div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
|
|
6169
6313
|
<section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
|
|
6170
6314
|
<h2 id="pp-none-title">Nobody has paired a machine yet</h2>
|
|
6171
|
-
<p>A teammate gets one page of their own, <b>My work</b>, on a machine you approve. To invite someone, from the folder that holds <code>agentx.json</code>:</p>
|
|
6315
|
+
<p>A teammate gets one page of their own, <b>My work</b>, on a machine you approve. A client gets <b>Your project</b> instead. To invite someone, from the folder that holds <code>agentx.json</code>:</p>
|
|
6172
6316
|
<ol>
|
|
6173
|
-
<li>List them, with the identity they write from: <code>agentx people add sara --name "Sara B" --identity gitlab:sara.b</code
|
|
6317
|
+
<li>List them, with the identity they write from: <code>agentx people add sara --name "Sara B" --identity gitlab:sara.b</code>. For a client, add <code>--role client</code>.</li>
|
|
6174
6318
|
<li>Make their one-time code: <code>agentx people invite sara</code></li>
|
|
6175
6319
|
<li>Send them the address and the code it prints, then say yes to their machine in <a href="/approvals">Approvals</a>.</li>
|
|
6176
6320
|
</ol>
|
|
6177
6321
|
</section>
|
|
6178
6322
|
<ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
|
|
6179
|
-
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:
|
|
6323
|
+
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:xp,scripts:`${e}<script>${vp}</script>`})}var xp=`
|
|
6180
6324
|
.pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
|
|
6181
6325
|
.pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
|
|
6182
6326
|
.pp-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -6217,14 +6361,14 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6217
6361
|
.pp-text { overflow-wrap: anywhere; }
|
|
6218
6362
|
.pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
6219
6363
|
@media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
|
|
6220
|
-
`,
|
|
6364
|
+
`,vp=`
|
|
6221
6365
|
(function () {
|
|
6222
6366
|
var list = document.getElementById('pp-list');
|
|
6223
6367
|
var msg = document.getElementById('pp-msg');
|
|
6224
6368
|
var none = document.getElementById('pp-none');
|
|
6225
6369
|
var open = {}; // person id -> the last detail loaded for it
|
|
6226
6370
|
var people = [];
|
|
6227
|
-
var ROLE = { owner: 'Owner', member: 'Member', guest: 'Guest' };
|
|
6371
|
+
var ROLE = { owner: 'Owner', member: 'Member', client: 'Client', guest: 'Guest' };
|
|
6228
6372
|
var REQUEST = {
|
|
6229
6373
|
in_progress: ['In progress', 'ok'], waiting_owner: ['Waiting on you', 'warn'], waiting_other: ['Waiting on another agent', 'warn'],
|
|
6230
6374
|
needs_attention: ['Needs attention', 'bad'], done: ['Done', 'off'], declined: ['Declined', 'off'], dropped: ['Dropped', 'off']
|
|
@@ -6355,7 +6499,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6355
6499
|
load();
|
|
6356
6500
|
setInterval(load, 30000);
|
|
6357
6501
|
})();
|
|
6358
|
-
`;var
|
|
6502
|
+
`;var ja="/api/admin/people";function bp(t,e){let a=Rr(t,e);return a?{...e,answer:a}:e}function yp(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function wp(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&yp(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:pt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var kp=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function ss(t,e,a,n){if(a!=="/people"&&a!==ja&&!a.startsWith(`${ja}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(fe(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 fe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(p=>bp(n.root,p)),s=()=>wp(n.people(),o());if(r==="GET"&&a===ja){let c=s();return fe(e,200,{people:c,paired:c.reduce((p,u)=>p+u.machines.active+u.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(h=>h.id===i[1]);if(!c)return fe(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),u=[],m=[];try{p&&(u=Ir(p,c.id))}catch{}try{p&&(m=Rt(p,c.id,20))}catch{}return fe(e,200,{person:c,devices:o(c.id).sort(kp),requests:u,runs:m,database:!!p}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,c,p]=l,u=n.members.byToken(p);if(!u||u.personId!==c)return fe(e,404,{error:"no such machine for this person"}),!0;if(u.state==="removed")return fe(e,409,{error:"this machine's access has already ended"}),!0;let m=Pr({tokens:n.tokens??new F,members:n.members,now:n.now},p,"removed by the owner (dashboard)");return fe(e,200,{ok:!0,device:m}),!0}return fe(e,404,{error:"not found"}),!0}import{resolve as Ap}from"path";import{existsSync as Cp}from"fs";import Ip from"better-sqlite3";var is=new WeakSet;function _p(t,e,a={}){if(is.has(t))return;is.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let c=i[l].bind(i);i[l]=(...p)=>{let u=r();try{return c(...p)}finally{let m=r()-u;m>=n&&e({sql:s,ms:m})}}}return i}}function Sp(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function we(t,e){_p(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Sp(a)}`))}function ls(t={}){let e=`<div class="ax-obs">
|
|
6359
6503
|
<header class="ax-obs__head">
|
|
6360
6504
|
<h1>Health</h1>
|
|
6361
6505
|
<p class="ax-obs__sub">Platform-health view: what each agent ran, what failed, and how the router decided. <span class="ax-obs__sub-link">Spend lives on the <a href="/admin/cost">Cost</a> page.</span></p>
|
|
@@ -6477,7 +6621,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6477
6621
|
</div>
|
|
6478
6622
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
6479
6623
|
</section>
|
|
6480
|
-
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6624
|
+
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ep,scripts:`<script>${Tp}</script>`})}var Ep=`
|
|
6481
6625
|
.ax-obs { padding: 16px 24px; }
|
|
6482
6626
|
.ax-obs__head { margin-bottom: 16px; }
|
|
6483
6627
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -6594,7 +6738,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6594
6738
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
6595
6739
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
6596
6740
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
6597
|
-
`,
|
|
6741
|
+
`,Tp=`
|
|
6598
6742
|
(function(){
|
|
6599
6743
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
6600
6744
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -6978,23 +7122,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6978
7122
|
|
|
6979
7123
|
load(current);
|
|
6980
7124
|
})();
|
|
6981
|
-
`;var
|
|
7125
|
+
`;var ps={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 us(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Oa(t){let e=ps[us(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 Mp(){let t=Ap(process.cwd(),".agentx/db.sqlite");if(!Cp(t))return null;try{let e=new Ip(t,{readonly:!0,fileMustExist:!0});return we(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function ms(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ls({peers:a}))}function Lp(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 he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function fs(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Mp();if(!r)return he(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Lp(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6982
7126
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
6983
7127
|
FROM route_traces
|
|
6984
7128
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6985
7129
|
ORDER BY at DESC LIMIT @limit
|
|
6986
|
-
`,
|
|
7130
|
+
`,p=r.db.prepare(c).all(l);return he(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6987
7131
|
SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
|
|
6988
7132
|
FROM rotations
|
|
6989
7133
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6990
7134
|
ORDER BY rotated_at DESC LIMIT @limit
|
|
6991
|
-
`,
|
|
7135
|
+
`,p=r.db.prepare(c).all(l);return he(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6992
7136
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
6993
7137
|
FROM task_history
|
|
6994
7138
|
WHERE ${i.join(" AND ")}
|
|
6995
7139
|
ORDER BY started_at DESC LIMIT @limit
|
|
6996
|
-
`,u=r.db.prepare(c).all(l).map(m=>({...m,plain:
|
|
6997
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
7140
|
+
`,u=r.db.prepare(c).all(l).map(m=>({...m,plain:hs(m.error)}));return he(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return he(e,200,Rp(r.db)),!0;if(n==="activity")return he(e,200,$p(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=cs(i.searchParams.get("range"));return he(e,200,ds(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=cs(i.searchParams.get("range")),c=ds(r.db,l),p=Pp(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return he(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return he(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function hs(t){let e=String(t||"");return e?/timed out|SIGTERM|exit 143|maxExecutionMinutes/i.test(e)?"Agent ran past its time limit":/ECONNREFUSED|fetch failed|getaddrinfo|ENOTFOUND/i.test(e)?"Couldn't reach a service over the network":/401|403|Unauthorized|Forbidden|invalid token|missing scope/i.test(e)?"Authentication or permission denied":/rate limit|429|too many requests/i.test(e)?"Hit a rate limit (too many calls)":/quota|insufficient_quota/i.test(e)?"Provider account out of quota or credits":/tier-?2|tier two|200K|200,000/i.test(e)?"Hit Anthropic tier-2 billing threshold":/JSON|parse|unexpected token/i.test(e)?"Got a response in the wrong shape":/permission denied|EACCES|EPERM/i.test(e)?"File permission denied":/ENOENT|no such file/i.test(e)?"Expected file is missing":/abort|cancel/i.test(e)?"Task was cancelled before it finished":e.split(`
|
|
7141
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Rp(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=w=>p.length?p[Math.min(p.length-1,Math.floor(p.length*w))].duration_ms:0,m=u(.5),h=u(.95),v=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((w,I)=>w+Oa(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((w,I)=>w+Oa(I),0),g=t.prepare(`
|
|
6998
7142
|
SELECT agent_id,
|
|
6999
7143
|
COUNT(*) AS tasks,
|
|
7000
7144
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -7004,7 +7148,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7004
7148
|
WHERE started_at >= ?
|
|
7005
7149
|
GROUP BY agent_id
|
|
7006
7150
|
ORDER BY tasks DESC LIMIT 10
|
|
7007
|
-
`).all(a),
|
|
7151
|
+
`).all(a),d=t.prepare(`
|
|
7008
7152
|
SELECT COALESCE(channel, 'unknown') AS channel,
|
|
7009
7153
|
COUNT(*) AS tasks,
|
|
7010
7154
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -7017,7 +7161,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7017
7161
|
FROM task_history
|
|
7018
7162
|
WHERE status='error' AND started_at >= ?
|
|
7019
7163
|
ORDER BY started_at DESC LIMIT 5
|
|
7020
|
-
`).all(o).map(w=>({...w,plain:
|
|
7164
|
+
`).all(o).map(w=>({...w,plain:hs(w.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:v,spendDelta:v-S,idleAgentCount:b.length},perAgent:g,perChannel:d,idleAgents:b,recentErrors:T}}function $p(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(`
|
|
7021
7165
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
7022
7166
|
COUNT(*) AS tasks,
|
|
7023
7167
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -7044,7 +7188,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7044
7188
|
WHERE started_at >= @since
|
|
7045
7189
|
GROUP BY agent_id
|
|
7046
7190
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
7047
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
7191
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function cs(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 ds(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
7048
7192
|
SELECT day, agent_id, model,
|
|
7049
7193
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
7050
7194
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -7052,20 +7196,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7052
7196
|
FROM usage_daily
|
|
7053
7197
|
${a}
|
|
7054
7198
|
ORDER BY day
|
|
7055
|
-
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,
|
|
7199
|
+
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,u=0,m=0,h=0,_=0,v=0,S=0,g={},d={};for(let E of n){let $=Oa(E),L=us(E.model),j=ps[L],W=(E.tier2_input_tokens||0)/1e6*j.input*.5+(E.tier2_output_tokens||0)/1e6*j.output*.5+(E.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,q=(E.input_tokens||0)+(E.tier2_input_tokens||0),G=(E.output_tokens||0)+(E.tier2_output_tokens||0),ie=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),Oe=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=$,E.day>=s&&(p+=$,_+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,v+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(m+=W),E.day>=s&&(h+=W);let Z=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=E.tasks||0,Z.input+=q,Z.output+=G,Z.cacheRead+=ie,Z.cacheCreate+=Oe,Z.cost+=$,Z.tier2+=W;let z=Z.agents[E.agent_id]||(Z.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});z.tasks+=E.tasks||0,z.cost+=$,z.tier2+=W,z.input+=q,z.output+=G,z.cacheRead+=ie,z.cacheCreate+=Oe,E.model&&(z.model=E.model);let O=d[E.agent_id]||(d[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});O.tasks+=E.tasks||0,O.cost+=$,O.tier2+=W,O.input+=q,O.output+=G,O.cacheRead+=ie,O.cacheCreate+=Oe,E.model&&(O.model=E.model)}let f=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,b=0,k=0,T=0,w=0,I=0;for(let E of f)x+=E.tasks,b+=E.input,k+=E.output,T+=E.cacheRead,w+=E.cacheCreate,I+=E.cost;let C=Object.entries(d).map(([E,$])=>({agent_id:E,...$,tokens:$.input+$.output+$.cacheRead+$.cacheCreate})).sort((E,$)=>$.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:b+k+T+w,cacheHitRange:T+b>0?T/(T+b):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:v>0?(_-v)/v:0},days:f,perAgent:C}}function Pp(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+`
|
|
7056
7200
|
`+a.join(`
|
|
7057
7201
|
`)+`
|
|
7058
|
-
`}import{resolve as
|
|
7202
|
+
`}import{resolve as jp}from"path";import{existsSync as Op}from"fs";import Np from"better-sqlite3";function Dp(){let t=jp(process.cwd(),".agentx/intent/ledger.sqlite");if(!Op(t))return null;try{let e=new Np(t,{readonly:!0,fileMustExist:!0});return we(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-gs>6e4&&(gs=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var gs=0;function Ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Hp(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 xs(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Dp();if(!r)return Ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=Hp(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),_=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,v=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
|
|
7059
7203
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
7060
7204
|
LEFT JOIN intent_resolutions r
|
|
7061
7205
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
7062
7206
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
7063
|
-
`).get().n;return Ce(e,200,{since:s??null,eventsBySource:h,totalDecisions:
|
|
7207
|
+
`).get().n;return Ce(e,200,{since:s??null,eventsBySource:h,totalDecisions:_,decisionsByOutcome:v,totalDivergences:S,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let u=[],m={limit:p};s!==void 0&&(u.push("ts >= @since"),m.since=s),i&&(u.push("source = @source"),m.source=i),l&&(u.push("project = @project"),m.project=l);let h=`
|
|
7064
7208
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
7065
7209
|
FROM intent_events
|
|
7066
7210
|
${u.length?"WHERE "+u.join(" AND "):""}
|
|
7067
7211
|
ORDER BY ts DESC LIMIT @limit
|
|
7068
|
-
`;return Ce(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="divergences"){let u=[],m={limit:
|
|
7212
|
+
`;return Ce(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="divergences"){let u=[],m={limit:p};s!==void 0&&(u.push("ts >= @since"),m.since=s),i&&(u.push("source = @source"),m.source=i);let h=`
|
|
7069
7213
|
SELECT ts, source, decided_by,
|
|
7070
7214
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
7071
7215
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
@@ -7073,7 +7217,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7073
7217
|
FROM intent_divergences
|
|
7074
7218
|
${u.length?"WHERE "+u.join(" AND "):""}
|
|
7075
7219
|
ORDER BY ts DESC LIMIT @limit
|
|
7076
|
-
`;return Ce(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:
|
|
7220
|
+
`;return Ce(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:p};i&&(u.push("e.source = @source"),m.source=i);let h=`
|
|
7077
7221
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
7078
7222
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
7079
7223
|
FROM intent_decisions d
|
|
@@ -7082,7 +7226,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7082
7226
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
7083
7227
|
WHERE ${u.join(" AND ")}
|
|
7084
7228
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
7085
|
-
`;return Ce(e,200,{rows:r.db.prepare(h).all(m)}),!0}return Ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function
|
|
7229
|
+
`;return Ce(e,200,{rows:r.db.prepare(h).all(m)}),!0}return Ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function vs(t={}){return M({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
7086
7230
|
<header class="ax-led__head">
|
|
7087
7231
|
<h1>Intent ledger</h1>
|
|
7088
7232
|
<p class="ax-led__sub">Read-only view over <code>.agentx/intent/ledger.sqlite</code> \u2014 same source as <code>agentx ledger</code>. Replay and lineage live in the CLI for now.</p>
|
|
@@ -7287,7 +7431,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7287
7431
|
}
|
|
7288
7432
|
load();
|
|
7289
7433
|
})();
|
|
7290
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7434
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function bs(t={}){return M({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
7291
7435
|
<header class="ax-cost__head">
|
|
7292
7436
|
<div>
|
|
7293
7437
|
<h1>Cost</h1>
|
|
@@ -7860,7 +8004,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7860
8004
|
load();
|
|
7861
8005
|
setInterval(load, 30000);
|
|
7862
8006
|
})();
|
|
7863
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
8007
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function ys(t={}){let e=`<div class="ax-pj__root">
|
|
7864
8008
|
<aside class="ax-pj__list">
|
|
7865
8009
|
<header>
|
|
7866
8010
|
<h2>Projects</h2>
|
|
@@ -7887,7 +8031,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7887
8031
|
</header>
|
|
7888
8032
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
7889
8033
|
</section>
|
|
7890
|
-
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
8034
|
+
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Bp,scripts:`<script>${zp}</script>`})}var Bp=`
|
|
7891
8035
|
.ax-pj__root {
|
|
7892
8036
|
display: grid;
|
|
7893
8037
|
grid-template-columns: 360px 1fr;
|
|
@@ -8074,7 +8218,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8074
8218
|
}
|
|
8075
8219
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
8076
8220
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
8077
|
-
`,
|
|
8221
|
+
`,zp=`
|
|
8078
8222
|
(function(){
|
|
8079
8223
|
const $ = (sel) => document.querySelector(sel);
|
|
8080
8224
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -8724,9 +8868,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8724
8868
|
load();
|
|
8725
8869
|
});
|
|
8726
8870
|
})();
|
|
8727
|
-
`;import{resolve as Ra,join as Bp}from"path";import{existsSync as $a,readdirSync as zp,readFileSync as qp}from"fs";import Fp from"better-sqlite3";var cs=String.raw`[\w.-]+(?:/[\w.-]+)+`,Ep=new RegExp(`^(?:chat:)?(${cs}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Tp=new RegExp(`^\\[(?:GitLab|GitHub) (${cs}) `);function ls(t){if(!t)return null;let e=t.match(Ep);return e?e[1]:null}function Ca(t){if(!t)return null;let e=t.trimStart().match(Tp);return e?e[1]:null}function qt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():ls(typeof n?.chatId=="string"?n.chatId:null)??ls(e)??Ca(a)}function Ap(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Ft(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Cp=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Ip=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Mp=t=>/^issue/i.test(t)?"issue":"mr";function Lp(t){let e=t.subject.match(Cp)??t.inputPreview.trimStart().match(Ip);return e?{kind:Mp(e[1]),n:Number(e[2])}:null}function Rp(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 ds(t){if(!Ap(t.projectId))return[];let e=Lp(t);return e?[e]:Rp(t.inputPreview)}var $p=6e4,Pp=5*6e4,jp=40,ps=6,us=new Map;function ms(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 ds(n)){let s=Ft(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=jp)return[...e.values()]}}return[...e.values()]}async function fs(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Ft(s.project,s.ref),l=us.get(i);l&&n-l.at<(s.github?Pp:$p)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ps)await Promise.all(o.slice(s,s+ps).map(async i=>{let l=Ft(i.project,i.ref),c=null;try{c=i.github?await Np(i,e,a):await Op(i,e,a)}catch{}us.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function hs(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 Op(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 hs(`${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 Np(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 hs(`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}mn();var Ia=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function gs(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=st(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Ia(o.from,80);if(s){a.callback={from:s,status:Ia(o.status,20)??"done"};let i=Ia(o.peer,80);i&&(a.callback.peer=i)}}return a}mn();ia();var xs={kind:"agentx",id:"agentx",name:"AgentX"},Ma={kind:"person",id:"unknown",name:"Unknown"},Dp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),vs=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ie=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Hp(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ie(o?.id)??(e==="whatsapp"?Ie(n?.from):void 0),i=Ie(o?.username)??Ie(o?.login);return s||i?{id:s,username:i,name:Ie(o?.name)}:null}function bs(t){let e=s=>({kind:"person",id:`person:${s}`,name:gn(t.people,s)}),a=(s,i)=>i||Dp.has(s)?xs:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ie(n.person)??vn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(un(s)==="human")return vs(s?.senderUsername)?a(c,!1):Ma;let d=!!Ie(n.senderAgentId)||ra(l?l.sender:s?.sender);return c==="desktop"&&!d?Ma:a(c,d)}let r=Hp(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=xn(t.people,t.channel,r);return o?e(o.id):ra(r.name)?xs:pn.has(t.channel)&&!vs(r.username)?Ma:a(t.channel,!1)}function Pa(){let t=Ra(process.cwd(),".agentx/intent/ledger.sqlite");if(!$a(t))return null;try{let e=new Fp(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ys>6e4&&(ys=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ys=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Me={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Up(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Me)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Me)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Me)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Me)return s}return"workflow"}return t}function _s(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 Wp(t,e){if(!t)return!1;let a=e?.agents?.[t];return a&&typeof a.system=="boolean"?a.system:!!(t==="graph-agent"||t==="intent-classifier"||/-classifier$/.test(t))}function Ss(t,e,a){return Mn(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 Gp(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&&!La(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!La(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Kp(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&&!La(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",u=ws(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:ws(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 Xp={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Kp(t,e){let a=Xp[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ws(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function La(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function Es(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
|
|
8871
|
+
`;import{resolve as za,join as nu}from"path";import{existsSync as qa,readdirSync as ru,readFileSync as ou}from"fs";import su from"better-sqlite3";var ks=String.raw`[\w.-]+(?:/[\w.-]+)+`,qp=new RegExp(`^(?:chat:)?(${ks}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Fp=new RegExp(`^\\[(?:GitLab|GitHub) (${ks}) `);function ws(t){if(!t)return null;let e=t.match(qp);return e?e[1]:null}function Na(t){if(!t)return null;let e=t.trimStart().match(Fp);return e?e[1]:null}function Xt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():ws(typeof n?.chatId=="string"?n.chatId:null)??ws(e)??Na(a)}function Up(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Kt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Wp=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Gp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Xp=t=>/^issue/i.test(t)?"issue":"mr";function Kp(t){let e=t.subject.match(Wp)??t.inputPreview.trimStart().match(Gp);return e?{kind:Xp(e[1]),n:Number(e[2])}:null}function Jp(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 _s(t){if(!Up(t.projectId))return[];let e=Kp(t);return e?[e]:Jp(t.inputPreview)}var Vp=6e4,Yp=5*6e4,Qp=40,Ss=6,Es=new Map;function Ts(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 _s(n)){let s=Kt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Qp)return[...e.values()]}}return[...e.values()]}async function As(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Kt(s.project,s.ref),l=Es.get(i);l&&n-l.at<(s.github?Yp:Vp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Ss)await Promise.all(o.slice(s,s+Ss).map(async i=>{let l=Kt(i.project,i.ref),c=null;try{c=i.github?await eu(i,e,a):await Zp(i,e,a)}catch{}Es.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Cs(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 Zp(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 Cs(`${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 eu(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 Cs(`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}kn();var Da=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Is(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=ct(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=Da(o.from,80);if(s){a.callback={from:s,status:Da(o.status,20)??"done"};let i=Da(o.peer,80);i&&(a.callback.peer=i)}}return a}kn();ua();var Ms={kind:"agentx",id:"agentx",name:"AgentX"},Ha={kind:"person",id:"unknown",name:"Unknown"},tu=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Ls=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ie=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function au(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ie(o?.id)??(e==="whatsapp"?Ie(n?.from):void 0),i=Ie(o?.username)??Ie(o?.login);return s||i?{id:s,username:i,name:Ie(o?.name)}:null}function Rs(t){let e=s=>({kind:"person",id:`person:${s}`,name:Tn(t.people,s)}),a=(s,i)=>i||tu.has(s)?Ms:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ie(n.person)??Cn(t.people,s)?.id;if(i)return e(i);let l=ct(s),c=l?.channel??t.channel;if(wn(s)==="human")return Ls(s?.senderUsername)?a(c,!1):Ha;let p=!!Ie(n.senderAgentId)||ca(l?l.sender:s?.sender);return c==="desktop"&&!p?Ha:a(c,p)}let r=au(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=An(t.people,t.channel,r);return o?e(o.id):ca(r.name)?Ms:yn.has(t.channel)&&!Ls(r.username)?Ha:a(t.channel,!1)}function Fa(){let t=za(process.cwd(),".agentx/intent/ledger.sqlite");if(!qa(t))return null;try{let e=new su(t,{readonly:!0,fileMustExist:!0});return we(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-$s>6e4&&($s=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var $s=0;function ge(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Me={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function iu(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Me)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Me)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Me)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Me)return s}return"workflow"}return t}function Os(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function lu(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 Ns(t,e,a){return Bn(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function cu(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&&!Ba(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ba(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:pu(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&&!Ba(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Ps(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:Ps(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 du={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function pu(t,e){let a=du[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Ps(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ba(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function Ds(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
|
|
8728
8872
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
8729
|
-
${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function
|
|
8873
|
+
${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function uu(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 Hs(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
8730
8874
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
8731
8875
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
8732
8876
|
`).all(r),s=new Map,i=new Map;if(o.length>0){let w=o.map(L=>L.id),I=w.map((L,j)=>`@id${j}`).join(","),C=Object.fromEntries(w.map((L,j)=>[`id${j}`,L])),E=t.prepare(`
|
|
@@ -8735,20 +8879,20 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
|
|
|
8735
8879
|
`).all(C);for(let L of E)s.has(L.event_id)||s.set(L.event_id,[]),s.get(L.event_id).push(L);let $=t.prepare(`
|
|
8736
8880
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
8737
8881
|
FROM intent_resolutions WHERE decision_event_id IN (${I})
|
|
8738
|
-
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,
|
|
8882
|
+
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,m=[],h=e?.business?.projects??[],_=e?.business?.contactMap??[],v=ha(e?.business??{}),S=e?.people??[];for(let w of o){let I=null;try{I=JSON.parse(w.raw_json)}catch{}let C=Ns(w.source,I,_),E=Ds(w.source,I),$=Is(I),L=w.project??Xt(I,w.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=gt(L,h),W=L);let q=iu(w.source,w.intent||"",I),G=Me[q]||{label:q,color:"#6b7280"};p.has(q)||p.set(q,{id:q,label:G.label,color:G.color});let ie=Rs({source:w.source,channel:q,raw:I,people:S,channelLabel:O=>Me[O]?.label??O}),Oe="__system",Z,z=cu(w.source,w.intent||"",I);if(z){Oe=z.id,Z=z.kind;let O=C?.displayName||z.name;(!u.has(z.id)||C?.displayName)&&u.set(z.id,{id:z.id,name:O,avatar:J(O),kind:z.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let O of s.get(w.id)??[]){if(O.outcome!=="dispatched"||!O.agent_id)continue;let Ql=`${w.id}|${O.decided_by}`,it=i.get(Ql),gn=O.decided_at,xn=it?.resolved_at??null,ia=xn===null,Zl=it?.duration_ms??(ia?n-gn:0),ec=ia?"active":it?.status==="error"||it?.status==="fail"?"error":"completed",ee,Ke;if(j)ee=j,Ke=W;else{let la=v.get(O.agent_id);la?(ee=la,Ke=`${la}/_${w.source}`):(ee="unmapped",Ke=`unmapped/_${w.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:Os(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ke),m.push({id:`${w.id}|${O.decided_by}`,agentId:O.agent_id,clientId:ee,projectId:Ke,channelId:q,initiatorId:Oe,initiatorKind:Z,subject:uu(w.subject),intent:w.intent||"",startedAt:gn,resolvedAt:xn,duration:Zl,active:ia,outcome:ec,tokens:0,inputPreview:E,system:lu(O.agent_id,e),...$,starter:ie})}}let g=[...l.values()].map(w=>({...w,projects:[...c.get(w.id)||[]].sort()})).sort((w,I)=>w.id.localeCompare(I.id)),d=[],f=new Set;if(e){let w=e.business??{},I=C=>{let E=w.orgChart?.[C]?.role,$=E?w.roles?.[E]?.title:void 0;return typeof $=="string"&&$.trim()?$.trim():void 0};for(let[C,E]of Object.entries(e.agents||{})){let $={id:C,name:E.name||C,tier:E.tier==="claude-code"?"lead":"worker",model:E.model||"",role:E.systemPrompt?E.systemPrompt.split(/[.\n]/)[0].slice(0,60):E.tier||"",title:I(C)};d.push($),f.add(C)}}for(let w of m)f.has(w.agentId)||(d.push({id:w.agentId,name:w.agentId,tier:"worker",model:"",role:""}),f.add(w.agentId));d.sort((w,I)=>w.id.localeCompare(I.id));let x=[],b=new Set;for(let[w,I]of Object.entries(Me))x.push({id:w,label:I.label,color:I.color}),b.add(w);for(let w of p.values())b.has(w.id)||x.push(w);let k=[...u.values()];k.find(w=>w.id==="__system")||k.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:d,channels:x,initiators:k,dispatches:m,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function Ua(t){let e=Fa();if(!e)return null;try{return Hs(e.db,zs(),t)}finally{e.close()}}function Bs(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:h})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let m=mu(u);if(m.clientId!==u.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Os(m.clientId),projects:[]}),m.projectId!==u.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function mu(t){if(t.clientId!=="unmapped")return t;let e=Na(t.inputPreview);if(!e)return t;let a=xe?.business?.projects??[];return{...t,projectId:e,clientId:gt(e,a)}}async function Jt(t){let e=xe?.channels?.gitlab,a=await As(Ts(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 xe=null;function zs(){return xe&&{...xe,people:Ye(xe.people)}}function qs(t){xe=t}async function Fs(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Fa();if(!n)return ge(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Us(parseInt(r.searchParams.get("hours")||"6",10));ge(e,200,await Jt(Hs(n.db,zs(),o)))}catch(r){ge(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var fu=5e3;async function Wa(t,e,a,n=Ua){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
|
|
8739
8883
|
|
|
8740
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
8884
|
+
`);let r=new URL(t.url||"/","http://_"),o=Us(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
|
|
8741
8885
|
|
|
8742
|
-
`)}catch{i()}},25e3);try{for(;!s;){try{let
|
|
8886
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await Jt(p);if(s)break;u?(e.write(`event: snapshot
|
|
8743
8887
|
`),e.write(`data: ${JSON.stringify(u)}
|
|
8744
8888
|
|
|
8745
8889
|
`)):e.write(`event: error
|
|
8746
8890
|
data: ${JSON.stringify({error:"ledger not available"})}
|
|
8747
8891
|
|
|
8748
|
-
`)}catch(
|
|
8749
|
-
data: ${JSON.stringify({error:
|
|
8892
|
+
`)}catch(p){e.write(`event: error
|
|
8893
|
+
data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
8750
8894
|
|
|
8751
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
8895
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<fu;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Us(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function hu(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=za(process.cwd(),".agentx/task-history",t,n);if(!qa(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=za(process.cwd(),".agentx/task-history",t,o);return qa(s)?js(s,e,a):null}return js(r,e,a)}function js(t,e,a){let n=null,r=1/0;for(let o of ru(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(ou(nu(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function Ws(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 ge(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Fa();if(!l)return ge(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return ge(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return ge(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=Ds(c.source,m),_=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,v=null,S=null;if(p.agent_id){let k=hu(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(v=k.responseText);let T=k.transcript;Array.isArray(T)&&(S=T.length)}}let g=xe?.business?.projects??[],d=xe?.business?.contactMap??[],f=ha(xe?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},b=Ns(c.source,m,d);if(b)x={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(c.project||Xt(m,c.subject,h)){let k=c.project||Xt(m,c.subject,h);x={client:gt(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=f.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}ge(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:_,response:v,transcriptLen:S,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){ge(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as bu,readFileSync as yu}from"fs";import{resolve as Xs}from"path";ut();function Gs(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=gu.replace(/__AGENT_ID__/g,N(e));return M({title:`AgentX \xB7 ${N(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${N(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:xu,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>${vu}</script>`})}var gu=`
|
|
8752
8896
|
<!-- Breadcrumb -->
|
|
8753
8897
|
<div class="ax-crumb">
|
|
8754
8898
|
<a href="/admin">Settings</a>
|
|
@@ -9337,7 +9481,7 @@ data: ${JSON.stringify({error:d?.message??String(d)})}
|
|
|
9337
9481
|
</div>
|
|
9338
9482
|
</div>
|
|
9339
9483
|
</div>
|
|
9340
|
-
`,
|
|
9484
|
+
`,xu=`
|
|
9341
9485
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
9342
9486
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
9343
9487
|
* primitives live in components.css.ts. */
|
|
@@ -9456,7 +9600,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
9456
9600
|
|
|
9457
9601
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
9458
9602
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
9459
|
-
`,
|
|
9603
|
+
`,vu=`
|
|
9460
9604
|
const $ = (id) => document.getElementById(id);
|
|
9461
9605
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
9462
9606
|
|
|
@@ -10312,15 +10456,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
10312
10456
|
/* ===== Boot ===== */
|
|
10313
10457
|
initOptsToggles();
|
|
10314
10458
|
loadAgent();
|
|
10315
|
-
`;function
|
|
10316
|
-
`);return
|
|
10317
|
-
`);return
|
|
10459
|
+
`;function Ks(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gs({agentId:a,peers:n,localToken:r}))}async function Js(t,e,a){try{let n=t.method==="GET"?void 0:await qu(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){Vt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>et(i),"PATCH ":()=>wu(i,n),"PATCH capability":()=>Su(i,n),"POST mcp":()=>ku(i,n),"DELETE mcp":()=>_u(i,n),"GET identity":()=>Eu(i),"GET identity/file":()=>Tu(i,String(o.path||"")),"PUT identity/file":()=>Au(i,n),"GET skills":()=>Cu(i),"POST skills":()=>Iu(i,n),"DELETE skills":()=>Mu(i,n),"GET skills/tree":()=>Lu(i,String(o.slug||"")),"GET skills/file":()=>Ru(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>$u(i,n),"GET skills/deps":()=>Pu(i,String(o.slug||"")),"POST skills/install":()=>ju(i,n,t),"POST skills/deps":()=>Ou(i,n,t),"GET channels":()=>Nu(i),"GET activity":()=>Du(i,t),"GET handovers":()=>Hu(i),"POST handovers":()=>Bu(i,n),"DELETE handovers":()=>zu(n)}[c];if(!u){Vt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await u();Vt(e,200,m)}catch(n){Vt(e,400,{error:n?.message||"agent op failed"})}}function Vs(){let t=Xs(process.cwd(),"agentx.json");return bu(t)?JSON.parse(yu(t,"utf-8")):null}function V(t){let e=Vs();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 et(t){let{def:e,cfg:a}=V(t),n=e.workspace?De(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function wu(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:et(t)}}function ku(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=A(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:et(t)}}function _u(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:et(t)}}function Su(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:et(t)}}function Eu(t){let{def:e}=V(t);return De(e.workspace)}function Tu(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Et(a.workspace,e)}function Au(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return Tt(n.workspace,a,String(e?.content??""))}function Cu(t){let{def:e}=V(t),a=De(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Iu(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return At(n.workspace,a,{title:e?.title,content:e?.content})}function Mu(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Ct(n.workspace,a)}function Lu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=ur(a.workspace,e),r=It(a.workspace,e);return{slug:e,tree:n,deps:r}}function Ru(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return mr(n.workspace,e,a)}function $u(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 fr(r.workspace,a,n,String(e?.content??""))}function Pu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return It(a.workspace,e)}async function ju(t,e,a){let n=String(e?.package||"").trim();if(!n||!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)?$/.test(n))throw new Error("package must be in 'owner/repo' or 'owner/repo/skill' form");let r=Ys(e?.worker),{def:o}=V(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
|
|
10460
|
+
`);return Qs(a,r,s,`install-${n}:${Date.now()}`)}async function Ou(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Ys(e?.worker),{def:o}=V(t),s=It(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=Xs(o.workspace,".claude","skills",n),l=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${i}`,`Detected manifest: ${s.file}`,`Run: ${s.command}`,"Stream the install output. On success, summarise the packages installed.","On failure, report the exit code and the last 20 lines of output."].join(`
|
|
10461
|
+
`);return Qs(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Ys(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Qs(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Nu(t){let e=Vs(),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 Du(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 Ga(){return new Mn}function Hu(t){let e=Ga(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Bu(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,c=Ga().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function zu(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:Ga().remove(e,a,n)?"Released":"No active handover for that chat"}}function Vt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function qu(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var Le={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var Zs=[{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 Xa(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Le)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
10318
10462
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
10319
10463
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
10320
10464
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
10321
10465
|
<main id="grid" class="ax-live__body"></main>
|
|
10322
10466
|
</div>
|
|
10323
|
-
`;return M({title:`${Le.brand} \xB7 ${Le.subtitle}`,activeTab:"live",subtitle:Le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:
|
|
10467
|
+
`;return M({title:`${Le.brand} \xB7 ${Le.subtitle}`,activeTab:"live",subtitle:Le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Fu,scripts:e+`<script>${Uu}</script>`,headExtras:`<script>
|
|
10324
10468
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
10325
10469
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
10326
10470
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -10331,7 +10475,7 @@ loadAgent();
|
|
|
10331
10475
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
10332
10476
|
right.insertBefore(extras, right.firstChild);
|
|
10333
10477
|
});
|
|
10334
|
-
</script>`})}var
|
|
10478
|
+
</script>`})}var Fu=`
|
|
10335
10479
|
/* --- Page frame --- */
|
|
10336
10480
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
10337
10481
|
|
|
@@ -10538,7 +10682,7 @@ loadAgent();
|
|
|
10538
10682
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
10539
10683
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
10540
10684
|
}
|
|
10541
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
10685
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,Uu=`
|
|
10542
10686
|
'use strict';
|
|
10543
10687
|
|
|
10544
10688
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -11109,7 +11253,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11109
11253
|
});
|
|
11110
11254
|
}
|
|
11111
11255
|
|
|
11112
|
-
`;var
|
|
11256
|
+
`;var ei=`
|
|
11113
11257
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
11114
11258
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
11115
11259
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -11283,7 +11427,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11283
11427
|
.mx-summary{max-width:56vw}
|
|
11284
11428
|
}
|
|
11285
11429
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
11286
|
-
`;var
|
|
11430
|
+
`;var ti=`<script>
|
|
11287
11431
|
window.MX=(function(){
|
|
11288
11432
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
11289
11433
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -11392,7 +11536,7 @@ window.MX=(function(){
|
|
|
11392
11536
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
11393
11537
|
setHealth:setHealth,get:get};
|
|
11394
11538
|
})();
|
|
11395
|
-
</script>`;var
|
|
11539
|
+
</script>`;var ai=`<script>
|
|
11396
11540
|
window.MXD=(function(){
|
|
11397
11541
|
function el(id){return document.getElementById(id)}
|
|
11398
11542
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -11606,7 +11750,7 @@ window.MXD=(function(){
|
|
|
11606
11750
|
|
|
11607
11751
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
11608
11752
|
})();
|
|
11609
|
-
</script>`;var
|
|
11753
|
+
</script>`;var ni=`<script>
|
|
11610
11754
|
(function(){
|
|
11611
11755
|
var LANES=[
|
|
11612
11756
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -11922,7 +12066,7 @@ window.MXD=(function(){
|
|
|
11922
12066
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
11923
12067
|
load();
|
|
11924
12068
|
})();
|
|
11925
|
-
</script>`;var
|
|
12069
|
+
</script>`;var ri=`<script>
|
|
11926
12070
|
(function(){
|
|
11927
12071
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
11928
12072
|
var esc=MX.esc;
|
|
@@ -12100,7 +12244,7 @@ window.MXD=(function(){
|
|
|
12100
12244
|
}
|
|
12101
12245
|
load();setInterval(load,5000);
|
|
12102
12246
|
})();
|
|
12103
|
-
</script>`;var
|
|
12247
|
+
</script>`;var oi=`
|
|
12104
12248
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
12105
12249
|
.mx-rt-wrap{border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-lg);background:var(--ax-surface);overflow-x:auto}
|
|
12106
12250
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -12141,7 +12285,7 @@ window.MXD=(function(){
|
|
|
12141
12285
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
12142
12286
|
.mx-rt-name{max-width:100%}
|
|
12143
12287
|
}
|
|
12144
|
-
`,
|
|
12288
|
+
`,si=`<script>
|
|
12145
12289
|
(function(){
|
|
12146
12290
|
var root=document.getElementById('mx-routines');
|
|
12147
12291
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -12268,7 +12412,7 @@ window.MXD=(function(){
|
|
|
12268
12412
|
syncBar();
|
|
12269
12413
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
12270
12414
|
})();
|
|
12271
|
-
</script>`;var
|
|
12415
|
+
</script>`;var ii=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],li=`<script>
|
|
12272
12416
|
(function(){
|
|
12273
12417
|
var root=document.getElementById('mx-feed');
|
|
12274
12418
|
if(!root)return;
|
|
@@ -12343,12 +12487,12 @@ window.MXD=(function(){
|
|
|
12343
12487
|
}
|
|
12344
12488
|
load();setInterval(load,5000);
|
|
12345
12489
|
})();
|
|
12346
|
-
</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
|
|
12490
|
+
</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 Wu=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Gu=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Xu=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function ci(t){let e=be({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Mt([{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">
|
|
12347
12491
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
12348
|
-
${
|
|
12492
|
+
${Gu.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("")}
|
|
12349
12493
|
</div>
|
|
12350
12494
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
12351
|
-
${
|
|
12495
|
+
${Xu.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
12352
12496
|
</div>
|
|
12353
12497
|
</div>
|
|
12354
12498
|
<p id="mx-analytics-updated" class="mx-updated" aria-live="polite">Reading node histories...</p>`,n=`<div class="mx-view" id="mx-view-activity" role="tabpanel" aria-labelledby="mx-tab-activity">
|
|
@@ -12401,7 +12545,7 @@ window.MXD=(function(){
|
|
|
12401
12545
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
12402
12546
|
${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>')}
|
|
12403
12547
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
12404
|
-
${
|
|
12548
|
+
${Wu.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12405
12549
|
</div>
|
|
12406
12550
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
12407
12551
|
</section>
|
|
@@ -12409,7 +12553,7 @@ window.MXD=(function(){
|
|
|
12409
12553
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
12410
12554
|
${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>')}
|
|
12411
12555
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
12412
|
-
${
|
|
12556
|
+
${ii.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12413
12557
|
</div>
|
|
12414
12558
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
12415
12559
|
</section>
|
|
@@ -12442,7 +12586,7 @@ window.MXD=(function(){
|
|
|
12442
12586
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
12443
12587
|
</header>
|
|
12444
12588
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
12445
|
-
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
12589
|
+
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:ei+oi,scripts:ti+Ku+ai+ni+si+ri+li})}var Ku=`<script>
|
|
12446
12590
|
(function(){
|
|
12447
12591
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
12448
12592
|
var range=document.getElementById('mx-range');
|
|
@@ -12470,10 +12614,10 @@ window.MXD=(function(){
|
|
|
12470
12614
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
12471
12615
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
12472
12616
|
})();
|
|
12473
|
-
</script>`;function
|
|
12617
|
+
</script>`;function di(t){let e=be({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
|
|
12474
12618
|
<div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
|
|
12475
12619
|
<ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
|
|
12476
|
-
<p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent <id></code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:
|
|
12620
|
+
<p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent <id></code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:Ju,scripts:`<script>${Vu}</script>`})}var Ju=`
|
|
12477
12621
|
.gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
|
|
12478
12622
|
.gm-empty { color: var(--ax-text-2); }
|
|
12479
12623
|
.gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
@@ -12491,7 +12635,7 @@ window.MXD=(function(){
|
|
|
12491
12635
|
.gm-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
12492
12636
|
.gm-msg.is-bad { color: var(--ax-red-ink); }
|
|
12493
12637
|
.gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
12494
|
-
|
|
12638
|
+
`,Vu=`
|
|
12495
12639
|
(function () {
|
|
12496
12640
|
var list = document.getElementById('gm-list');
|
|
12497
12641
|
var msg = document.getElementById('gm-msg');
|
|
@@ -12538,7 +12682,7 @@ window.MXD=(function(){
|
|
|
12538
12682
|
load();
|
|
12539
12683
|
setInterval(load, 30000);
|
|
12540
12684
|
})();
|
|
12541
|
-
`;async function
|
|
12685
|
+
`;async function pi(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Yu(s,e.days)}function Yu(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,u=0,m=0,h=0,_=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let f=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])f[x][0]+=d[x]?.[0]||0,f[x][1]+=d[x]?.[1]||0;n.set(d.day,f)}for(let d of g.origins){let f=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};f.runs+=d.runs,f.errors+=d.errors,f.hours+=d.hours,r.set(d.channel,f)}for(let d of g.causes){let f=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};f.count+=d.count;for(let x of d.agents)f.agents.includes(x)||f.agents.push(x);f.example||(f.example=d.example),o.set(d.cause,f)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,m=Math.max(m,g.rotations.maxTokens),h+=g.retention.traces,_+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let v=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:v.length?Math.min(...v):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:p,tokenSamples:u,maxTokens:m},retention:{traces:h,tracesWithSteps:_}}}async function ui(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 mi(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Qu(s,e.day)}function Qu(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function fi(t={}){let e=`
|
|
12542
12686
|
<select id="boardPicker" title="Switch board"></select>
|
|
12543
12687
|
<div class="search">
|
|
12544
12688
|
<span class="icon">\u2315</span>
|
|
@@ -12639,7 +12783,7 @@ window.MXD=(function(){
|
|
|
12639
12783
|
</footer>
|
|
12640
12784
|
</div>
|
|
12641
12785
|
</div>
|
|
12642
|
-
<script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:
|
|
12786
|
+
<script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Zu,scripts:`<script>${em}</script>`,headExtras:`<script>
|
|
12643
12787
|
// The boards page has its own connection dot + wants body height:100%
|
|
12644
12788
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
12645
12789
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -12655,7 +12799,7 @@ window.MXD=(function(){
|
|
|
12655
12799
|
right.insertBefore(dot, right.firstChild);
|
|
12656
12800
|
}
|
|
12657
12801
|
});
|
|
12658
|
-
</script>`})}var
|
|
12802
|
+
</script>`})}var Zu=`
|
|
12659
12803
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
12660
12804
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
12661
12805
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -12908,7 +13052,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
12908
13052
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
12909
13053
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
12910
13054
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
12911
|
-
`,
|
|
13055
|
+
`,em=`
|
|
12912
13056
|
'use strict';
|
|
12913
13057
|
const state = {
|
|
12914
13058
|
boards: [], current: null, items: {},
|
|
@@ -13961,9 +14105,9 @@ function appendEvents(events) {
|
|
|
13961
14105
|
}
|
|
13962
14106
|
|
|
13963
14107
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
13964
|
-
`;function
|
|
14108
|
+
`;function hi(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
13965
14109
|
<p class="lead">What the terms on the dashboard mean. Schema keys (shown in the pill on the right of each term) are what you'd write in <code>agentx.json</code> \u2014 the dashboard just relabels them for readability.</p>
|
|
13966
|
-
${
|
|
14110
|
+
${Zs.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${N(n.alias)}</span>`:"";return`<article class="term"><h3>${N(n.term)}${r}</h3><p>${N(n.definition)}</p></article>`}).join("")}`;return M({title:`${Le.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:tm})}var tm=`
|
|
13967
14111
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
13968
14112
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
13969
14113
|
.lead {
|
|
@@ -13993,7 +14137,7 @@ article.term .alias {
|
|
|
13993
14137
|
}
|
|
13994
14138
|
article.term p {
|
|
13995
14139
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
13996
|
-
}`;function
|
|
14140
|
+
}`;function gi(t={}){let e=`<div class="ax-wf__root">
|
|
13997
14141
|
<aside class="ax-wf__list">
|
|
13998
14142
|
<header>
|
|
13999
14143
|
<h2>Workflows</h2>
|
|
@@ -14070,7 +14214,7 @@ article.term p {
|
|
|
14070
14214
|
</aside>
|
|
14071
14215
|
</div>
|
|
14072
14216
|
|
|
14073
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
14217
|
+
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:am,scripts:`<script>${B({workflowHealth:Hn})}${nm}</script>`})}var am=`
|
|
14074
14218
|
.ax-wf__root {
|
|
14075
14219
|
display: grid;
|
|
14076
14220
|
grid-template-columns: 340px 1fr;
|
|
@@ -14454,7 +14598,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14454
14598
|
font-size: 12px; z-index: 50;
|
|
14455
14599
|
}
|
|
14456
14600
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
14457
|
-
`,
|
|
14601
|
+
`,nm=`
|
|
14458
14602
|
(() => {
|
|
14459
14603
|
const $ = (sel) => document.querySelector(sel)
|
|
14460
14604
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -15243,7 +15387,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15243
15387
|
setInterval(refresh, 15000)
|
|
15244
15388
|
})
|
|
15245
15389
|
})();
|
|
15246
|
-
`;function
|
|
15390
|
+
`;function xi(t={}){let e=`<div class="ax-proc__root">
|
|
15247
15391
|
<header class="ax-proc__header">
|
|
15248
15392
|
<h1>Procedures</h1>
|
|
15249
15393
|
<p class="hint">Reusable building blocks workflows compose. See <a href="/admin/wiki/architecture/three-tier" target="_blank">three-tier model</a> for how this fits with System and Processes.</p>
|
|
@@ -15287,7 +15431,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15287
15431
|
<p class="hint">AgentX is layered: <strong>System</strong> (agents, channels, mesh) \u2192 <strong>Processes</strong> (workflows that turn intent into work) \u2192 <strong>Procedures</strong> (this page: reusable steps a process composes). Higher tiers depend on lower; never the reverse.</p>
|
|
15288
15432
|
<p class="hint">Adding a new procedure is a code change (a new <code>action.builtin</code> module under <code>src/actions/builtin/</code> or a new template YAML in <code>src/workflows/templates/</code>) \u2014 not a UI flow. This page is the read-only catalog.</p>
|
|
15289
15433
|
</section>
|
|
15290
|
-
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
15434
|
+
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:rm,scripts:`<script>${om}</script>`})}var rm=`
|
|
15291
15435
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
15292
15436
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
15293
15437
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -15313,7 +15457,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15313
15457
|
.ax-proc__req { display: inline-block; padding: 1px 6px; font-size: 10px; font-family: var(--ax-mono); border: 1px solid color-mix(in oklch, var(--ax-warn, #f59e0b) 40%, var(--ax-border)); border-radius: 3px; color: var(--ax-warn, #f59e0b); }
|
|
15314
15458
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
15315
15459
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
15316
|
-
`,
|
|
15460
|
+
`,om=`
|
|
15317
15461
|
(function(){
|
|
15318
15462
|
function $(sel){ return document.querySelector(sel) }
|
|
15319
15463
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -15413,7 +15557,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15413
15557
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
15414
15558
|
else bootAll()
|
|
15415
15559
|
})();
|
|
15416
|
-
`;function
|
|
15560
|
+
`;function vi(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
15417
15561
|
data-task-id="${N(t.taskId)}"
|
|
15418
15562
|
data-agent-id="${N(t.agentId)}"
|
|
15419
15563
|
data-node-url="${N(t.nodeUrl)}"
|
|
@@ -15456,7 +15600,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15456
15600
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
15457
15601
|
</div>
|
|
15458
15602
|
</footer>
|
|
15459
|
-
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15603
|
+
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:sm,scripts:`<script>${im}</script>`})}var sm=`
|
|
15460
15604
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
15461
15605
|
the sticky topbar. Breathe. */
|
|
15462
15606
|
.ax-task-page {
|
|
@@ -15598,7 +15742,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15598
15742
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
15599
15743
|
}
|
|
15600
15744
|
|
|
15601
|
-
`,
|
|
15745
|
+
`,im=`
|
|
15602
15746
|
(function () {
|
|
15603
15747
|
var root = document.querySelector('.ax-task-page');
|
|
15604
15748
|
if (!root) return;
|
|
@@ -15983,7 +16127,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15983
16127
|
});
|
|
15984
16128
|
|
|
15985
16129
|
})();
|
|
15986
|
-
`;function
|
|
16130
|
+
`;function bi(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
15987
16131
|
data-agent-id="${N(t.agentId)}"
|
|
15988
16132
|
data-agent-name="${N(e)}"
|
|
15989
16133
|
data-node-url="${N(t.nodeUrl)}">
|
|
@@ -16012,7 +16156,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16012
16156
|
<div class="ax-history__list" id="hist-list">
|
|
16013
16157
|
<div class="ax-history__empty">loading\u2026</div>
|
|
16014
16158
|
</div>
|
|
16015
|
-
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
16159
|
+
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:lm,scripts:`<script>${cm}</script>`})}var lm=`
|
|
16016
16160
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
16017
16161
|
flush against the sticky topbar. */
|
|
16018
16162
|
.ax-history {
|
|
@@ -16064,7 +16208,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16064
16208
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
16065
16209
|
}
|
|
16066
16210
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
16067
|
-
`,
|
|
16211
|
+
`,cm=`
|
|
16068
16212
|
(function () {
|
|
16069
16213
|
var root = document.querySelector('.ax-history');
|
|
16070
16214
|
if (!root) return;
|
|
@@ -16164,26 +16308,26 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16164
16308
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
16165
16309
|
});
|
|
16166
16310
|
})();
|
|
16167
|
-
`;function
|
|
16311
|
+
`;function wi(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return Ue(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:pm(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return R(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Ue(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return R(e,200,{ok:!0,emission:c})}):R(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Ue(t,e,l=>{try{let c=a.layouts.save(s,l);return R(e,200,{layout:c})}catch(c){return R(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ue(t,e,l=>{let c=ma.safeParse(l);if(!c.success)return R(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=fa(c.data).map(u=>({path:"",message:u}));return R(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?R(e,200,{workflow:l}):R(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ue(t,e,p=>yi(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),R(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return R(e,404,{error:"unknown workflows endpoint",path:n})}var dm=["mesh"];function yi(t,e,a,n){let r=ma.safeParse(a);if(!r.success)return R(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=fa(o);if(s.length>0)return R(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return R(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return R(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,c=e.store.get(n.id);if(c)for(let p of dm)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(c);return R(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),R(t,200,{workflow:i})}function pm(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return R(e,200,{runs:u});let m=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Ue(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?R(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?R(e,200,{ok:!0,runId:l,status:p}):R(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return um(t,e,a,l);let c=a.runs.get(l);return c?R(e,200,{run:c}):R(e,404,{error:"run not found"})}return R(e,404,{error:"unknown runs endpoint"})}function um(t,e,a,n){let r=a.runs.get(n);if(!r)return R(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
|
|
16168
16312
|
|
|
16169
|
-
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(
|
|
16313
|
+
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
|
|
16170
16314
|
|
|
16171
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,
|
|
16315
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function Ue(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){R(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{R(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{R(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>R(e,400,{error:"body read failed",message:r.message})),!0}function R(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Wm}from"fs";import{createRequire as Gm}from"module";var mm=2048,ki=/^[A-Za-z0-9_-]{8,256}$/;async function _i(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return Y(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):fm()});if(n==="GET"&&a==="/api/app/alerts")return Y(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return Y(e,404,{error:"not found"});if(!s||l)return Y(e,503,{error:l});let c;try{c=await _t(t)}catch(h){return Y(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),_=h.map(g=>ce[g].field).join(", "),v=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return Y(e,400,{error:`send ${v}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return Y(e,400,{error:`${_} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),S[ce[g].field]=c[ce[g].field];return Y(e,200,{ok:!0,...S})}let p=hm(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return Y(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return Y(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!ki.test(u)||typeof m!="string"||!ki.test(m)?Y(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?Y(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function fm(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function hm(t,e){if(typeof t!="string"||t.length>mm)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Sn();var Ei=50,gm=280;async function Ti(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=xm(await o.recent(Ei))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Si(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Si(e,404,{error:"not found"})}function Ai(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=dt();return r?new xr(r):null}}}function xm(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:Ka(typeof n.summary=="string"?n.summary:"",gm),by:typeof n.agentId=="string"?Ka(n.agentId,100):null,node:Ka(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,Ei)}function Ka(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Si(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var vm="operator",bm=50,Ci=4,Ii=500;function ym(t){let e={channel:"app",chatId:t.chatId,sender:vm,...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 Mi(t,e,a,n){let{path:r,body:o}=ym(e),s="",i=!1,l=[],c=new Map,p=(u,m,h)=>{let _=u!=="done",v=i?{text:ht(m,_),artifacts:[]}:ft(m,le.perMessage,_),{cleanText:S,ui:g}=u==="done"?xt(v.text):{cleanText:v.text,ui:void 0},d=i?void 0:Ja(g);return{status:u,text:S,tools:l,files:v.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of km(u.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<bm){let _={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(_),h.id&&c.set(String(h.id),_)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return p("error",s,wm(h.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(u){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${u?.message||u}`)}}function wm(t){let e=String(t||"The agent could not answer.");return Ln(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function Ja(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}});let r=(t.quickReplies??[]).slice(0,Ci).map(s=>s.slice(0,Ii));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Ci).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Ii)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*km(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,`
|
|
16172
16316
|
`);let s;for(;(s=n.indexOf(`
|
|
16173
16317
|
|
|
16174
|
-
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let
|
|
16175
|
-
`))
|
|
16176
|
-
`))}}catch{}}}}finally{e.releaseLock()}}var
|
|
16318
|
+
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
|
|
16319
|
+
`))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&c.push(p.slice(5).replace(/^ /,""));if(c.length)try{yield{event:l,data:JSON.parse(c.join(`
|
|
16320
|
+
`))}}catch{}}}}finally{e.releaseLock()}}var Yt=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}
|
|
16177
16321
|
data: ${JSON.stringify(s)}
|
|
16178
16322
|
|
|
16179
16323
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
16180
16324
|
|
|
16181
|
-
`)},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
|
|
16182
|
-
`)){let n
|
|
16183
|
-
`).map(
|
|
16325
|
+
`)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};function Ri(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=_m(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:Va(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Va(t,e=120){for(let a of t.split(`
|
|
16326
|
+
`)){let n=$i(a);if(n)return Ya(n,e)}return""}function _m(t,e=120){let a=t.split(`
|
|
16327
|
+
`).map($i).filter(Boolean);return a.length?Ya(a[a.length-1],e):""}function $i(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Ya(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Qt=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Zt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Li=140;function ea(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Va(r||"",Li-18)||"something went wrong."}`:Va(n,Li)||"Answered.";return{deviceId:t,title:Ya(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var ji=8e3,Em=/^[A-Za-z0-9_.:-]{1,64}$/,Re=new Map,Qa=new Map,tn=new Qt;function Oi(){return tn}async function Ni(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??tn;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await Di(o)});let i=o.store();if(!i)return H(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),H(e,200,{conversations:Ri(r.id,Cm(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Re.get(p.id);return H(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Re.get(p.id);if(!p||!u)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Hi(e);let{id:m,title:h,node:_,nodeName:v,agent:S,agentName:g}=p;return e.write(Za("conversation",{id:m,title:h,node:_,nodeName:v,agent:S,agentName:g})),e.write(Za("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await _t(t,64*1024)}catch(p){return H(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return H(e,404,{error:"no such conversation"});let u=Re.get(p.id);return u?(u.ac.abort(),en(p,o,r.name),H(e,200,{stopped:!0})):await en(p,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await Am(e,c,r,i,o),!0}function Tm(t,e,a){let n=We(e.url),r=new Set,o=[];for(let s of t){let i=We(s.url),l=a.find(u=>We(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let m=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:m>0||(u.active??0)>0,running:m,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Di(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Tm(e.nodes,t.daemon,a)}async function Am(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>ji){H(t,400,{error:`message must be 1\u2013${ji} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let _=typeof e.node=="string"?e.node:"",v=typeof e.agent=="string"?e.agent:"";if(!Em.test(v)){H(t,400,{error:"pick an agent"});return}let S=(await Di(r)).find(d=>d.target===_);if(!S){H(t,400,{error:`unknown node "${_}"`});return}if(!S.online){H(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===v);if(!g){H(t,400,{error:`no agent "${v}" on ${S.name}`});return}s=n.create(a.id,{node:_,nodeName:S.name,agent:v,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Re.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new Yt(r.orphanLimitMs??18e5);Re.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h}=s;Qa.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Hi(t),t.write(Za("conversation",{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h})),i.attach(t);try{let _=e.spoken===!0,v=await Mi(r.daemon,{node:p,agent:m,message:o,chatId:`app:${l}`,spoken:_},i.ac.signal,(f,x)=>i.broadcast(f,x));i.orphaned&&(v.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,en(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:v.text,status:v.status,at:Date.now(),...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...v.tools.length?{tools:v.tools}:{}},v.files)??[];i.broadcast("final",{status:v.status,content:v.text,...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:v.status,attached:g,appOpen:(r.presence??tn).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Zt(d)&&r.notifyFinish(ea(a.id,s,v.status,v.text,v.error)).catch(()=>{})}finally{Re.delete(l),Qa.delete(l),i.finish()}}function Cm(){let t=[];for(let[e,a]of Qa){let n=Re.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Hi(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Za(t,e){return`event: ${t}
|
|
16184
16328
|
data: ${JSON.stringify(e)}
|
|
16185
16329
|
|
|
16186
|
-
`}async function Wa(t,e,a){try{let n=Fe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Fe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Fe(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Fe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as um}from"stream";var mm=/^\/api\/app\/files\/([^/]+)$/,fm=15e3;async function Ci(t,e,a,n,r,o){let s=mm.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return $e(e,405,{error:"GET only"});let i=o.store();if(!i)return $e(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return $e(e,404,{error:"no such file"});let d=await hm(c.node,o);if(!d)return $e(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),fm),h;try{let p=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${d.url}${Fn}?${p}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return $e(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let p=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,f,{error:p||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),$e(e,413,{error:"the file is too large"});let v=h.headers.get("content-range");if(e.writeHead(h.status,{...Un(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&v?{"Content-Range":v}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=um.fromWeb(h.body);return g.on("data",p=>{S+=p.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function hm(t,e){if(t==="local")return{url:Ai(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Ai(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Ai(t){return t.replace(/\/+$/,"")}function $e(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var Mi=8e3;async function Li(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Zn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Qn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let v=await Ne(t,Yn.bytes);if(!v)return Q(e,413,{error:er()});if(!v.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Ii(e,o.daemon,"/voice/transcribe",v,S,18e4)}let s,i=await Ne(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let d=typeof s?.text=="string"?s.text.slice(0,Mi):"";if(!d.trim())return Q(e,400,{error:"text is required"});if(!xm(c.messages,d))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return Ii(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Ii(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(gm(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function gm(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function xm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Mi&&a.content.startsWith(e)))}var vm=new Set(["ring","offer","answer","ice","hangup"]),Vt=/^[A-Za-z0-9_-]{4,64}$/,bm=128*1024;async function Ri(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),d=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,bm);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let d=ym(c,r.nodeName);if(typeof d=="string")return P(e,400,{error:d});let u=$i(d.to);if(u&&d.kind==="ring"){let m=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:u});return P(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)}),h=await m.json().catch(()=>({}));return P(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Vt.test(l)?wm(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Vt.test(d))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:u},18e4);return P(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Qe(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Qe(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Vt.test(l))return P(e,400,{error:"callId is required"});let c=await Qe(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function $i(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Qe(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function ym(t,e){let a=String(t?.kind??"");if(!vm.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Vt.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:")&&!$i(r))return"to must be bot:<agent id> for an agent";if(Xe(r)===Xe(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function wm(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Pi=`
|
|
16330
|
+
`}async function en(t,e,a){try{let n=We(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=We(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>We(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 We(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Im}from"stream";var Mm=/^\/api\/app\/files\/([^/]+)$/,Lm=15e3;async function zi(t,e,a,n,r,o){let s=Mm.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return $e(e,405,{error:"GET only"});let i=o.store();if(!i)return $e(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return $e(e,404,{error:"no such file"});let p=await Rm(c.node,o);if(!p)return $e(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),Lm),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Zn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return $e(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,f,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let _=Number(h.headers.get("content-length")||0);if(_>le.bytes)return u.abort(),$e(e,413,{error:"the file is too large"});let v=h.headers.get("content-range");if(e.writeHead(h.status,{...er(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(_)}:{},...h.status===206&&v?{"Content-Range":v}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Im.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function Rm(t,e){if(t==="local")return{url:Bi(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Bi(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Bi(t){return t.replace(/\/+$/,"")}function $e(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var Fi=8e3;async function Ui(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!cr(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let _=lr(t.headers["x-audio-duration-ms"]);if(_)return t.resume(),Q(e,_.status,{error:_.error});let v=await Ne(t,ir.bytes);if(!v)return Q(e,413,{error:dr()});if(!v.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return qi(e,o.daemon,"/voice/transcribe",v,S,18e4)}let s,i=await Ne(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Fi):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!Pm(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return qi(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function qi(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($m(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function $m(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Pm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Fi&&a.content.startsWith(e)))}var jm=new Set(["ring","offer","answer","ice","hangup"]),ta=/^[A-Za-z0-9_-]{4,64}$/,Om=128*1024;async function Wi(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=Je(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Je(String(h?.name??""))!==p),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,Om);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=Nm(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=Gi(p.to);if(u&&p.kind==="ring"){let m=await tt(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return P(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return ta.test(l)?Dm(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!ta.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await tt(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await tt(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await tt(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!ta.test(l))return P(e,400,{error:"callId is required"});let c=await tt(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function Gi(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function tt(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function Nm(t,e){let a=String(t?.kind??"");if(!jm.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!ta.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:")&&!Gi(r))return"to must be bot:<agent id> for an agent";if(Je(r)===Je(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 Dm(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Xi=`
|
|
16187
16331
|
:root {
|
|
16188
16332
|
--ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
|
|
16189
16333
|
--ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
|
|
@@ -16197,6 +16341,7 @@ data: ${JSON.stringify(e)}
|
|
|
16197
16341
|
--ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
|
|
16198
16342
|
--phone-bubble: #1d2f52; --phone-green: #3dbe74;
|
|
16199
16343
|
}
|
|
16344
|
+
`,Ki=`
|
|
16200
16345
|
[hidden] { display: none !important; }
|
|
16201
16346
|
main > .sw-peek[hidden] { display: block !important; }
|
|
16202
16347
|
main > #panel-chat.sw-peek[hidden] { display: flex !important; }
|
|
@@ -16302,7 +16447,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
|
|
|
16302
16447
|
@media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
|
|
16303
16448
|
@media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
|
|
16304
16449
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
|
|
16305
|
-
`;var
|
|
16450
|
+
`;var Ji=`
|
|
16306
16451
|
window.AXSheet = function (sheet, onClose) {
|
|
16307
16452
|
var handle = document.createElement('button');
|
|
16308
16453
|
handle.type = 'button'; handle.className = 'sheet-handle';
|
|
@@ -16331,7 +16476,7 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
16331
16476
|
handle.addEventListener('pointercancel', reset);
|
|
16332
16477
|
sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
|
|
16333
16478
|
};
|
|
16334
|
-
`;var
|
|
16479
|
+
`;var Vi=`
|
|
16335
16480
|
(function () {
|
|
16336
16481
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
16337
16482
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -16551,11 +16696,13 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
16551
16696
|
path: '/api/app/tasks/followup', body: function (text) { return { node: t.node, taskId: t.taskId, message: text }; }, done: function () { return 'Follow-up queued.'; } });
|
|
16552
16697
|
});
|
|
16553
16698
|
|
|
16554
|
-
var loading = false;
|
|
16699
|
+
var loading = false, again = 0;
|
|
16555
16700
|
function visible(panel) { return !panel.hidden && document.visibilityState === 'visible'; }
|
|
16556
16701
|
function refresh() {
|
|
16557
16702
|
// Never redraw under an open sheet: the rows it refers to would move.
|
|
16558
16703
|
if (loading || sheet.open) return;
|
|
16704
|
+
// Nor under a finger pulling the next tab in: the redraw would end the swipe.
|
|
16705
|
+
if (document.querySelector('main.sw-on')) { clearTimeout(again); again = setTimeout(refresh, 300); return; }
|
|
16559
16706
|
var q = '?timezone=' + encodeURIComponent(tz);
|
|
16560
16707
|
var jobs = [];
|
|
16561
16708
|
loading = true;
|
|
@@ -16578,7 +16725,7 @@ window.AXSheet = function (sheet, onClose) {
|
|
|
16578
16725
|
setInterval(refresh, 15000);
|
|
16579
16726
|
refresh();
|
|
16580
16727
|
})();
|
|
16581
|
-
`;var
|
|
16728
|
+
`;var Yi=`
|
|
16582
16729
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
16583
16730
|
.fx-head h2 { margin: 4px 0 0; }
|
|
16584
16731
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -16635,7 +16782,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16635
16782
|
}
|
|
16636
16783
|
.fx-error:empty { display: none; }
|
|
16637
16784
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
16638
|
-
`;var
|
|
16785
|
+
`;var Qi=`
|
|
16639
16786
|
(function () {
|
|
16640
16787
|
var panel = document.getElementById('panel-alerts');
|
|
16641
16788
|
if (!panel) return;
|
|
@@ -16846,7 +16993,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16846
16993
|
refresh();
|
|
16847
16994
|
loadRecent();
|
|
16848
16995
|
})();
|
|
16849
|
-
`;var
|
|
16996
|
+
`;var Zi=`
|
|
16850
16997
|
(function () {
|
|
16851
16998
|
var panel = document.getElementById('panel-alerts');
|
|
16852
16999
|
if (!panel) return;
|
|
@@ -16959,7 +17106,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16959
17106
|
}
|
|
16960
17107
|
load();
|
|
16961
17108
|
})();
|
|
16962
|
-
`;var
|
|
17109
|
+
`;var el=`
|
|
16963
17110
|
(function () {
|
|
16964
17111
|
var panel = document.getElementById('panel-chat');
|
|
16965
17112
|
var V = window.AXChatView;
|
|
@@ -17242,7 +17389,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17242
17389
|
var last = recall('ax-chat-conv');
|
|
17243
17390
|
if (!fromHash() && last) openConversation(last);
|
|
17244
17391
|
})();
|
|
17245
|
-
`;var
|
|
17392
|
+
`;var tl=`
|
|
17246
17393
|
window.AXChatView = (function () {
|
|
17247
17394
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
17248
17395
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -17523,7 +17670,7 @@ window.AXChatView = (function () {
|
|
|
17523
17670
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
17524
17671
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
17525
17672
|
})();
|
|
17526
|
-
`;var
|
|
17673
|
+
`;var al=`
|
|
17527
17674
|
window.AXChatSheets = function (o) {
|
|
17528
17675
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
17529
17676
|
function loadPicker() {
|
|
@@ -17569,7 +17716,7 @@ window.AXChatSheets = function (o) {
|
|
|
17569
17716
|
});
|
|
17570
17717
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
17571
17718
|
};
|
|
17572
|
-
`;var
|
|
17719
|
+
`;var nl=`
|
|
17573
17720
|
window.AXChatLog = function (o) {
|
|
17574
17721
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
17575
17722
|
function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
|
|
@@ -17632,7 +17779,7 @@ window.AXChatLog = function (o) {
|
|
|
17632
17779
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
17633
17780
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
17634
17781
|
};
|
|
17635
|
-
`;var
|
|
17782
|
+
`;var rl=`
|
|
17636
17783
|
(function () {
|
|
17637
17784
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
17638
17785
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -17782,7 +17929,7 @@ window.AXChatLog = function (o) {
|
|
|
17782
17929
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
17783
17930
|
poll();
|
|
17784
17931
|
})();
|
|
17785
|
-
`;var
|
|
17932
|
+
`;var ol=`
|
|
17786
17933
|
.cs { margin: 0 -2px; }
|
|
17787
17934
|
.cs[hidden] { display: none; }
|
|
17788
17935
|
.cs-list {
|
|
@@ -17838,7 +17985,7 @@ window.AXChatLog = function (o) {
|
|
|
17838
17985
|
@media (prefers-reduced-motion: reduce) {
|
|
17839
17986
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
17840
17987
|
}
|
|
17841
|
-
`;function
|
|
17988
|
+
`;function sl(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 il(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var ll=`
|
|
17842
17989
|
body { height: 100dvh; }
|
|
17843
17990
|
main { min-height: 0; }
|
|
17844
17991
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -17948,7 +18095,7 @@ main { min-height: 0; }
|
|
|
17948
18095
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
17949
18096
|
}
|
|
17950
18097
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
17951
|
-
`;var
|
|
18098
|
+
`;var cl=`
|
|
17952
18099
|
window.AXOrb = (function () {
|
|
17953
18100
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
17954
18101
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -18065,7 +18212,7 @@ window.AXOrb = (function () {
|
|
|
18065
18212
|
}
|
|
18066
18213
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
18067
18214
|
})();
|
|
18068
|
-
`;var
|
|
18215
|
+
`;var dl=`
|
|
18069
18216
|
window.AXVoiceIO = (function () {
|
|
18070
18217
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
18071
18218
|
var ac = null, playing = null;
|
|
@@ -18183,7 +18330,7 @@ window.AXVoiceIO = (function () {
|
|
|
18183
18330
|
|
|
18184
18331
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
18185
18332
|
})();
|
|
18186
|
-
`;var
|
|
18333
|
+
`;var pl=`
|
|
18187
18334
|
(function () {
|
|
18188
18335
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
18189
18336
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -18396,7 +18543,7 @@ window.AXVoiceIO = (function () {
|
|
|
18396
18543
|
idle();
|
|
18397
18544
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
18398
18545
|
})();
|
|
18399
|
-
`;var
|
|
18546
|
+
`;var ul=`
|
|
18400
18547
|
.vx {
|
|
18401
18548
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
18402
18549
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -18432,7 +18579,7 @@ window.AXVoiceIO = (function () {
|
|
|
18432
18579
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
18433
18580
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
18434
18581
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
18435
|
-
`;var
|
|
18582
|
+
`;var ml=`
|
|
18436
18583
|
<main class="card">
|
|
18437
18584
|
<h1>This phone isn't paired</h1>
|
|
18438
18585
|
<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>
|
|
@@ -18446,7 +18593,7 @@ window.AXVoiceIO = (function () {
|
|
|
18446
18593
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
18447
18594
|
</form>
|
|
18448
18595
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
18449
|
-
</main>`,
|
|
18596
|
+
</main>`,fl=`
|
|
18450
18597
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
18451
18598
|
.pair-form label { font-weight: 600; }
|
|
18452
18599
|
.pair-form input {
|
|
@@ -18468,7 +18615,7 @@ window.AXVoiceIO = (function () {
|
|
|
18468
18615
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
18469
18616
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
18470
18617
|
}
|
|
18471
|
-
`,
|
|
18618
|
+
`,hl=`
|
|
18472
18619
|
(function () {
|
|
18473
18620
|
var form = document.getElementById('pair-form');
|
|
18474
18621
|
var input = document.getElementById('pair-code');
|
|
@@ -18560,7 +18707,7 @@ window.AXVoiceIO = (function () {
|
|
|
18560
18707
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
18561
18708
|
}
|
|
18562
18709
|
})();
|
|
18563
|
-
`;var
|
|
18710
|
+
`;var gl=`
|
|
18564
18711
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
18565
18712
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
18566
18713
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -18569,7 +18716,7 @@ window.AXVoiceIO = (function () {
|
|
|
18569
18716
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
18570
18717
|
</div>
|
|
18571
18718
|
<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>
|
|
18572
|
-
</div>`,
|
|
18719
|
+
</div>`,xl=`
|
|
18573
18720
|
.pair-form .scan-btn {
|
|
18574
18721
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
18575
18722
|
}
|
|
@@ -18598,7 +18745,7 @@ window.AXVoiceIO = (function () {
|
|
|
18598
18745
|
}
|
|
18599
18746
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
18600
18747
|
body.scanning { overflow: hidden; }
|
|
18601
|
-
`,
|
|
18748
|
+
`,vl=`
|
|
18602
18749
|
(function () {
|
|
18603
18750
|
var openBtn = document.getElementById('scan-btn');
|
|
18604
18751
|
var box = document.getElementById('scan');
|
|
@@ -18764,7 +18911,7 @@ body.scanning { overflow: hidden; }
|
|
|
18764
18911
|
document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
|
|
18765
18912
|
window.addEventListener('pagehide', close);
|
|
18766
18913
|
})();
|
|
18767
|
-
`;var
|
|
18914
|
+
`;var an=`
|
|
18768
18915
|
.cam { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; background: var(--ax-bg); }
|
|
18769
18916
|
.cam[hidden] { display: none; }
|
|
18770
18917
|
.cam-live {
|
|
@@ -18806,7 +18953,7 @@ body.scanning { overflow: hidden; }
|
|
|
18806
18953
|
border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
|
|
18807
18954
|
}
|
|
18808
18955
|
.cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
|
|
18809
|
-
`;var
|
|
18956
|
+
`;var bl='<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>',yl=`
|
|
18810
18957
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
18811
18958
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
18812
18959
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -18831,7 +18978,7 @@ body.scanning { overflow: hidden; }
|
|
|
18831
18978
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
18832
18979
|
</div>
|
|
18833
18980
|
</div>
|
|
18834
|
-
</div>`,
|
|
18981
|
+
</div>`,wl=`
|
|
18835
18982
|
(function () {
|
|
18836
18983
|
var btn = document.getElementById('cam-btn');
|
|
18837
18984
|
var sheet = document.getElementById('cam');
|
|
@@ -19100,7 +19247,7 @@ body.scanning { overflow: hidden; }
|
|
|
19100
19247
|
});
|
|
19101
19248
|
window.addEventListener('pagehide', function () { stop(); });
|
|
19102
19249
|
})();
|
|
19103
|
-
`;var
|
|
19250
|
+
`;var kl=`
|
|
19104
19251
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
19105
19252
|
<div class="cam-askbar-text">
|
|
19106
19253
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -19110,7 +19257,7 @@ body.scanning { overflow: hidden; }
|
|
|
19110
19257
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
19111
19258
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
19112
19259
|
</div>
|
|
19113
|
-
</div>`,
|
|
19260
|
+
</div>`,_l=`
|
|
19114
19261
|
.cam-askbar[hidden] { display: none; }
|
|
19115
19262
|
.cam-askbar {
|
|
19116
19263
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -19125,7 +19272,7 @@ body.scanning { overflow: hidden; }
|
|
|
19125
19272
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
19126
19273
|
}
|
|
19127
19274
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
19128
|
-
`,
|
|
19275
|
+
`,Sl=`
|
|
19129
19276
|
(function () {
|
|
19130
19277
|
var bar = document.getElementById('cam-ask-bar');
|
|
19131
19278
|
if (!bar) return;
|
|
@@ -19195,7 +19342,7 @@ body.scanning { overflow: hidden; }
|
|
|
19195
19342
|
setInterval(poll, 5000);
|
|
19196
19343
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
19197
19344
|
})();
|
|
19198
|
-
`;function
|
|
19345
|
+
`;function El(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 Tl(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}var Al=`
|
|
19199
19346
|
(function () {
|
|
19200
19347
|
var main = document.querySelector('main');
|
|
19201
19348
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
@@ -19283,8 +19430,15 @@ body.scanning { overflow: hidden; }
|
|
|
19283
19430
|
if (g) { end(true); return; } // a second finger: let go
|
|
19284
19431
|
if (ev.touches.length !== 1 || !swipeMayStart(pathFrom(ev.target))) return;
|
|
19285
19432
|
var t = ev.touches[0];
|
|
19286
|
-
g = { x: t.clientX, y: t.clientY, trail: [{ dx: 0, t: Date.now() }], axis: '', dx: 0, side: 0, peek: null, index: current() };
|
|
19433
|
+
g = { x: t.clientX, y: t.clientY, trail: [{ dx: 0, t: Date.now() }], axis: '', dx: 0, side: 0, peek: null, index: current(), target: ev.target };
|
|
19287
19434
|
}, { passive: true });
|
|
19435
|
+
// The touched node left the page: its events no longer arrive here.
|
|
19436
|
+
if (window.MutationObserver) {
|
|
19437
|
+
new window.MutationObserver(function () {
|
|
19438
|
+
if (!g || sliding || !g.target || main.contains(g.target)) return;
|
|
19439
|
+
if (g.axis === 'x') end(false); else g = null;
|
|
19440
|
+
}).observe(main, { childList: true, subtree: true });
|
|
19441
|
+
}
|
|
19288
19442
|
main.addEventListener('touchmove', function (ev) {
|
|
19289
19443
|
if (!g || sliding) return;
|
|
19290
19444
|
var t = ev.touches[0], dx = t.clientX - g.x;
|
|
@@ -19307,7 +19461,7 @@ body.scanning { overflow: hidden; }
|
|
|
19307
19461
|
main.addEventListener('touchend', function () { end(false); });
|
|
19308
19462
|
main.addEventListener('touchcancel', function () { end(true); });
|
|
19309
19463
|
})();
|
|
19310
|
-
`,
|
|
19464
|
+
`,Cl=`
|
|
19311
19465
|
main { position: relative; }
|
|
19312
19466
|
main.sw-on { overflow: hidden; }
|
|
19313
19467
|
.sw-on > [role=tabpanel] { will-change: transform; }
|
|
@@ -19318,8 +19472,8 @@ main > .sw-peek {
|
|
|
19318
19472
|
}
|
|
19319
19473
|
main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
|
|
19320
19474
|
@media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
|
|
19321
|
-
`;function
|
|
19322
|
-
${
|
|
19475
|
+
`;function Il(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 Ml(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Ll(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Rl(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 nn=`
|
|
19476
|
+
${B({afterUnauthorized:ao})}
|
|
19323
19477
|
var CACHE = 'agentx-app-v3';
|
|
19324
19478
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
19325
19479
|
self.addEventListener('install', function (e) {
|
|
@@ -19410,7 +19564,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19410
19564
|
return self.clients.openWindow(target);
|
|
19411
19565
|
}));
|
|
19412
19566
|
});
|
|
19413
|
-
`;var
|
|
19567
|
+
`;var Hm="<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 rn(t){return`<meta charset="utf-8">
|
|
19414
19568
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
19415
19569
|
<meta name="theme-color" content="#2979FF">
|
|
19416
19570
|
<meta name="referrer" content="no-referrer">
|
|
@@ -19421,57 +19575,57 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19421
19575
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
19422
19576
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
19423
19577
|
<title>${t}</title>
|
|
19424
|
-
${
|
|
19425
|
-
<style>${
|
|
19578
|
+
${Hm}
|
|
19579
|
+
<style>${He}${Xi}${Fm}</style>`}var Bm={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"},$l=[{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 Pl(){let t=$l.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="${Bm[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=$l.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
19426
19580
|
<h2>${a.label}</h2>
|
|
19427
19581
|
<p class="soon">${a.soon}</p>
|
|
19428
19582
|
</section>`).join("");return`<!doctype html>
|
|
19429
19583
|
<html lang="en">
|
|
19430
|
-
<head>${
|
|
19584
|
+
<head>${rn("AgentX")}<style>${Um}${Yi}${ll}${ol}${ul}${an}${_l}${Cl}${Ki}</style></head>
|
|
19431
19585
|
<body>
|
|
19432
19586
|
<header class="bar">
|
|
19433
19587
|
<div>
|
|
19434
19588
|
<h1>AgentX</h1>
|
|
19435
19589
|
<p id="who" class="who">Connecting\u2026</p>
|
|
19436
19590
|
</div>
|
|
19437
|
-
<div class="bar-btns">${
|
|
19591
|
+
<div class="bar-btns">${bl}<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>
|
|
19438
19592
|
</header>
|
|
19439
19593
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
19440
|
-
${
|
|
19594
|
+
${kl}
|
|
19441
19595
|
<main>${e}</main>
|
|
19442
19596
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
19443
|
-
${
|
|
19444
|
-
<script>${
|
|
19445
|
-
<script>${
|
|
19446
|
-
<script>${
|
|
19447
|
-
<script>${
|
|
19448
|
-
<script>${
|
|
19449
|
-
<script>${
|
|
19450
|
-
<script>${
|
|
19451
|
-
<script>${
|
|
19452
|
-
<script>${
|
|
19453
|
-
<script>${
|
|
19454
|
-
<script>${
|
|
19597
|
+
${yl}
|
|
19598
|
+
<script>${zm}</script>
|
|
19599
|
+
<script>${B({swipeMayStart:Il,swipeAxis:Ml,swipeOffset:Ll,swipeLanding:Rl})}${Al}</script>
|
|
19600
|
+
<script>${Ji}</script>
|
|
19601
|
+
<script>${Vi}</script>
|
|
19602
|
+
<script>${Qi}</script>
|
|
19603
|
+
<script>${Zi}</script>
|
|
19604
|
+
<script>${B({markdownToHtml:Vn})}${tl}${nl}${al}${el}</script>
|
|
19605
|
+
<script>${B({queueSpeech:sl,nextSpeech:il})}${cl}${dl}${pl}</script>
|
|
19606
|
+
<script>${rl}</script>
|
|
19607
|
+
<script>${B({cameraConstraints:El,shareClock:Tl})}${wl}</script>
|
|
19608
|
+
<script>${Sl}</script>
|
|
19455
19609
|
</body>
|
|
19456
|
-
</html>`}function
|
|
19610
|
+
</html>`}function jl(){return`<!doctype html>
|
|
19457
19611
|
<html lang="en">
|
|
19458
|
-
<head>${
|
|
19612
|
+
<head>${rn("Pair \xB7 AgentX")}</head>
|
|
19459
19613
|
<body>
|
|
19460
19614
|
<main class="card">
|
|
19461
19615
|
<h1>Pairing this phone\u2026</h1>
|
|
19462
19616
|
<p id="msg" role="status">One moment.</p>
|
|
19463
19617
|
</main>
|
|
19464
|
-
<script>${
|
|
19618
|
+
<script>${qm}</script>
|
|
19465
19619
|
</body>
|
|
19466
|
-
</html>`}function
|
|
19620
|
+
</html>`}function Ol(){return`<!doctype html>
|
|
19467
19621
|
<html lang="en">
|
|
19468
|
-
<head>${
|
|
19469
|
-
<body>${
|
|
19470
|
-
<script>${
|
|
19471
|
-
<script>${
|
|
19472
|
-
<script>${
|
|
19622
|
+
<head>${rn("Not paired \xB7 AgentX")}<style>${fl}${xl}</style></head>
|
|
19623
|
+
<body>${ml}${gl}
|
|
19624
|
+
<script>${B({mayBounce:no,formatPairInput:Dt,parsePairScan:ro})}</script>
|
|
19625
|
+
<script>${hl}</script>
|
|
19626
|
+
<script>${vl}</script>
|
|
19473
19627
|
</body>
|
|
19474
|
-
</html>`}function
|
|
19628
|
+
</html>`}function Nl(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var zm=`
|
|
19475
19629
|
(function () {
|
|
19476
19630
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
19477
19631
|
function select(tab, focus, keepHash) {
|
|
@@ -19543,7 +19697,7 @@ ${sl}
|
|
|
19543
19697
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
19544
19698
|
}
|
|
19545
19699
|
})();
|
|
19546
|
-
`,
|
|
19700
|
+
`,qm=`
|
|
19547
19701
|
(function () {
|
|
19548
19702
|
var msg = document.getElementById('msg');
|
|
19549
19703
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -19560,7 +19714,7 @@ ${sl}
|
|
|
19560
19714
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
19561
19715
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
19562
19716
|
})();
|
|
19563
|
-
`,
|
|
19717
|
+
`,Fm=`
|
|
19564
19718
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
19565
19719
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
19566
19720
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -19572,7 +19726,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
19572
19726
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
19573
19727
|
.muted { color: var(--ax-text-2); }
|
|
19574
19728
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
19575
|
-
`,
|
|
19729
|
+
`,Um=`
|
|
19576
19730
|
body { display: flex; flex-direction: column; }
|
|
19577
19731
|
.bar {
|
|
19578
19732
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -19610,8 +19764,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
19610
19764
|
}
|
|
19611
19765
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
19612
19766
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
19613
|
-
`;var
|
|
19614
|
-
`;
|
|
19767
|
+
`;var aa="agentx_app",Xm=400*86400,Km=new St,Jm=new Te;async function Dl(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new F;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ve(e,200,"application/manifest+json",Nl());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ve(e,200,"text/javascript; charset=utf-8",nn);if(a==="/app/icon-192.png")return ve(e,200,"image/png",ze(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ve(e,200,"image/png",ze(512),"public, max-age=86400");if(a==="/app/pair")return ve(e,200,"text/html; charset=utf-8",jl());if(a==="/app/qr.js"){let i=Vm();return i?ve(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Pe(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=on(nt(t),o);return i?(e.setHeader("Set-Cookie",sn(nt(t))),Pe(e,200,{device:i.name})):Pe(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Jn(t,{codes:r.pairCodes??new vt,limiter:r.pairLimiter??Km,verify:l=>on(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",sn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Pe(e,i.status,i.body)}let s=on(Ym(t),o);if(!s){let i=nt(t);return(r.rejectLog??Jm).record(a.slice(0,120),Ot(t,Be(ln(t,aa),o),i?Be(i,o):null)),a==="/app"?ve(e,401,"text/html; charset=utf-8",Ol()):Pe(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=ln(t,aa);return i&&!nt(t)&&e.setHeader("Set-Cookie",sn(i)),ve(e,200,"text/html; charset=utf-8",Pl())}return n==="GET"&&a==="/api/app/me"?Pe(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Kn(t,e,a,n,s.name,r.fleet)||r.push&&await _i(t,e,a,n,s,r.push)||r.announce&&await Ti(t,e,a,n,s,r.announce)||r.chat&&await Ni(t,e,a,n,s,r.chat)||r.chat&&await zi(t,e,a,n,s,r.chat)||r.voice&&await Ui(t,e,a,n,s,r.voice)||r.camera&&await Wi(t,e,a,n,r.camera)?!0:Pe(e,404,{error:"not found"})}var at;function Vm(){if(at!==void 0)return at;try{let t=Gm(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
19768
|
+
`;at=Buffer.concat([Buffer.from(a),Wm(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),at=null}return at}function on(t,e){if(!t)return null;let a=e.verify(t);return a&&_e(a,"app")?a:null}function sn(t){return`${aa}=${t}; Path=/; Max-Age=${Xm}; HttpOnly; Secure; SameSite=Lax`}function Ym(t){return nt(t)??ln(t,aa)}function nt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ln(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 ve(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Pe(t,e,a){return ve(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Hl}from"crypto";var je={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},Qm=/^[a-f0-9]{32}$/,Zm=/^c[a-z0-9]{8,32}$/,ef=/^#[0-9a-fA-F]{6}$/;function cn(t){return Zm.test(t)}var rt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
19615
19769
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
19616
19770
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
19617
19771
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -19624,39 +19778,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
19624
19778
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
19625
19779
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
19626
19780
|
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 (
|
|
19627
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return
|
|
19628
|
-
(id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!
|
|
19781
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return cn(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)}${Hl(4).toString("hex")}`,{color:s,...i}=a,l=s&&ef.test(s)?s:void 0,c={id:o,title:af(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
19782
|
+
(id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!cn(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(tf);return{...Bl(n),messages:r}}list(e,a=je.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
19629
19783
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
19630
19784
|
(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
|
|
19631
|
-
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{...
|
|
19785
|
+
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{...Bl(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){cn(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,
|
|
19632
19786
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
19633
19787
|
FROM app_chat_conversations c
|
|
19634
19788
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
19635
19789
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
19636
19790
|
ORDER BY m.at DESC, m.id DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>({id:r.id,title:r.title,agent:r.agent,...r.agent_name?{agentName:r.agent_name}:{},...r.color?{color:r.color}:{},answer:String(r.answer??"").trim(),status:r.status==="error"||r.status==="stopped"?r.status:"done",at:r.at}))}append(e,a,n){return this.appendWithFiles(e,a,n)!==null}appendWithFiles(e,a,n,r=[]){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return null;let s=n.content.length>je.content?n.content.slice(0,je.content)+`
|
|
19637
19791
|
|
|
19638
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let m of r){if(l.length>=je.filesPerMessage)break;let h=m.filename.trim(),
|
|
19792
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let m of r){if(l.length>=je.filesPerMessage)break;let h=m.filename.trim(),_=On(h);if(!_||!h||h.length>le.pathChars||h.includes("\0"))continue;let v=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Hl(16).toString("hex"),name:v,mime:_.mime,kind:_.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
19639
19793
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,c.length?JSON.stringify(c):null,n.at),u=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
|
|
19640
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)u.run(m.id,a,Number(
|
|
19794
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)u.run(m.id,a,Number(p.lastInsertRowid),m.path,m.name,m.mime,m.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
19641
19795
|
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,je.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
|
|
19642
|
-
(SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!
|
|
19796
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!Qm.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
19643
19797
|
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 = ?
|
|
19644
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,je.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function
|
|
19798
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,je.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function Bl(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 tf(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 af(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var nf=4e3,dn=100,rf=15,zl=t=>t.replace(/\/+$/,""),na=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=nf){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,dn);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??rf)-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>=dn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${dn}); 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||zl(l)!==zl(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=of(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&Zt(h)&&this.deps.notifyFinish(ea(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function of(t,e){let a=t.plain?{text:ht(t.text,!1),artifacts:[]}:ft(t.text,le.perMessage,!1),{cleanText:n,ui:r}=xt(a.text),o=t.plain?void 0:Ja(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:sf(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function sf(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Sn();function Ge(){let t=dt();return t&&we(t,"dashboard"),t}function Zw(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let h of a)try{s.set(h.id,bf(h,t))}catch(_){console.error(` Board "${h.id}" failed to initialize: ${_.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?ot(process.cwd(),t.workflows.dir):void 0,c=new Rn(l?{baseDir:l}:void 0),p=new $n(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new Pn(l?{baseDir:l}:void 0);qs(t),Ge(),nr({business:t.business?.enabled===!0});let m=lf(async(h,_)=>{try{await hf(h,_,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(v){y(_,500,{error:v.message||"internal error"})}});Of(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
19645
19799
|
Live dashboard: http://${h}:${n}
|
|
19646
19800
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
19647
19801
|
Kanban dashboard: http://${h}:${n}
|
|
19648
|
-
`),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Vm=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Ym(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){y(e,404,{error:"not found"});return}if(Wn(t.headers)==="foreign"&&Gn(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await go(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:Cl(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(p,f)=>Br(p,f,{gitlab:a.config.channels.gitlab?.host})})||await Sl(t,e,r,o,{nodeName:a.config.node?.name,fleet:Pl(a.config),push:$l(a.config),announce:fi(a.config),chat:jl(a.config),voice:yf(a.config),camera:wf(a.config)}))return;if(o==="GET"&&Vm.has(r)&&Ar("page",r),o==="GET"&&r==="/"){let p=mr();if(!p.configExists||p.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ti({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[p]=await we(a.config);if(!p){y(e,503,{error:"no node available"});return}let f=await new Promise(b=>{let _="";t.on("data",T=>_+=T),t.on("end",()=>b(_)),t.on("error",()=>b(""))}),x=await fetch(p.url+r,{method:"POST",headers:{"Content-Type":"application/json",...p.token?{Authorization:`Bearer ${p.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(p){y(e,502,{error:"could not reach the node",message:String(p?.message||p)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let p=await we(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await pe(t):void 0,b=x?.node??f,_=b?p.find(I=>I.url===b):p[0];if(!_){y(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",w=await fetch(_.url+r+T,{method:o,headers:{"Content-Type":"application/json",..._.token?{Authorization:`Bearer ${_.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,w.status,await w.json().catch(()=>({error:`HTTP ${w.status}`})))}catch(p){y(e,502,{error:"could not reach the node",message:p?.message||String(p)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let p=await pe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(p??{})}),_=await b.json().catch(()=>({error:`HTTP ${b.status}`}));y(e,b.status,_)}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[p]=await we(a.config);if(!p){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(p.url+"/api/n8n/workflows",{headers:p.token?{Authorization:`Bearer ${p.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Or({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(Rr({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let p=new AbortController,f=setTimeout(()=>p.abort(),8e3);try{let x=Cn(await we(a.config,p.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:p.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));y(e,200,{nodes:I});return}let b=x.find(I=>I.url===n.searchParams.get("node"));if(!b){y(e,400,{error:"Select a known node"});return}let _=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(_)||o==="POST"&&["register","ended","action","retry","clear"].includes(_))){y(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await An(t)):void 0,w=await fetch(b.url+"/monitor/"+_+(_==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):_==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:p.signal,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}}});y(e,w.status,await w.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vs({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ys({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await pe(t).catch(()=>({})):void 0,b=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:p,...x!==void 0?{body:JSON.stringify(x??{})}:{}});y(e,b.status,await b.json().catch(()=>({error:`HTTP ${b.status}`})))}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ai({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ni({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ri({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let p=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!p){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(oi({taskId:decodeURIComponent(i[1]),agentId:p,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 l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(si({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){fr(t,e);return}if(o==="POST"&&r==="/api/setup"){await hr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await gr(t,e);return}if(o==="GET"&&r==="/admin"){Ao(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Uo(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Po(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}es(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let p=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(p==="fleet"){if(r==="/api/admin/activity-graph"){await Af(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Oa(t,e,r,x=>Nl(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),b=x.indexOf("::");if(b>0){let _=x.slice(0,b),T=x.slice(b+2),w=a.config.node?.id||a.config.node?.name||"local";if(_===w)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===_);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await Ml(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}y(e,404,{error:`unknown node "${_}" in fleet dispatch id`});return}}}}else if(p&&p!=="primary"){let f=nt(p,a.config);if(!f){y(e,404,{error:`unknown peer: ${p}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,_=>_.startsWith("?")?"?":"");await Ml(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await ts(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Cf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:p}=await import("./doctor-GHUPUBET.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",b=await p({running:x});y(e,200,b)}catch(p){y(e,500,{error:p?.message||String(p)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(os({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await rs(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ss({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(is({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 rf(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 Ms(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Oa(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Rs(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){js(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let p=t.headers.authorization||"",f=p.startsWith("Bearer ")?p.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!ke(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Co(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,Vn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Wo(t,e,r,n);return}if(await Xo(t,e,r,{people:()=>Ke(a.config.people),members:Cl(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await jo(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Os(t,e,r);return}if(r.startsWith("/api/admin/")){await Io(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(xo);return}if(o==="GET"&&r.startsWith("/assets/")){let p=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(p)){y(e,400,{error:"invalid asset name"});return}let f=Ef("web/"+p);try{let x=await Tf(f),b=p.endsWith(".map")?"application/json; charset=utf-8":p.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",_=n.searchParams.has("v");e.writeHead(200,{"Content-Type":b,"Cache-Control":_?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let p=await We(a.config);y(e,200,p)}catch(p){y(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let p=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:p,timezone:f});y(e,200,x)}catch(p){y(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let p=(f,x,b,_)=>{let T=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(T)?Math.max(b,Math.min(_,T)):x};try{let f=await we(a.config);y(e,200,await Qs(f,{days:p("days",30,0,180),tzOffsetMinutes:p("tzOffset",0,-840,840),limit:p("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let p=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(p)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,b,_,T)=>{let w=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(w)?Math.max(_,Math.min(T,w)):b};try{let x=await we(a.config);y(e,200,await ei(x,{day:p,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let p=n.searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[b,_,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!_||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(_)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[b,_]=[f.get("kind"),f.get("key")];if(!b||!_){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(b)}&key=${encodeURIComponent(_)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[b,_,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!_||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(_)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let b=f.get("task");if(!b){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(b)}`}try{await Zs(e,await we(a.config),p,x)}catch(b){y(e,502,{error:b.message})}return}if(o==="GET"&&r==="/api/live/stream"){uf(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("agent"),b=p.searchParams.get("task");if(!f||!x||!b){y(e,400,{error:"node, agent, task query params required"});return}await mf(t,e,a,f,x,b);return}if(o==="GET"&&r==="/api/task/history"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("agent"),b=p.searchParams.get("task"),_=p.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await gf(e,a,f,x,b,_);return}if(o==="POST"&&r==="/api/task/action"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("task"),b=p.searchParams.get("kind");if(!f||!x||b!=="cancel"&&b!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await xf(t,e,a,f,x,b);return}if(o==="POST"&&r==="/api/voice/stop"){let p=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}await on(t,e,a,p,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:p});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(p){y(e,502,{error:p.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:p});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(p){y(e,502,{error:p.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let p=await pe(t);try{let f=await _f(a.config,p);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let p=d[1];if(!ff(t,e,[`agent:${p}`]))return;await hf(t,e,a.config,p);return}if(o==="GET"&&r==="/api/node/build"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:p,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);y(e,200,Jn(await f.json()))}catch(p){y(e,502,{error:p.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let p=t.headers.authorization||"",f=p.startsWith("Bearer ")?p.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!ke(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await of(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let p=n.searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}await on(t,e,a,p,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(w=>({name:w.name,url:w.url,token:w.token}))],b={flag:!1},_=[];t.on("close",()=>{b.flag=!0;for(let w of _)try{w.abort()}catch{}});let T=setInterval(()=>{if(!b.flag)try{e.write(`: ping
|
|
19802
|
+
`),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 ff=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function hf(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){y(e,404,{error:"not found"});return}if(tr(t.headers)==="foreign"&&ar(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Io(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ye(a.config.people),members:ql(a.config.members.logRetentionDays),db:()=>Ge(),linkFor:(d,f)=>Vr(d,f,{gitlab:a.config.channels.gitlab?.host})})||await Dl(t,e,r,o,{nodeName:a.config.node?.name,fleet:Kl(a.config),push:Xl(a.config),announce:Ai(a.config),chat:Jl(a.config),voice:Nf(a.config),camera:Df(a.config)}))return;if(o==="GET"&&ff.has(r)&&Nr("page",r),o==="GET"&&r==="/"){let d=_r();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({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(Xa({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ke(a.config);if(!d){y(e,503,{error:"no node available"});return}let f=await new Promise(b=>{let k="";t.on("data",T=>k+=T),t.on("end",()=>b(k)),t.on("error",()=>b(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await ke(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await pe(t):void 0,b=x?.node??f,k=b?d.find(I=>I.url===b):d[0];if(!k){y(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",w=await fetch(k.url+r+T,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,w.status,await w.json().catch(()=>({error:`HTTP ${w.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await pe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await b.json().catch(()=>({error:`HTTP ${b.status}`}));y(e,b.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ke(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gr({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(qr({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,f=setTimeout(()=>d.abort(),8e3);try{let x=Dn(await ke(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));y(e,200,{nodes:I});return}let b=x.find(I=>I.url===n.searchParams.get("node"));if(!b){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await Nn(t)):void 0,w=await fetch(b.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}}});y(e,w.status,await w.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ci({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(di({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await pe(t).catch(()=>({})):void 0,b=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});y(e,b.status,await b.json().catch(()=>({error:`HTTP ${b.status}`})))}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hi({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xi({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(vi({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:D(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(bi({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Sr(t,e);return}if(o==="POST"&&r==="/api/setup"){await Er(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Tr(t,e);return}if(o==="GET"&&r==="/admin"){Bo(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){ns(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Xo(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}ms(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Uf(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Wa(t,e,r,x=>Yl(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),b=x.indexOf("::");if(b>0){let k=x.slice(0,b),T=x.slice(b+2),w=a.config.node?.id||a.config.node?.name||"local";if(k===w)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(I){let C=st(I.url.replace(/\/+$/,""),a.config);if(C){await Ul(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let f=st(d,a.config);if(!f){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Ul(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await fs(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Wf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-XP7O45RC.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",b=await d({running:x});y(e,200,b)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(vs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await xs(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(bs({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(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 kf(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 Fs(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Wa(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ws(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Ks(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!_e(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await zo(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,sr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await rs(t,e,r,n);return}if(await ss(t,e,r,{people:()=>Ye(a.config.people),members:ql(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ge(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Ko(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Js(t,e,r);return}if(r.startsWith("/api/admin/")){await qo(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(Mo);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let f=qf("web/"+d);try{let x=await Ff(f),b=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":b,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Xe(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await Xe(a.config,{date:d,timezone:f});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(f,x,b,k)=>{let T=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(T)?Math.max(b,Math.min(k,T)):x};try{let f=await ke(a.config);y(e,200,await pi(f,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,b,k,T)=>{let w=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(w)?Math.max(k,Math.min(T,w)):b};try{let x=await ke(a.config);y(e,200,await mi(x,{day:d,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[b,k,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!k||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[b,k]=[f.get("kind"),f.get("key")];if(!b||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(b)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[b,k,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!k||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let b=f.get("task");if(!b){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(b)}`}try{await ui(e,await ke(a.config),d,x)}catch(b){y(e,502,{error:b.message})}return}if(o==="GET"&&r==="/api/live/stream"){If(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),b=d.searchParams.get("task");if(!f||!x||!b){y(e,400,{error:"node, agent, task query params required"});return}await Mf(t,e,a,f,x,b);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),b=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await $f(e,a,f,x,b,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("task"),b=d.searchParams.get("kind");if(!f||!x||b!=="cancel"&&b!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Pf(t,e,a,f,x,b);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await hn(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await pe(t);try{let f=await Bf(a.config,d);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!Lf(t,e,[`agent:${d}`]))return;await Rf(t,e,a.config,d);return}if(o==="GET"&&r==="/api/node/build"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:d,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);y(e,200,or(await f.json()))}catch(d){y(e,502,{error:d.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!_e(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await _f(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await hn(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(w=>({name:w.name,url:w.url,token:w.token}))],b={flag:!1},k=[];t.on("close",()=>{b.flag=!0;for(let w of k)try{w.abort()}catch{}});let T=setInterval(()=>{if(!b.flag)try{e.write(`: ping
|
|
19649
19803
|
|
|
19650
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let w of x)(async()=>{let I={Accept:"text/event-stream"};w.token&&(I.Authorization=`Bearer ${w.token}`);let C=new AbortController;
|
|
19804
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let w of x)(async()=>{let I={Accept:"text/event-stream"};w.token&&(I.Authorization=`Bearer ${w.token}`);let C=new AbortController;k.push(C);try{let E=await fetch(`${w.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:I,signal:C.signal});if(!E.ok||!E.body)return;let $=E.body.getReader(),L=new TextDecoder,j="";for(;!b.flag;){let{done:W,value:q}=await $.read();if(W)break;j+=L.decode(q,{stream:!0});let G;for(;(G=j.indexOf(`
|
|
19651
19805
|
|
|
19652
19806
|
`))>=0;){let ie=j.slice(0,G);if(j=j.slice(G+2),b.flag)break;try{e.write(ie+`
|
|
19653
19807
|
|
|
19654
|
-
`)}catch{b.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let
|
|
19655
|
-
`;
|
|
19808
|
+
`)}catch{b.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,b=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:f,workflowId:x}),T=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${b?"&summary=1":""}`,w=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(w.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let W=new AbortController,q=setTimeout(()=>W.abort(),5e3);try{let G=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${T}`,{headers:j,signal:W.signal});if(!G.ok)return[];let ie=await G.json();return Array.isArray(ie.runs)?ie.runs:[]}finally{clearTimeout(q)}}catch{return[]}})),C=new Map;for(let L of k)C.set(L.id,L);for(let L of I)for(let j of L)C.set(j.id,j);let E=Array.from(C.values()).sort((L,j)=>L.updatedAt<j.updatedAt?1:-1).slice(0,f),$=b?E.map(L=>vf(L)):E;y(e,200,{runs:$})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let m=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(m){let d=decodeURIComponent(m[1]),f=a.workflowRuns.get(d);if(f){y(e,200,{run:f});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(b=>({url:b.url,token:b.token}))];for(let b of x)try{let k={};b.token&&(k.Authorization=`Bearer ${b.token}`);let T=await fetch(`${b.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(T.ok){y(e,200,await T.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${f}/api/actions/builtin`,{headers:d}),b=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,b)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await pe(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await b.json().catch(()=>({error:`HTTP ${b.status}`}));y(e,b.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&wi(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,x,b)=>{if(a.token)return!0;let k=ga(f);if(!k)return!0;let T=new F().verify(k);if(!T)return y(x,401,{error:"invalid or revoked token"}),!1;for(let w of b)if(!_e(T,w))return y(x,403,{error:`token missing scope: ${w}`,scopes:T.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let v=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(v&&o==="GET"){let d=a.sources.get(v[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,f]=S,x=decodeURIComponent(f),b=a.boards.find(C=>C.id===d);if(!b){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let T=await pe(t),w=b.columns.find(C=>C.id===T.to),I=b.columns.find(C=>C.id===T.from);if(!w){y(e,400,{error:`unknown 'to' column: ${T.to}`});return}try{await xf(k,x,I,w),pn({actor:un(t),action:"move",boardId:d,itemId:x,payload:{from:T.from,to:T.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,f]=g,x=f?decodeURIComponent(f):void 0,b=a.boards.find(T=>T.id===d);if(!b){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:T,totals:w}=await gf(b,k,n.searchParams);y(e,200,{columns:T,totals:w});return}if(o==="GET"&&x){try{let T=typeof k.getItem=="function"?await k.getItem(x):null;if(!T){y(e,404,{error:"not found"});return}y(e,200,T)}catch(T){y(e,502,{error:T.message})}return}if(o==="PATCH"&&x){let T=await pe(t);try{let w=typeof k.updateItem=="function"?await k.updateItem(x,T):null;if(!w){y(e,501,{error:"update unsupported"});return}pn({actor:un(t),action:"update",boardId:d,itemId:x,payload:T}),y(e,200,w)}catch(w){y(e,502,{error:w.message})}return}if(o==="POST"&&!x){let T=await pe(t);if(!T.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let w=await k.create({title:T.title,description:T.description,labels:T.labels,assigneeUsernames:T.assigneeUsernames,milestoneTitle:T.milestoneTitle,projectHint:T.projectHint});pn({actor:un(t),action:"create",boardId:d,itemId:w.id,payload:{title:T.title}}),y(e,201,w)}catch(w){y(e,502,{error:w.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}y(e,404,{error:"not found",path:r})}async function gf(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let f of t.columns)d[f.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(f=>[f.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let d of t.columns)_[d.id]=[];let v=t.columns.find(d=>d.kind==="closed");for(let d of h)v&&_[v.id].push({...d,stage:v.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of m){let f=vn(d,S);if(!f)continue;let x=_[f];x&&x.push({...d,stage:f})}if(i)for(let d of Object.keys(_))_[d]=_[d].filter(f=>f.assignee===i);for(let d of Object.keys(_))_[d].sort((f,x)=>{let b=(f.priority??99)-(x.priority??99);return b!==0?b:(x.updatedAt||"").localeCompare(f.updatedAt||"")});let g=Object.fromEntries(Object.entries(_).map(([d,f])=>[d,f.length]));return{columns:_,totals:g}}async function xf(t,e,a,n){let r=bn(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 vf(t){return{id:t.id,workflowId:t.workflowId,workflowVersion:t.workflowVersion,homeNode:t.homeNode,status:t.status,pending:t.pending,entityRef:t.entityRef,history:(t.history||[]).slice(-5),parentRunId:t.parentRunId,parentNodeId:t.parentNodeId,rootRunId:t.rootRunId,depth:t.depth,createdAt:t.createdAt,updatedAt:t.updatedAt}}function bf(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 pr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function pn(t){try{let e=ot(process.cwd(),".agentx");Wl(e)||df(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
19809
|
+
`;cf(ot(e,"board-audit.jsonl"),a)}catch{}}function un(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var yf=2e3;async function wf(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",i=g=>{let d=new AbortController,f=setTimeout(()=>d.abort(),yf),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async b=>{let k=b.ok?await b.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",x)})},[l,c,p,u,m,h,_,v]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,zn.routines))}if(h&&h.ok){let g=await h.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(v&&v.ok){let g=await v.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Cf(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var ra=null;function kf(t){if(ra)return ra;let e=ot(process.cwd(),".agentx/wiki");return ra=Br({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),ra}async function sa(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 _f(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){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function ke(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 sa(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 Sf=3e3,Ef=6e3,Tf=5*6e4,fn=new Map,oa=new Map;function Xe(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=oa.get(a);if(n)return n;let r=(async()=>{let o=await ke(t,AbortSignal.timeout(Sf)),s=await Promise.all(o.map(async i=>{let l=await wf(i.url,i.token,AbortSignal.timeout(Ef),e);return e?l:Af(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>oa.delete(a));return oa.set(a,r),r}function Af(t,e,a=Date.now()){if(e.reachable&&!e.error)return fn.set(t,{node:e,at:a}),e;let n=fn.get(t);return!n||a-n.at>Tf?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function ek(){fn.clear(),oa.clear()}function Cf(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 If(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,c)=>{n||e.write(`event: ${l}
|
|
19656
19810
|
data: ${JSON.stringify(c)}
|
|
19657
19811
|
|
|
19658
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await
|
|
19659
|
-
${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
|
|
19812
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Xe(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 Mf(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 sa(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let v of _)i.add(v.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(_){y(e,502,{error:_.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=u.body.getReader();(async()=>{try{for(;;){let{value:_,done:v}=await m.read();if(v)break;_&&e.write(_)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Lf(t,e,a){let n=ga(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new F().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!_e(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Rf(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await pe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function $f(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await sa(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of u)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:c}),m=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function Pf(t,e,a,n,r,o){await hn(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function hn(t,e,a,n,r){let o={};try{o=await pe(t)??{}}catch{}let s=await Gl(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Gl(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await sa(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function Xl(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=Wn(e.keysFile);return{store:()=>{let r=Ge();return r?new vr(r):null},publicKey:()=>Gn(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Kl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Xe(t,n),async nodePost(n,r,o){let s=await Gl(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=wt({root:process.cwd()}).items.map(Fl)}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=st(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(Fl)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=Se(),p=await kt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=st(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}var mn=null;function ql(t){return mn?.days!==t&&(mn={days:t,store:new mt(process.cwd(),Date.now,t)}),mn.store}function Jl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Kl(t);return{store:()=>{let r=Ge();return r?new rt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:En(process.cwd())??void 0},snapshot:()=>Xe(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(/\/+$/,"")),...jf(t,e,a)}}function jf(t,e,a){let n=Xl(t);return{finishAlerts:r=>{let o=n.store();return!!o&&o.chatFinishOn(r)&&o.list(r).length>0},notifyFinish:async r=>{try{let o=await fetch(e+"/channel/send",{method:"POST",headers:{"Content-Type":"application/json",...a?{Authorization:`Bearer ${a}`}:{}},body:JSON.stringify({channel:"push",chatId:r.deviceId,text:`${r.title}
|
|
19813
|
+
${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 Of(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=Jl(t);return new na({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await Xe(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:Oi(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Nf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ge();return a?new rt(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Df(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function Fl(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var Hf=`
|
|
19660
19814
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
19661
19815
|
|
|
19662
19816
|
Title pattern:
|
|
@@ -19688,10 +19842,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
19688
19842
|
Shape:
|
|
19689
19843
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
19690
19844
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
19691
|
-
`;async function
|
|
19845
|
+
`;async function Bf(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):
|
|
19692
19846
|
- ${r.knownLabels.slice(0,60).join(`
|
|
19693
19847
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
19694
|
-
`),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:
|
|
19848
|
+
`),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:Hf}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),u=zf(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:m,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function zf(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 qf(t){let e=mf(uf(import.meta.url));return ot(e,t)}async function Ff(t){return pf(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function pe(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 Vl(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:Vl(s),tokenScope:s.dashboardToken||s.token?"proxy-ready":void 0})),o=r.length>0?[{id:"fleet",name:"Fleet (all peers)",dashboardUrl:"",tokenScope:"merged across nodes"}]:[];return[n,...r,...o]}async function Uf(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await Jt(await Yl(r,a.config)))}async function Yl(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ua(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=st(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Bs(n)}async function Wf(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",m=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(_=>Wl(_));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:m}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
|
|
19695
19849
|
|
|
19696
19850
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let m;for(;(m=i.indexOf(`
|
|
19697
19851
|
`))>=0;){let h=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
|
|
@@ -19699,5 +19853,5 @@ data: ${h.replace(/\n/g," ")}
|
|
|
19699
19853
|
|
|
19700
19854
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
19701
19855
|
|
|
19702
|
-
`)}catch{}},15e3),
|
|
19703
|
-
//# sourceMappingURL=board-dashboard-
|
|
19856
|
+
`)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function Ul(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,m)=>{let h=[];t.on("data",_=>h.push(_)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function st(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Vl(n),token:n.dashboardToken||n.token}:null}export{Cf as applyAttachSessions,wf as fetchDaemonAgents,hf as handleBoardRequest,ek as resetLiveCaches,ke as resolveNodeTargets,Zw as startBoardDashboard,Af as withLastGood};
|
|
19857
|
+
//# sourceMappingURL=board-dashboard-3TVUCOSI.js.map
|