agentix-cli 0.81.1 → 0.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{App-HF6W6CV2.js → App-3AZUZJPW.js} +2 -2
- package/dist/{ChatApp-74VBWP7R.js → ChatApp-ACIKF3GC.js} +2 -2
- package/dist/{agent-75URYGWI.js → agent-X2UYZ3ZE.js} +2 -2
- package/dist/{board-dashboard-TWEF5XVE.js → board-dashboard-65HGTFRC.js} +485 -235
- package/dist/board-dashboard-65HGTFRC.js.map +1 -0
- package/dist/{chunk-ATXE3EMV.js → chunk-5LD6TA4A.js} +2 -2
- package/dist/{chunk-ES7Z64Z5.js → chunk-6G72CCT2.js} +2 -2
- package/dist/{chunk-LUL4ILAQ.js → chunk-6PTO6DWW.js} +2 -2
- package/dist/{chunk-R64DAHBH.js → chunk-AW3YGAVS.js} +5 -5
- package/dist/{chunk-GUAJNZIX.js → chunk-BM6ZLX6F.js} +2 -2
- package/dist/{chunk-5GXCOHDM.js → chunk-C4YY6746.js} +2 -2
- package/dist/{chunk-4KJ3PCAI.js → chunk-CG3FSQ23.js} +2 -2
- package/dist/{chunk-JG3O5GL6.js → chunk-CT36XINH.js} +2 -2
- package/dist/{chunk-BDM4VTBR.js → chunk-E3SVSIUU.js} +3 -3
- package/dist/chunk-E3SVSIUU.js.map +1 -0
- package/dist/{chunk-WWU2D65N.js → chunk-E63BQ6VJ.js} +2 -2
- package/dist/chunk-FSHQMXM3.js +5 -0
- package/dist/{chunk-XF65CDNS.js.map → chunk-FSHQMXM3.js.map} +1 -1
- package/dist/{chunk-TW4L6RP2.js → chunk-ISRGFMQC.js} +2 -2
- package/dist/{chunk-V4GXHBOH.js → chunk-KUUIIZEH.js} +5 -5
- package/dist/{chunk-74FSHUB3.js → chunk-LQLMNBJS.js} +2 -2
- package/dist/{chunk-XQ7MVPWP.js → chunk-ONGL6EKZ.js} +2 -2
- package/dist/{chunk-3FCYKGU6.js → chunk-PLTX6YGD.js} +2 -2
- package/dist/{chunk-LTHQXWZN.js → chunk-VQN36LEB.js} +2 -2
- package/dist/{chunk-BB3ESU74.js → chunk-WIGJ5BVG.js} +2 -2
- package/dist/{chunk-HUQRPEDP.js → chunk-X7STXQOX.js} +2 -2
- package/dist/chunk-XMDA4JYK.js +748 -0
- package/dist/chunk-XMDA4JYK.js.map +1 -0
- package/dist/{chunk-ZUAV3PTL.js → chunk-ZUCJK5PL.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/client-QE4D43K3.js +2 -0
- package/dist/config-ME774GIO.js +2 -0
- package/dist/config-mutator-2AUDHSVD.js +2 -0
- package/dist/{doctor-6EWW7NC2.js → doctor-GS2ZHLWU.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{program-7UH4FCA3.js → program-R646G4NP.js} +195 -195
- package/dist/{program-7UH4FCA3.js.map → program-R646G4NP.js.map} +1 -1
- package/dist/{promote-ZZWMGVO2.js → promote-ZJCGGVRD.js} +2 -2
- package/dist/{query-OQBB7EFS.js → query-UMGPOBEJ.js} +2 -2
- package/dist/{registry-MDWD7EAO.js → registry-WD5B2DQQ.js} +2 -2
- package/dist/{request-planner-HX44G2SX.js → request-planner-L2S4KMMU.js} +2 -2
- package/dist/{review-candidates-FBDLPU6H.js → review-candidates-R23QNJ2Q.js} +2 -2
- package/dist/{routing-3SZHWHUA.js → routing-PUQUADQ6.js} +2 -2
- package/dist/schedule-tool-3DAJU764.js +2 -0
- package/dist/scheduler-JTPIGC5K.js +2 -0
- package/dist/{seat-2HJG3UNW.js → seat-O5IC5M5D.js} +2 -2
- package/dist/{select-UKAOL7QB.js → select-KCCT7OJZ.js} +2 -2
- package/dist/{set-enabled-ADFSNG5A.js → set-enabled-FEUPS2WI.js} +2 -2
- package/dist/{tool-GPCJM7U5.js → tool-WGPZW3SR.js} +2 -2
- package/dist/{tool-VKQIDEG7.js → tool-YOXUNCTU.js} +2 -2
- package/dist/wiki-QSBAE5ZK.js +2 -0
- package/package.json +1 -1
- package/dist/board-dashboard-TWEF5XVE.js.map +0 -1
- package/dist/chunk-BDM4VTBR.js.map +0 -1
- package/dist/chunk-VVW4JYV6.js +0 -740
- package/dist/chunk-VVW4JYV6.js.map +0 -1
- package/dist/chunk-XF65CDNS.js +0 -5
- package/dist/client-JDY2FZUF.js +0 -2
- package/dist/config-JCETBKWT.js +0 -2
- package/dist/config-mutator-YQWTY47O.js +0 -2
- package/dist/schedule-tool-5FULSHWJ.js +0 -2
- package/dist/scheduler-ITOKSMYT.js +0 -2
- package/dist/wiki-QUVWB4IN.js +0 -2
- /package/dist/{App-HF6W6CV2.js.map → App-3AZUZJPW.js.map} +0 -0
- /package/dist/{ChatApp-74VBWP7R.js.map → ChatApp-ACIKF3GC.js.map} +0 -0
- /package/dist/{agent-75URYGWI.js.map → agent-X2UYZ3ZE.js.map} +0 -0
- /package/dist/{chunk-ATXE3EMV.js.map → chunk-5LD6TA4A.js.map} +0 -0
- /package/dist/{chunk-ES7Z64Z5.js.map → chunk-6G72CCT2.js.map} +0 -0
- /package/dist/{chunk-LUL4ILAQ.js.map → chunk-6PTO6DWW.js.map} +0 -0
- /package/dist/{chunk-R64DAHBH.js.map → chunk-AW3YGAVS.js.map} +0 -0
- /package/dist/{chunk-GUAJNZIX.js.map → chunk-BM6ZLX6F.js.map} +0 -0
- /package/dist/{chunk-5GXCOHDM.js.map → chunk-C4YY6746.js.map} +0 -0
- /package/dist/{chunk-4KJ3PCAI.js.map → chunk-CG3FSQ23.js.map} +0 -0
- /package/dist/{chunk-JG3O5GL6.js.map → chunk-CT36XINH.js.map} +0 -0
- /package/dist/{chunk-WWU2D65N.js.map → chunk-E63BQ6VJ.js.map} +0 -0
- /package/dist/{chunk-TW4L6RP2.js.map → chunk-ISRGFMQC.js.map} +0 -0
- /package/dist/{chunk-V4GXHBOH.js.map → chunk-KUUIIZEH.js.map} +0 -0
- /package/dist/{chunk-74FSHUB3.js.map → chunk-LQLMNBJS.js.map} +0 -0
- /package/dist/{chunk-XQ7MVPWP.js.map → chunk-ONGL6EKZ.js.map} +0 -0
- /package/dist/{chunk-3FCYKGU6.js.map → chunk-PLTX6YGD.js.map} +0 -0
- /package/dist/{chunk-LTHQXWZN.js.map → chunk-VQN36LEB.js.map} +0 -0
- /package/dist/{chunk-BB3ESU74.js.map → chunk-WIGJ5BVG.js.map} +0 -0
- /package/dist/{chunk-HUQRPEDP.js.map → chunk-X7STXQOX.js.map} +0 -0
- /package/dist/{chunk-ZUAV3PTL.js.map → chunk-ZUCJK5PL.js.map} +0 -0
- /package/dist/{client-JDY2FZUF.js.map → client-QE4D43K3.js.map} +0 -0
- /package/dist/{config-JCETBKWT.js.map → config-ME774GIO.js.map} +0 -0
- /package/dist/{config-mutator-YQWTY47O.js.map → config-mutator-2AUDHSVD.js.map} +0 -0
- /package/dist/{doctor-6EWW7NC2.js.map → doctor-GS2ZHLWU.js.map} +0 -0
- /package/dist/{promote-ZZWMGVO2.js.map → promote-ZJCGGVRD.js.map} +0 -0
- /package/dist/{query-OQBB7EFS.js.map → query-UMGPOBEJ.js.map} +0 -0
- /package/dist/{registry-MDWD7EAO.js.map → registry-WD5B2DQQ.js.map} +0 -0
- /package/dist/{request-planner-HX44G2SX.js.map → request-planner-L2S4KMMU.js.map} +0 -0
- /package/dist/{review-candidates-FBDLPU6H.js.map → review-candidates-R23QNJ2Q.js.map} +0 -0
- /package/dist/{routing-3SZHWHUA.js.map → routing-PUQUADQ6.js.map} +0 -0
- /package/dist/{schedule-tool-5FULSHWJ.js.map → schedule-tool-3DAJU764.js.map} +0 -0
- /package/dist/{scheduler-ITOKSMYT.js.map → scheduler-JTPIGC5K.js.map} +0 -0
- /package/dist/{seat-2HJG3UNW.js.map → seat-O5IC5M5D.js.map} +0 -0
- /package/dist/{select-UKAOL7QB.js.map → select-KCCT7OJZ.js.map} +0 -0
- /package/dist/{set-enabled-ADFSNG5A.js.map → set-enabled-FEUPS2WI.js.map} +0 -0
- /package/dist/{tool-GPCJM7U5.js.map → tool-WGPZW3SR.js.map} +0 -0
- /package/dist/{tool-VKQIDEG7.js.map → tool-YOXUNCTU.js.map} +0 -0
- /package/dist/{wiki-QUVWB4IN.js.map → wiki-QSBAE5ZK.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as A,b as
|
|
1
|
+
import{A as Yn,B as Qn,C as er,D as tr,E as ar,a as A,b as Hn,c as Bn,d as zn,e as qn,h as ht,i as ke,j as Fn,k as Un,l as Wn,n as Gn,o as Xn,p as gt,q as xt,r as Kn,u as Jn,v as Vn}from"./chunk-XMDA4JYK.js";import{a as Zn}from"./chunk-BYD5B3P3.js";import{a as $n}from"./chunk-2NYP4OQU.js";import{a as ce,b as Rn}from"./chunk-JWDJMFU6.js";import{a as Dn}from"./chunk-CPXZWVKN.js";import{a as pt,b as z,c as Pn,d as L,i as ut,j as mt,k as re,l as G,m as ft,n as jn,o as On,p as Nn}from"./chunk-O5U5NVLR.js";import{$ as xn,$a as $e,Ga as wn,Ia as kn,Ja as _n,K as Vt,Ka as En,L as mn,M as Yt,N as rt,O as ot,R as fn,S as hn,Sa as Sn,T as gn,Ua as Re,Za as Tn,_ as q,a as rn,aa as vn,ab as st,bb as it,c as at,cb as lt,d as Kt,db as ct,e as on,eb as An,fb as Cn,gb as In,hb as dt,i as nt,jb as Mn,l as qe,mb as Ln,n as sn,p as W,q as we,r as dn,s as Jt}from"./chunk-E3SVSIUU.js";import"./chunk-GTJIKXDB.js";import{g as an,h as nn}from"./chunk-ZUCJK5PL.js";import{p as ln,t as cn}from"./chunk-S2GAEH2F.js";import{a as O,b as bn,c as yn}from"./chunk-CL53UVOF.js";import"./chunk-E63BQ6VJ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as pn,c as un}from"./chunk-2D3RYIDU.js";import{a as Va,f as Ya,g as Gt,h as Xt,l as Qa,m as Za,n as en,u as et,v as tt,w as le,x as tn}from"./chunk-6G72CCT2.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-WIGJ5BVG.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-CG3FSQ23.js";import"./chunk-FSHQMXM3.js";import"./chunk-5LD6TA4A.js";import"./chunk-6PTO6DWW.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as Ja}from"./chunk-BM6ZLX6F.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-C4YY6746.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{B as ji,L as Ka,N as Oi,a as Ua,b as Wa,ba as ne,c as Ri,ea as Wt,v as Ze,w as $i,x as Ft,y as Ut}from"./chunk-VQN36LEB.js";import{b as Ga,h as Pi}from"./chunk-UCKKAWLZ.js";import{a as ye,i as Xa}from"./chunk-PN6XHTG5.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Qt(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 nr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Qt(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"/>'},_e=(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>",vt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+_e(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function rr(t={}){return L({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
|
|
2
2
|
|
|
3
3
|
<div class="bf-head">
|
|
4
4
|
<div>
|
|
@@ -7,8 +7,8 @@ import{a as A,b as Rn,c as Ln,d as $n,e as Pn,h as jn,i as we,j as On,k as Nn,n
|
|
|
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">${_e(oe.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${_e(oe.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{a as A,b as Rn,c as Ln,d as $n,e as Pn,h as jn,i as we,j as On,k as Nn,n
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${vt(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
|
+
${vt(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
|
+
${vt(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
|
+
${vt(oe.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${
|
|
41
|
+
<div class="bf-search">${_e(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 @@ ${ut(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">${_e(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">${_e(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>${_e(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 @@ ${ut(oe.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:Ni,scripts:`<script>${z({decayOf:Qt,rankByDecay:nr})}const ICON = ${JSON.stringify(oe)};${Di}</script>`})}var Ni=`
|
|
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
|
+
}`,Di=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 Zt(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),u=r[r.length-1];u&&l.startedAt-u.to<=e?(u.to=Math.max(u.to,c),u.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let u=1;u<r.length;u++){let p=r[u].from-r[u-1].to;p<c&&(c=p,l=u)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function ea(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function or(t,e=[],a){let{bands:n,gaps:r}=Zt(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(E=>l.startedAt>=E.from&&l.startedAt<=E.to);if(c===-1)continue;let u=n[c],p=u.to-u.from||1,f=(l.startedAt-u.from)/p*100,h=Math.min(Math.max((l.durationMs||0)/p*100,1.2),100-f),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:c,track:0,left:f,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,u)=>ea(l.runs.filter(p=>p.band===u))),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 Hi}from"crypto";import{readFileSync as Bi,statSync as zi}from"fs";import{resolve as qi,dirname as Fi}from"path";import{fileURLToPath as Ui}from"url";var sr=new Map;function bt(t){let e=sr.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Fi(Ui(import.meta.url)),r=qi(n,"web",t),o=zi(r),s=o.size<8e6?Hi("sha1").update(Bi(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return sr.set(t,a),a}var de={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},yt=(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>",Wi=[["agent","Agent",de.bot],["client","Client",de.user],["project","Project",de.folder],["channel","Channel",de.route],["node","Node",de.mesh]],ir={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 lr(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return L({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
|
|
780
780
|
|
|
781
781
|
<div class="ac-head">
|
|
782
782
|
<div>
|
|
783
783
|
<div class="ac-kicker">Operations</div>
|
|
784
784
|
<h1>What ran, where, and what it decided</h1>
|
|
785
|
-
<p class="ac-sub" id="sub">${
|
|
785
|
+
<p class="ac-sub" id="sub">${ir[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",de.timeline],["map","Map",de.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${
|
|
789
|
+
${[["timeline","Timeline",de.timeline],["map","Map",de.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${yt(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":""}>${yt(de.refresh,13)} Refresh</button>
|
|
795
795
|
</div>
|
|
796
796
|
</div>
|
|
797
797
|
|
|
@@ -799,14 +799,14 @@ refresh();
|
|
|
799
799
|
<div class="ac-bar">
|
|
800
800
|
<span class="ac-lbl">Lanes by</span>
|
|
801
801
|
<div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
|
|
802
|
-
${
|
|
802
|
+
${Wi.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${yt(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">${yt(de.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="${bt("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Gi,scripts:`<script>${z({computeBands:Zt,packTracks:ea,buildTimeline:or})}const ICON = ${JSON.stringify(de)};const SUB = ${JSON.stringify(ir)};${Xi}</script>`})}var Gi=`
|
|
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
|
+
`,Xi=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>';
|
|
@@ -1022,7 +1022,7 @@ history.replaceState(null,'',u);
|
|
|
1022
1022
|
if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
|
|
1023
1023
|
$('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
|
|
1024
1024
|
show(view);
|
|
1025
|
-
`;function
|
|
1025
|
+
`;function cr(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return L({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ki,scripts:`<script src="${bt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Ki=`
|
|
1026
1026
|
/* Preload the fonts the redesign's CSS references. Placed in the shell so
|
|
1027
1027
|
* they start fetching while the React bundle is still parsing. */
|
|
1028
1028
|
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
|
|
@@ -1043,10 +1043,260 @@ body { margin: 0; overflow: hidden; }
|
|
|
1043
1043
|
font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1044
1044
|
text-align: center;
|
|
1045
1045
|
}
|
|
1046
|
-
`;import{createServer as Vp}from"http";import{appendFileSync as Yp,existsSync as ni,mkdirSync as Qp}from"fs";import{readFile as Zp}from"fs/promises";import{fileURLToPath as eu}from"url";import{dirname as tu,resolve as Je}from"path";hi();ui();var Yn='/*! 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 gt,readFileSync as or,writeFileSync as sr,rmSync as im,mkdirSync as $i,copyFileSync as Pi,readdirSync as ji}from"fs";import{resolve as $e}from"path";mi();function Zn(t){let e=Ye.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:Ye.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=Ye.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 Qn=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function er(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 tr(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:Qn(t?.chats),senders:Qn(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 ar(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 nr(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}"`})}Nt();var pe={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function rr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ct({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.`})+dt([{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 R({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ii()+An,css:Ri,scripts:`${e}<script>${Cn}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1046
|
+
`;import{createServer as Su}from"http";import{appendFileSync as Tu,existsSync as _i,mkdirSync as Au}from"fs";import{readFile as Cu}from"fs/promises";import{fileURLToPath as Iu}from"url";import{dirname as Mu,resolve as Ye}from"path";Oi();function Pe(t,e){if(!t)return"absent";let a=dn(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ee=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function wt(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=dr(t.headers["sec-fetch-mode"]),n.site=dr(t.headers["sec-fetch-site"]),n}function dr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Ji}from"zlib";var Vi=[41,121,255],Yi=[255,255,255],pr=new Map;function je(t){let e=pr.get(t);return e||(e=Zi(t,Qi(t)),pr.set(t,e)),e}function Qi(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?Yi:Vi;a.set(c,o*e+1+s*3)}return a}function Zi(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]),ta("IHDR",a),ta("IDAT",Ji(e)),ta("IEND",Buffer.alloc(0))])}function ta(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(tl(n)),Buffer.concat([a,n,r])}var el=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 tl(t){let e=4294967295;for(let a of t)e=el[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}ji();var al=7,nl={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function rl(t,e){let a=t.toLowerCase().split("@")[0],n=nl[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 ur(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 mr(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(p=>p.name==="person"),i=p=>({id:p.id,state:p.state,agentId:p.agent_id,text:p.text,channel:p.channel,chatId:p.chat_id,createdAt:p.created_at,updatedAt:p.updated_at,closedAt:p.closed_at??null,question:p.question??null,attentionReason:p.attention_reason??null,evidence:p.evidence??null,where:{label:rl(p.channel,p.chat_id),url:a.linkFor?.(p.channel,p.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Ft.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...Ft).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Ut.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1047
|
+
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...Ut,n-al*864e5).map(i):[],u=[];try{u=Wn(t,e,10)}catch{}return{open:l,recent:c,runs:u}}function fr(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function hr(t,e){return!t||e-t>=3e4||t>e}function kt(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 gr(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}var ol="<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 aa(t){return`<meta charset="utf-8">
|
|
1048
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1049
|
+
<meta name="theme-color" content="#2979FF">
|
|
1050
|
+
<meta name="referrer" content="no-referrer">
|
|
1051
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
1052
|
+
<meta name="apple-mobile-web-app-title" content="My work">
|
|
1053
|
+
<link rel="manifest" href="/member/manifest.webmanifest">
|
|
1054
|
+
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1055
|
+
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1056
|
+
<title>${t}</title>
|
|
1057
|
+
${ol}
|
|
1058
|
+
<style>${pt}${ll}</style>`}function xr(){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 vr=`
|
|
1059
|
+
var CACHE = 'agentx-member-v1';
|
|
1060
|
+
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
1061
|
+
self.addEventListener('install', function (e) {
|
|
1062
|
+
e.waitUntil(caches.open(CACHE).then(function (c) { return c.addAll(STATIC); }).then(function () { return self.skipWaiting(); }));
|
|
1063
|
+
});
|
|
1064
|
+
self.addEventListener('activate', function (e) {
|
|
1065
|
+
e.waitUntil(caches.keys().then(function (keys) {
|
|
1066
|
+
return Promise.all(keys.filter(function (k) { return k !== CACHE; }).map(function (k) { return caches.delete(k); }));
|
|
1067
|
+
}).then(function () { return self.clients.claim(); }));
|
|
1068
|
+
});
|
|
1069
|
+
self.addEventListener('fetch', function (e) {
|
|
1070
|
+
var req = e.request;
|
|
1071
|
+
var url = new URL(req.url);
|
|
1072
|
+
if (req.method !== 'GET' || url.origin !== self.location.origin) return;
|
|
1073
|
+
if (url.pathname.indexOf('/api/') === 0) return;
|
|
1074
|
+
if (req.mode === 'navigate' && url.pathname === '/member') {
|
|
1075
|
+
e.respondWith(fetch(req).then(function (res) {
|
|
1076
|
+
if (res.status === 200) { e.waitUntil(caches.open(CACHE).then(function (c) { return c.put('/member', res.clone()); })); }
|
|
1077
|
+
if (res.status === 401) { e.waitUntil(caches.open(CACHE).then(function (c) { return c.delete('/member'); })); }
|
|
1078
|
+
return res;
|
|
1079
|
+
}).catch(function () {
|
|
1080
|
+
return caches.match('/member').then(function (hit) { return hit || Response.error(); });
|
|
1081
|
+
}));
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
if (STATIC.indexOf(url.pathname) >= 0) {
|
|
1085
|
+
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
`;function br(){return`<!doctype html>
|
|
1089
|
+
<html lang="en">
|
|
1090
|
+
<head>${aa("My work \xB7 AgentX")}<style>${cl}</style></head>
|
|
1091
|
+
<body>
|
|
1092
|
+
<header class="bar">
|
|
1093
|
+
<div><h1>My work</h1><p id="who" class="who">Connecting\u2026</p></div>
|
|
1094
|
+
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>
|
|
1095
|
+
</header>
|
|
1096
|
+
<p id="offline" class="offline" role="status" hidden>Offline. Showing what was last loaded; live state needs a connection.</p>
|
|
1097
|
+
<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>
|
|
1098
|
+
<main>
|
|
1099
|
+
<section aria-labelledby="h-open"><h2 id="h-open">Open <span id="n-open" class="count"></span></h2><ul id="open" class="list"><li class="muted">Loading\u2026</li></ul></section>
|
|
1100
|
+
<section aria-labelledby="h-recent"><h2 id="h-recent">Finished in the last 7 days</h2><ul id="recent" class="list"><li class="muted">Loading\u2026</li></ul></section>
|
|
1101
|
+
<section aria-labelledby="h-runs"><h2 id="h-runs">Latest turns</h2><ul id="runs" class="list"><li class="muted">Loading\u2026</li></ul></section>
|
|
1102
|
+
<p id="updated" class="muted small"></p>
|
|
1103
|
+
</main>
|
|
1104
|
+
<script>${z({workState:sl,ageText:il})}${ml}</script>
|
|
1105
|
+
</body>
|
|
1106
|
+
</html>`}function yr(){return`<!doctype html>
|
|
1107
|
+
<html lang="en">
|
|
1108
|
+
<head>${aa("Pair this machine \xB7 AgentX")}<style>${dl}</style></head>
|
|
1109
|
+
<body>
|
|
1110
|
+
<main class="card">
|
|
1111
|
+
<h1>Pair this machine</h1>
|
|
1112
|
+
<p>The owner sent you a pairing code. Type it below with a name for this machine. The owner then approves the machine, and your work page opens.</p>
|
|
1113
|
+
<form id="pair-form" class="pair-form" novalidate>
|
|
1114
|
+
<label for="machine">This machine's name</label>
|
|
1115
|
+
<input id="machine" name="machine" type="text" maxlength="60" placeholder="Work laptop" autocomplete="off" required>
|
|
1116
|
+
<label for="pair-code">Pairing code</label>
|
|
1117
|
+
<input id="pair-code" name="code" type="text" placeholder="XXXX-XXXX" maxlength="9"
|
|
1118
|
+
autocomplete="one-time-code" inputmode="text" autocapitalize="characters" autocorrect="off" spellcheck="false" enterkeyhint="go" required>
|
|
1119
|
+
<button type="submit" id="pair-btn">Pair</button>
|
|
1120
|
+
<p id="pair-offline" class="pair-offline" role="status" hidden>You're offline. Pairing needs a connection to the private network.</p>
|
|
1121
|
+
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
1122
|
+
</form>
|
|
1123
|
+
<p class="muted">No code? Ask the owner to run <code>agentx people invite <you></code>. A code works once, for 10 minutes.</p>
|
|
1124
|
+
</main>
|
|
1125
|
+
<script>${z({formatPairInput:kt})}${pl}</script>
|
|
1126
|
+
</body>
|
|
1127
|
+
</html>`}function wr(){return`<!doctype html>
|
|
1128
|
+
<html lang="en">
|
|
1129
|
+
<head>${aa("Waiting for the owner \xB7 AgentX")}</head>
|
|
1130
|
+
<body>
|
|
1131
|
+
<main class="card">
|
|
1132
|
+
<h1>Waiting for the owner</h1>
|
|
1133
|
+
<p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens by itself when they do.</p>
|
|
1134
|
+
<p class="muted">If they said no, this page will ask for a new code.</p>
|
|
1135
|
+
</main>
|
|
1136
|
+
<script>${ul}</script>
|
|
1137
|
+
</body>
|
|
1138
|
+
</html>`}function sl(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 il(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 ll=`
|
|
1139
|
+
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
1140
|
+
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
1141
|
+
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
1142
|
+
.card { max-width: 460px; margin: 0 auto; padding: 40px 24px; line-height: 1.55; }
|
|
1143
|
+
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
1144
|
+
.muted { color: var(--ax-text-2); }
|
|
1145
|
+
.small { font-size: var(--ax-fs-xs); }
|
|
1146
|
+
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
1147
|
+
`,cl=`
|
|
1148
|
+
body { display: flex; flex-direction: column; }
|
|
1149
|
+
.bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; background: var(--ax-surface); border-bottom: var(--ax-border-w) solid var(--ax-border); }
|
|
1150
|
+
.bar h1 { font-size: 18px; margin: 0; font-weight: 700; }
|
|
1151
|
+
.who { margin: 2px 0 0; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
1152
|
+
.icon-btn { min-width: 44px; min-height: 44px; font-size: 20px; line-height: 1; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-pill); background: var(--ax-surface-2); color: var(--ax-text); cursor: pointer; }
|
|
1153
|
+
.offline, .install { margin: 0; padding: 8px 16px; font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border-bottom: 1px solid var(--ax-amber-e); }
|
|
1154
|
+
.install { background: var(--ax-surface-2); color: var(--ax-text-2); border-bottom: var(--ax-border-w) solid var(--ax-border); }
|
|
1155
|
+
main { flex: 1; overflow-y: auto; padding: 16px; max-width: 720px; width: 100%; box-sizing: border-box; margin: 0 auto; }
|
|
1156
|
+
main h2 { font-size: 16px; margin: 12px 0 8px; }
|
|
1157
|
+
.count { color: var(--ax-text-2); font-weight: 400; }
|
|
1158
|
+
.list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
|
|
1159
|
+
.item { padding: 10px 12px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm); background: var(--ax-surface); }
|
|
1160
|
+
.item .text { margin: 0 0 4px; line-height: 1.4; }
|
|
1161
|
+
.item .meta { margin: 0; font-size: var(--ax-fs-xs); color: var(--ax-text-2); display: flex; flex-wrap: wrap; gap: 4px 10px; }
|
|
1162
|
+
.item .note { margin: 6px 0 0; font-size: var(--ax-fs-sm); }
|
|
1163
|
+
.state { font-weight: 600; }
|
|
1164
|
+
.state.ok { color: var(--ax-green-ink, var(--ax-text)); }
|
|
1165
|
+
.state.warn { color: var(--ax-amber-ink); }
|
|
1166
|
+
.state.bad { color: var(--ax-red-ink); }
|
|
1167
|
+
[data-theme="dark"] .state.bad { color: var(--ax-red); }
|
|
1168
|
+
.state.muted { color: var(--ax-text-2); }
|
|
1169
|
+
a { color: var(--ax-accent); }
|
|
1170
|
+
`,dl=`
|
|
1171
|
+
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
1172
|
+
.pair-form label { font-weight: 600; }
|
|
1173
|
+
.pair-form input { box-sizing: border-box; width: 100%; min-height: 48px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: 2px solid var(--ax-border); border-radius: var(--ax-radius-sm); }
|
|
1174
|
+
.pair-form input#pair-code { min-height: 60px; font: 600 26px/1.2 var(--ax-mono); letter-spacing: 0.12em; text-align: center; text-transform: uppercase; }
|
|
1175
|
+
.pair-form input:focus { border-color: var(--ax-accent); outline: none; }
|
|
1176
|
+
.pair-form button { min-height: 52px; border: 0; border-radius: var(--ax-radius-pill); font: inherit; font-size: 17px; font-weight: 700; color: #fff; background: var(--ax-accent); cursor: pointer; }
|
|
1177
|
+
.pair-form button:disabled { opacity: 0.55; cursor: default; }
|
|
1178
|
+
.pair-msg { margin: 0; min-height: 1.5em; }
|
|
1179
|
+
.pair-msg.bad { color: var(--ax-red-ink); }
|
|
1180
|
+
[data-theme="dark"] .pair-msg.bad { color: var(--ax-red); }
|
|
1181
|
+
.pair-offline { margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
|
|
1182
|
+
`,pl=`
|
|
1183
|
+
(function () {
|
|
1184
|
+
var form = document.getElementById('pair-form');
|
|
1185
|
+
var machine = document.getElementById('machine');
|
|
1186
|
+
var input = document.getElementById('pair-code');
|
|
1187
|
+
var btn = document.getElementById('pair-btn');
|
|
1188
|
+
var msg = document.getElementById('pair-msg');
|
|
1189
|
+
var offline = document.getElementById('pair-offline');
|
|
1190
|
+
var busy = false;
|
|
1191
|
+
function setOnline(on) { offline.hidden = on; btn.disabled = busy || !on; }
|
|
1192
|
+
function say(text, bad) { msg.textContent = text; msg.className = bad ? 'pair-msg bad' : 'pair-msg'; }
|
|
1193
|
+
setOnline(navigator.onLine !== false);
|
|
1194
|
+
window.addEventListener('online', function () { setOnline(true); });
|
|
1195
|
+
window.addEventListener('offline', function () { setOnline(false); });
|
|
1196
|
+
input.addEventListener('input', function () {
|
|
1197
|
+
var f = formatPairInput(input.value, input.selectionStart == null ? input.value.length : input.selectionStart);
|
|
1198
|
+
if (f.value !== input.value) {
|
|
1199
|
+
input.value = f.value;
|
|
1200
|
+
try { if (document.activeElement === input) input.setSelectionRange(f.caret, f.caret); } catch (x) {}
|
|
1201
|
+
}
|
|
1202
|
+
if (msg.className.indexOf('bad') >= 0) say('', false);
|
|
1203
|
+
});
|
|
1204
|
+
form.addEventListener('submit', function (ev) {
|
|
1205
|
+
ev.preventDefault();
|
|
1206
|
+
if (busy) return;
|
|
1207
|
+
var code = input.value.replace(/[^A-Z0-9]/g, '');
|
|
1208
|
+
var name = machine.value.replace(/\\s+/g, ' ').trim();
|
|
1209
|
+
if (!name) { say('Give this machine a name.', true); machine.focus(); return; }
|
|
1210
|
+
if (code.length !== 8) { say('The code has 8 letters and digits.', true); input.focus(); return; }
|
|
1211
|
+
busy = true; btn.disabled = true; say('Pairing\u2026', false);
|
|
1212
|
+
fetch('/api/member/pair-code', {
|
|
1213
|
+
method: 'POST', credentials: 'same-origin', cache: 'no-store',
|
|
1214
|
+
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'fetch' },
|
|
1215
|
+
body: JSON.stringify({ code: code, machine: name })
|
|
1216
|
+
}).then(function (r) {
|
|
1217
|
+
return r.json().catch(function () { return {}; }).then(function (j) { return { status: r.status, body: j }; });
|
|
1218
|
+
}).then(function (r) {
|
|
1219
|
+
if (r.status === 200) { say('Paired. Waiting for the owner\u2026', false); location.replace('/member'); return; }
|
|
1220
|
+
busy = false; btn.disabled = false;
|
|
1221
|
+
if (r.status === 429) { say('Too many attempts. Wait ' + Math.ceil((r.body.retryAfter || 300) / 60) + ' minutes, then try again.', true); return; }
|
|
1222
|
+
say(r.body.error || 'That code did not work.', true);
|
|
1223
|
+
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1224
|
+
});
|
|
1225
|
+
})();
|
|
1226
|
+
`,ul=`
|
|
1227
|
+
(function () {
|
|
1228
|
+
var msg = document.getElementById('msg');
|
|
1229
|
+
function check() {
|
|
1230
|
+
fetch('/api/member/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) {
|
|
1231
|
+
if (r.status === 200) { location.replace('/member'); return; }
|
|
1232
|
+
if (r.status === 401) { msg.textContent = 'The owner did not approve this machine. Ask them for a new code.'; setTimeout(function () { location.replace('/member'); }, 4000); return; }
|
|
1233
|
+
}).catch(function () {});
|
|
1234
|
+
}
|
|
1235
|
+
setInterval(check, 5000);
|
|
1236
|
+
})();
|
|
1237
|
+
`,ml=`
|
|
1238
|
+
(function () {
|
|
1239
|
+
var who = document.getElementById('who');
|
|
1240
|
+
var offline = document.getElementById('offline');
|
|
1241
|
+
var install = document.getElementById('install');
|
|
1242
|
+
var updated = document.getElementById('updated');
|
|
1243
|
+
var theme = document.getElementById('theme');
|
|
1244
|
+
theme.addEventListener('click', function () {
|
|
1245
|
+
var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
1246
|
+
document.documentElement.setAttribute('data-theme', cur);
|
|
1247
|
+
try { localStorage.setItem('ax-theme', cur); } catch (e) {}
|
|
1248
|
+
});
|
|
1249
|
+
if ('serviceWorker' in navigator) { try { navigator.serviceWorker.register('/member/sw.js', { scope: '/member' }); } catch (e) {} }
|
|
1250
|
+
var standalone = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
|
|
1251
|
+
if (!standalone && /Windows|Macintosh|Linux/.test(navigator.userAgent) && !/Mobile/.test(navigator.userAgent)) install.hidden = false;
|
|
1252
|
+
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }
|
|
1253
|
+
function setOnline(on) { offline.hidden = on; }
|
|
1254
|
+
window.addEventListener('online', function () { setOnline(true); load(); });
|
|
1255
|
+
window.addEventListener('offline', function () { setOnline(false); });
|
|
1256
|
+
function where(r) {
|
|
1257
|
+
var label = esc(r.where && r.where.label || r.channel);
|
|
1258
|
+
return r.where && r.where.url ? '<a href="' + esc(r.where.url) + '" target="_blank" rel="noopener noreferrer">' + label + '</a>' : label;
|
|
1259
|
+
}
|
|
1260
|
+
function item(r, now, closed) {
|
|
1261
|
+
var st = workState(r.state);
|
|
1262
|
+
var note = '';
|
|
1263
|
+
if (r.state === 'waiting_owner' && r.question) note = '<p class="note"><b>The owner is asked:</b> ' + esc(r.question) + '</p>';
|
|
1264
|
+
else if (r.state === 'needs_attention' && r.attentionReason) note = '<p class="note">' + esc(r.attentionReason) + '</p>';
|
|
1265
|
+
else if (closed && r.evidence) note = '<p class="note"><a href="' + esc(r.evidence) + '" target="_blank" rel="noopener noreferrer">What was delivered</a></p>';
|
|
1266
|
+
var age = closed ? 'closed ' + ageText(r.closedAt || r.updatedAt, now) + ' ago' : 'for ' + ageText(r.createdAt, now);
|
|
1267
|
+
return '<li class="item"><p class="text">' + esc(r.text) + '</p>' +
|
|
1268
|
+
'<p class="meta"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span>' + esc(r.agentId) + '</span><span>' + age + '</span><span>asked on ' + where(r) + '</span></p>' + note + '</li>';
|
|
1269
|
+
}
|
|
1270
|
+
function run(r, now) {
|
|
1271
|
+
var mark = r.status === 'ok' ? 'finished' : r.status === 'in-flight' ? 'running' : esc(r.status);
|
|
1272
|
+
return '<li class="item"><p class="text">' + esc(r.messagePreview || '') + '</p><p class="meta"><span class="state ' + (r.status === 'ok' ? 'ok' : r.status === 'in-flight' ? 'warn' : 'bad') + '">' + mark + '</span><span>' + esc(r.agentId) + '</span><span>' + ageText(r.startedAt, now) + ' ago</span><span>' + esc(r.channel || '') + '</span></p></li>';
|
|
1273
|
+
}
|
|
1274
|
+
function fill(id, html, empty) { document.getElementById(id).innerHTML = html || '<li class="muted">' + empty + '</li>'; }
|
|
1275
|
+
function load() {
|
|
1276
|
+
fetch('/api/member/work', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) {
|
|
1277
|
+
if (r.status === 401 || r.status === 403) { location.replace('/member'); return null; }
|
|
1278
|
+
return r.json();
|
|
1279
|
+
}).then(function (w) {
|
|
1280
|
+
if (!w) return;
|
|
1281
|
+
setOnline(true);
|
|
1282
|
+
var now = Date.now();
|
|
1283
|
+
document.getElementById('n-open').textContent = w.open.length ? '(' + w.open.length + ')' : '';
|
|
1284
|
+
fill('open', w.open.map(function (r) { return item(r, now, false); }).join(''), 'Nothing open. What you ask the agents for shows up here while it is being worked on.');
|
|
1285
|
+
fill('recent', w.recent.map(function (r) { return item(r, now, true); }).join(''), 'Nothing finished in the last 7 days.');
|
|
1286
|
+
fill('runs', w.runs.map(function (r) { return run(r, now); }).join(''), 'No turns recorded yet.');
|
|
1287
|
+
updated.textContent = 'Updated ' + new Date(now).toLocaleTimeString();
|
|
1288
|
+
}).catch(function () { setOnline(false); });
|
|
1289
|
+
}
|
|
1290
|
+
fetch('/api/member/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.ok ? r.json() : null; }).then(function (me) {
|
|
1291
|
+
if (me) who.textContent = me.name + ' \xB7 ' + me.device + (me.node ? ' \xB7 ' + me.node : '');
|
|
1292
|
+
}).catch(function () {});
|
|
1293
|
+
load();
|
|
1294
|
+
setInterval(load, 30000);
|
|
1295
|
+
})();
|
|
1296
|
+
`;var _t="agentx_member",fl=90*86400,hl=new xt,Er=t=>t.replace(/^\[app\]/,"[member]"),gl=new Ee(t=>console.log(Er(t))),kr=new WeakMap;function xl(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return gl;let e=kr.get(t.log);return e||kr.set(t.log,e=new Ee(a=>t.log(Er(a)))),e}async function Sr(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new W(r.root),s=r.members??new Gn(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ht(r.root),limiter:r.pairLimiter??hl,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return xe(e,200,"application/manifest+json",xr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),xe(e,200,"text/javascript; charset=utf-8",vr);if(a==="/member/icon-192.png")return xe(e,200,"image/png",je(192),"public, max-age=86400");if(a==="/member/icon-512.png")return xe(e,200,"image/png",je(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Jn(t,i);return p.status===200&&e.setHeader("Set-Cookie",_r(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Se(e,p.status,p.body)}let l=t.socket?.remoteAddress||void 0,c=Vn(vl(t),i,l);if(!c.ok){if(c.status===401){let p=na(t);return xl(r).record(a.slice(0,120),wt(t,Pe(ra(t,_t),o),p?Pe(p,o):null)),a==="/member"?xe(e,401,"text/html; charset=utf-8",yr()):Se(e,401,{error:c.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?xe(e,202,"text/html; charset=utf-8",wr()):Se(e,403,{error:c.error,waiting:!0})}let u=r.people().find(p=>p.id===c.personId);if(n==="GET"&&a==="/member"){let p=ra(t,_t);return p&&!na(t)&&e.setHeader("Set-Cookie",_r(p)),xe(e,200,"text/html; charset=utf-8",br())}if(n==="GET"&&a==="/api/member/me")return Se(e,200,{person:c.personId,name:u?.name??c.personId,device:c.device.name,since:c.device.approvedAt??c.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let p=r.db?.()??null;return p?Se(e,200,mr(p,c.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Se(e,503,{error:"the work list needs the database"})}return Se(e,404,{error:"not found"})}function _r(t){return`${_t}=${t}; Path=/; Max-Age=${fl}; HttpOnly; Secure; SameSite=Lax`}function vl(t){return na(t)??ra(t,_t)}function na(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ra(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function xe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Se(t,e,a){return xe(t,e,"application/json",JSON.stringify(a))}Ri();var Tr='/*! 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 St,readFileSync as Pr,writeFileSync as jr,rmSync as rf,mkdirSync as El,copyFileSync as Sl,readdirSync as Tl}from"fs";import{resolve as Oe}from"path";$i();function Cr(t){let e=Ze.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:Ze.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 Et(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=Ze.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 Ar=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Ir(t){return Et(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 Mr(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Et((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:Ar(t?.chats),senders:Ar(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 Lr(t){let e=String(t?.id??"");return Et(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 Rr(t){let e=String(t?.id??"");return Et(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}"`})}Wt();var pe={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function $r(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ut({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 L({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+yl()+jn,css:kl,scripts:`${e}<script>${On}
|
|
1297
|
+
${Nn}
|
|
1298
|
+
${bl}
|
|
1299
|
+
${_l}</script>`})}var bl=`
|
|
1050
1300
|
(function(){
|
|
1051
1301
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1052
1302
|
async function voiceMissing() {
|
|
@@ -1140,8 +1390,8 @@ ${Li}</script>`})}var Ci=`
|
|
|
1140
1390
|
refresh();
|
|
1141
1391
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1142
1392
|
document.addEventListener('ax-config-saved', refresh);
|
|
1143
|
-
})();`;function
|
|
1144
|
-
`:"";return
|
|
1393
|
+
})();`;function yl(){let t=yn().business?`<button data-tab="business">Business</button>
|
|
1394
|
+
`:"";return wl.replace("__BUSINESS_TABS__",t)}var wl=`
|
|
1145
1395
|
<div id="peer-banner" class="peer-banner">
|
|
1146
1396
|
<span class="label">Managing</span>
|
|
1147
1397
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -1284,7 +1534,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1284
1534
|
<div id="global-msg" class="msg"></div>
|
|
1285
1535
|
|
|
1286
1536
|
<section id="tab-agents" class="tab active">
|
|
1287
|
-
${
|
|
1537
|
+
${G({icon:pe.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
|
|
1288
1538
|
${re({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
|
|
1289
1539
|
<div id="agent-list" class="ax-stack"></div>
|
|
1290
1540
|
<div class="add-form">
|
|
@@ -1307,7 +1557,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1307
1557
|
</section>
|
|
1308
1558
|
|
|
1309
1559
|
<section id="tab-channels" class="tab">
|
|
1310
|
-
${
|
|
1560
|
+
${G({icon:pe.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
|
|
1311
1561
|
${re({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
|
|
1312
1562
|
|
|
1313
1563
|
<details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
|
|
@@ -1393,10 +1643,10 @@ ${Li}</script>`})}var Ci=`
|
|
|
1393
1643
|
</div>
|
|
1394
1644
|
</details>
|
|
1395
1645
|
|
|
1396
|
-
<div id="ch-chatapps-label">${
|
|
1646
|
+
<div id="ch-chatapps-label">${ft({label:"Chat apps"})}</div>
|
|
1397
1647
|
<div class="ax-connectors" id="ch-chatapps"></div>
|
|
1398
1648
|
|
|
1399
|
-
<div id="ch-devtools-label">${
|
|
1649
|
+
<div id="ch-devtools-label">${ft({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
|
|
1400
1650
|
<div class="ax-connectors" id="ch-devtools"></div>
|
|
1401
1651
|
|
|
1402
1652
|
<!-- Active-channel configuration panes. One shows at a time; clicking
|
|
@@ -1414,7 +1664,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1414
1664
|
</section>
|
|
1415
1665
|
|
|
1416
1666
|
<section id="tab-crons" class="tab">
|
|
1417
|
-
${
|
|
1667
|
+
${G({icon:pe.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
|
|
1418
1668
|
${re({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
|
|
1419
1669
|
<div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
|
|
1420
1670
|
|
|
@@ -1512,7 +1762,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1512
1762
|
</section>
|
|
1513
1763
|
|
|
1514
1764
|
<section id="tab-webhooks" class="tab">
|
|
1515
|
-
${
|
|
1765
|
+
${G({icon:pe.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
|
|
1516
1766
|
${re({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
|
|
1517
1767
|
<div id="webhook-list" class="ax-stack"></div>
|
|
1518
1768
|
<div class="add-form">
|
|
@@ -1554,10 +1804,10 @@ ${Li}</script>`})}var Ci=`
|
|
|
1554
1804
|
</section>
|
|
1555
1805
|
|
|
1556
1806
|
<section id="tab-mesh" class="tab">
|
|
1557
|
-
${
|
|
1807
|
+
${G({icon:pe.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
|
|
1558
1808
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
1559
1809
|
${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."})}
|
|
1560
|
-
${
|
|
1810
|
+
${ft({label:"Connected peers"})}
|
|
1561
1811
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
1562
1812
|
<div class="add-form">
|
|
1563
1813
|
<h3>Add a peer</h3>
|
|
@@ -1584,7 +1834,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1584
1834
|
</section>
|
|
1585
1835
|
|
|
1586
1836
|
<section id="tab-business" class="tab">
|
|
1587
|
-
${
|
|
1837
|
+
${G({icon:pe.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
|
|
1588
1838
|
${re({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
|
|
1589
1839
|
|
|
1590
1840
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -1672,7 +1922,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1672
1922
|
</section>
|
|
1673
1923
|
|
|
1674
1924
|
<section id="tab-boards-cfg" class="tab">
|
|
1675
|
-
${
|
|
1925
|
+
${G({icon:pe.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
|
|
1676
1926
|
${re({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
|
|
1677
1927
|
|
|
1678
1928
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -1697,7 +1947,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1697
1947
|
</section>
|
|
1698
1948
|
|
|
1699
1949
|
<section id="tab-actions" class="tab">
|
|
1700
|
-
${
|
|
1950
|
+
${G({icon:pe.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
|
|
1701
1951
|
${re({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
|
|
1702
1952
|
|
|
1703
1953
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -1753,7 +2003,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1753
2003
|
</section>
|
|
1754
2004
|
|
|
1755
2005
|
<section id="tab-tokens" class="tab">
|
|
1756
|
-
${
|
|
2006
|
+
${G({icon:pe.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
|
|
1757
2007
|
${re({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
|
|
1758
2008
|
<div id="token-list" class="ax-stack"></div>
|
|
1759
2009
|
<div class="add-form">
|
|
@@ -1773,7 +2023,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1773
2023
|
</section>
|
|
1774
2024
|
|
|
1775
2025
|
<section id="tab-advanced" class="tab">
|
|
1776
|
-
${
|
|
2026
|
+
${G({icon:pe.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
|
|
1777
2027
|
${re({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
|
|
1778
2028
|
|
|
1779
2029
|
<div class="ax-jv-toolbar">
|
|
@@ -1800,7 +2050,7 @@ ${Li}</script>`})}var Ci=`
|
|
|
1800
2050
|
<div class="hint-block">Every setting is documented in the <code>docs/reference/config.md</code> reference. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
|
|
1801
2051
|
</section>
|
|
1802
2052
|
</main>
|
|
1803
|
-
`,
|
|
2053
|
+
`,kl=`
|
|
1804
2054
|
|
|
1805
2055
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
1806
2056
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2008,7 +2258,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2008
2258
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2009
2259
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2010
2260
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2011
|
-
`,
|
|
2261
|
+
`,_l=`
|
|
2012
2262
|
const $ = (id) => document.getElementById(id);
|
|
2013
2263
|
let state = null;
|
|
2014
2264
|
|
|
@@ -4892,11 +5142,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
4892
5142
|
})();
|
|
4893
5143
|
|
|
4894
5144
|
refresh();
|
|
4895
|
-
`;function ir(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rr({peers:a,localToken:n}))}async function lr(t,e){let a=Jt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function cr(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ji(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Oi(t),r={"GET /api/admin/state":()=>Di(),"POST /api/admin/agents":()=>Ui(n),"PATCH /api/admin/agents":()=>Wi(n),"DELETE /api/admin/agents":()=>Gi(n),"POST /api/admin/agents/access":()=>Hi(n),"POST /api/admin/channels/telegram":()=>Xi(n),"DELETE /api/admin/channels/telegram":()=>xl(n),"POST /api/admin/channels/telegram/toggle":()=>vl(n),"POST /api/admin/crons":()=>bl(n),"DELETE /api/admin/crons":()=>yl(n),"POST /api/admin/config/raw":()=>wl(n),"GET /api/admin/tokens":()=>Bi(),"POST /api/admin/tokens":()=>zi(n),"DELETE /api/admin/tokens":()=>qi(n),"POST /api/admin/agents/test":()=>Fi(n),"POST /api/admin/agents/integrations":()=>tl(n),"DELETE /api/admin/agents/integrations":()=>al(n),"PATCH /api/admin/agents/integrations":()=>nl(n),"PATCH /api/admin/channels/telegram":()=>Ki(n),"POST /api/admin/channels/slack":()=>dl(n),"POST /api/admin/channels/slack/toggle":()=>pl(n),"POST /api/admin/channels/discord":()=>ul(n),"POST /api/admin/channels/discord/toggle":()=>ml(n),"POST /api/admin/channels/gitlab":()=>fl(n),"POST /api/admin/channels/gitlab/toggle":()=>hl(n),"POST /api/admin/channels/request-status":()=>Hn(n),"GET /api/admin/channels/whatsapp/state":()=>Be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Be("/webrtc/history"),"POST /api/admin/actions":()=>Pl(n),"DELETE /api/admin/actions":()=>jl(n),"POST /api/admin/actions/run":()=>Ol(n),"GET /api/admin/channels/whatsapp/chats":()=>Be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>gl(n),"POST /api/admin/webhooks":()=>rl(n),"PATCH /api/admin/webhooks":()=>ol(n),"DELETE /api/admin/webhooks":()=>cl(n),"POST /api/admin/whatsapp-triage":()=>er(n),"POST /api/admin/whatsapp-triage/rules":()=>tr(n),"PATCH /api/admin/whatsapp-triage/rules":()=>ar(n),"DELETE /api/admin/whatsapp-triage/rules":()=>nr(n),"POST /api/admin/mesh/peers":()=>sl(n),"DELETE /api/admin/mesh/peers":()=>il(n),"POST /api/admin/mesh/toggle":()=>ll(n),"GET /api/admin/files":()=>Vi(t),"GET /api/admin/files/read":()=>Yi(t),"PUT /api/admin/files":()=>Qi(n),"POST /api/admin/files/skill":()=>Zi(n),"DELETE /api/admin/files/skill":()=>el(n),"POST /api/admin/business/orgchart":()=>kl(n),"DELETE /api/admin/business/orgchart":()=>_l(n),"POST /api/admin/business/project":()=>Sl(n),"DELETE /api/admin/business/project":()=>Al(n),"POST /api/admin/business/client":()=>El(n),"DELETE /api/admin/business/client":()=>Tl(n),"POST /api/admin/business/contact":()=>Cl(n),"DELETE /api/admin/business/contact":()=>Il(n),"POST /api/admin/boards":()=>Ml(n),"DELETE /api/admin/boards":()=>Rl(n),"POST /api/admin/boards/columns":()=>Ll(n),"DELETE /api/admin/boards/columns":()=>$l(n),"POST /api/admin/notifications":()=>Dl(n),"POST /api/admin/screen":()=>Hl(n),"POST /api/admin/webhooks/triggers":()=>Bl(n),"POST /api/admin/mesh/health":()=>Nl(n),"GET /api/admin/projects":()=>Be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Xt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Xt(e,200,i)}catch(n){Xt(e,400,{error:n.message||"admin op failed"})}}function Xt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Oi(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 Ni(t){let e=$e(process.cwd(),t);if(!gt(e))return[];let a=[];for(let n of ji(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(or($e(e,n.name),"utf-8")))}catch{}return a}function Jt(){let t=$e(process.cwd(),"agentx.json");return gt(t)?JSON.parse(or(t,"utf-8")):null}function Di(){let t=Jt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,f])=>({id:d,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let v=x.credentials||{},k={};for(let[b,S]of Object.entries(v))typeof S=="string"&&/^[A-Z][A-Z0-9_]*$/.test(S)?k[b]=process.env[S]?"set":"unset":typeof S=="string"&&(k[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:k,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,f])=>({id:d,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,f])=>({id:d,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},w=t.notifications||{},_={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:Qa(w.local),ntfy:zn(t.channels?.ntfy)},E=[];try{E=Ni(".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:Dn(t),whatsappTriage:Zn(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:wn(t.screen),actions:E}}function Hi(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 Bi(){return new ne().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 zi(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 ne().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function qi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ne().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Fi(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=ae();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 Ui(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=pr(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=$e(process.cwd(),"agents",e),{summary:l}=A(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),c=$e(i,"CLAUDE.md");if(!gt(c))try{$i(i,{recursive:!0}),sr(c,`# ${a}
|
|
5145
|
+
`;function Or(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({peers:a,localToken:n}))}async function Nr(t,e){let a=ia();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Dr(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Bl(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Al(t),r={"GET /api/admin/state":()=>Il(),"POST /api/admin/agents":()=>jl(n),"PATCH /api/admin/agents":()=>Ol(n),"DELETE /api/admin/agents":()=>Nl(n),"POST /api/admin/agents/access":()=>Ml(n),"POST /api/admin/channels/telegram":()=>Dl(n),"DELETE /api/admin/channels/telegram":()=>lc(n),"POST /api/admin/channels/telegram/toggle":()=>cc(n),"POST /api/admin/crons":()=>dc(n),"DELETE /api/admin/crons":()=>pc(n),"POST /api/admin/config/raw":()=>uc(n),"GET /api/admin/tokens":()=>Ll(),"POST /api/admin/tokens":()=>Rl(n),"DELETE /api/admin/tokens":()=>$l(n),"POST /api/admin/agents/test":()=>Pl(n),"POST /api/admin/agents/integrations":()=>Gl(n),"DELETE /api/admin/agents/integrations":()=>Xl(n),"PATCH /api/admin/agents/integrations":()=>Kl(n),"PATCH /api/admin/channels/telegram":()=>Hl(n),"POST /api/admin/channels/slack":()=>tc(n),"POST /api/admin/channels/slack/toggle":()=>ac(n),"POST /api/admin/channels/discord":()=>nc(n),"POST /api/admin/channels/discord/toggle":()=>rc(n),"POST /api/admin/channels/gitlab":()=>oc(n),"POST /api/admin/channels/gitlab/toggle":()=>sc(n),"POST /api/admin/channels/request-status":()=>Qn(n),"GET /api/admin/channels/whatsapp/state":()=>Fe("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Fe("/webrtc/history"),"POST /api/admin/actions":()=>Sc(n),"DELETE /api/admin/actions":()=>Tc(n),"POST /api/admin/actions/run":()=>Ac(n),"GET /api/admin/channels/whatsapp/chats":()=>Fe("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Fe("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ue("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ic(n),"POST /api/admin/webhooks":()=>Jl(n),"PATCH /api/admin/webhooks":()=>Vl(n),"DELETE /api/admin/webhooks":()=>ec(n),"POST /api/admin/whatsapp-triage":()=>Ir(n),"POST /api/admin/whatsapp-triage/rules":()=>Mr(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Lr(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Rr(n),"POST /api/admin/mesh/peers":()=>Yl(n),"DELETE /api/admin/mesh/peers":()=>Ql(n),"POST /api/admin/mesh/toggle":()=>Zl(n),"GET /api/admin/files":()=>zl(t),"GET /api/admin/files/read":()=>ql(t),"PUT /api/admin/files":()=>Fl(n),"POST /api/admin/files/skill":()=>Ul(n),"DELETE /api/admin/files/skill":()=>Wl(n),"POST /api/admin/business/orgchart":()=>mc(n),"DELETE /api/admin/business/orgchart":()=>fc(n),"POST /api/admin/business/project":()=>hc(n),"DELETE /api/admin/business/project":()=>vc(n),"POST /api/admin/business/client":()=>gc(n),"DELETE /api/admin/business/client":()=>xc(n),"POST /api/admin/business/contact":()=>bc(n),"DELETE /api/admin/business/contact":()=>yc(n),"POST /api/admin/boards":()=>wc(n),"DELETE /api/admin/boards":()=>kc(n),"POST /api/admin/boards/columns":()=>_c(n),"DELETE /api/admin/boards/columns":()=>Ec(n),"POST /api/admin/notifications":()=>Ic(n),"POST /api/admin/screen":()=>Mc(n),"POST /api/admin/webhooks/triggers":()=>Lc(n),"POST /api/admin/mesh/health":()=>Cc(n),"GET /api/admin/projects":()=>Fe("/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){oa(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();oa(e,200,i)}catch(n){oa(e,400,{error:n.message||"admin op failed"})}}function oa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Al(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 Cl(t){let e=Oe(process.cwd(),t);if(!St(e))return[];let a=[];for(let n of Tl(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Pr(Oe(e,n.name),"utf-8")))}catch{}return a}function ia(){let t=Oe(process.cwd(),"agentx.json");return St(t)?JSON.parse(Pr(t,"utf-8")):null}function Il(){let t=ia();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[b,_]of Object.entries(v))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?w[b]=process.env[_]?"set":"unset":typeof _=="string"&&(w[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],u={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}},p=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},E={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:ln(k.local),ntfy:er(t.channels?.ntfy)},S=[];try{S=Cl(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Yn(t),whatsappTriage:Cr(t),crons:l,webhooks:c,mesh:u,daemonUrl:p,nodeName:t.node?.name,business:h,boards:g,notifications:E,screen:Mn(t.screen),actions:S}}function Ml(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 Ll(){return new W().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 Rl(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 W().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function $l(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new W().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Pl(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 u=ne();r=u.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=u.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 jl(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=Br(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=Oe(process.cwd(),"agents",e),{summary:l}=A(u=>{if(u.agents=u.agents||{},u.agents[e])throw new Error(`Agent "${e}" already exists.`);let p={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(p.model=o),s&&(p.systemPrompt=s.slice(0,400)),u.agents[e]=p,`added agent "${e}"`}),c=Oe(i,"CLAUDE.md");if(!St(c))try{El(i,{recursive:!0}),jr(c,`# ${a}
|
|
4896
5146
|
|
|
4897
5147
|
${s||"You are "+a+"."}
|
|
4898
|
-
`)}catch{}return{summary:l}}function Wi(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=pr(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 Gi(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 Xi(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 Ki(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Be(t){let{url:e,headers:a}=Vt(),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}=Vt(),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 Ji(t,e){try{let{url:a,headers:n}=Vt(),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 Vt(){let t="http://127.0.0.1:18800",e={};try{let a=ae();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=Jt()?.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 Kt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Vi(t){let e=Kt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Le(ze(e));return{agentId:e,...a}}function Yi(t){let e=Kt(t,"agent").trim(),a=Kt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return rt(ze(e),a)}function Qi(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=ot(ze(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Zi(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(ze(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function el(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=it(ze(e),a);return{summary:`removed skill "${a}"`,...n}}function tl(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 al(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 nl(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 dr=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function rl(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(!dr.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 ol(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"&&dr.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 sl(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 il(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 ll(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 cl(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 dl(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 pl(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 ul(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 ml(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 fl(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 hl(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 gl(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-ITOKSMYT.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 xl(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 vl(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 bl(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 yl(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 wl(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=$e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(gt(n))try{Pi(n,r)}catch{}sr(n,JSON.stringify(a,null,2)+`
|
|
4899
|
-
`,"utf-8");try{let s=ae().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 pr(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function kl(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 _l(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 Sl(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 El(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 Tl(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 Al(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 Cl(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 Il(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 Ml(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 Rl(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 Ll(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 $l(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 Pl(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 jl(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 Ol(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 Nl(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 Dl(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=Za(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=qn(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 Hl(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=kn(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Bl(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}}Nt();import{resolve as Fl}from"path";function ur(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5148
|
+
`)}catch{}return{summary:l}}function Ol(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=Br(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 Nl(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 Dl(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 Hl(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 Fe(t){let{url:e,headers:a}=la(),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}=la(),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 Bl(t,e){try{let{url:a,headers:n}=la(),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 la(){let t="http://127.0.0.1:18800",e={};try{let a=ne();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ue(t){let a=ia()?.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 sa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function zl(t){let e=sa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=$e(Ue(e));return{agentId:e,...a}}function ql(t){let e=sa(t,"agent").trim(),a=sa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return st(Ue(e),a)}function Fl(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=it(Ue(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Ul(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=lt(Ue(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Wl(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(Ue(e),a);return{summary:`removed skill "${a}"`,...n}}function Gl(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 Xl(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 Kl(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(u=>u.kind===a&&u.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 Hr=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Jl(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(!Hr.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(p=>p.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(u=>u.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 Vl(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"&&Hr.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 Yl(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 Ql(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 Zl(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 ec(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 tc(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 ac(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 nc(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 rc(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 oc(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 sc(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 ic(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-JTPIGC5K.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 lc(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 cc(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 dc(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 pc(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 uc(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=Oe(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(St(n))try{Sl(n,r)}catch{}jr(n,JSON.stringify(a,null,2)+`
|
|
5149
|
+
`,"utf-8");try{let s=ne().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 Br(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function mc(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 fc(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 hc(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 gc(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 xc(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 vc(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 bc(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 yc(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 wc(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(p=>p.id===e),u={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(u.primaryToolLabel=r),c>=0){let p=l.boards[c];return l.boards[c]={...p,...u,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(u),`board "${e}" added`});return{summary:i}}async function kc(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 _c(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(p=>p.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let u=l.columns.findIndex(p=>p.id===a);return u>=0?(l.columns[u]={...l.columns[u],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ec(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 Sc(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 Tc(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 Ac(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 Cc(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 Ic(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=cn(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=tr(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 Mc(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=Ln(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Lc(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}}Wt();import{resolve as Pc}from"path";function zr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
4900
5150
|
|
|
4901
5151
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
4902
5152
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -4951,7 +5201,7 @@ ${s||"You are "+a+"."}
|
|
|
4951
5201
|
<h2>Recent classifications</h2>
|
|
4952
5202
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
4953
5203
|
<div id="recent"></div>
|
|
4954
|
-
</section>`;return
|
|
5204
|
+
</section>`;return L({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Rc,scripts:`${e}<script>${$c}</script>`})}var Rc=`
|
|
4955
5205
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
4956
5206
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
4957
5207
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5055,7 +5305,7 @@ details {
|
|
|
5055
5305
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5056
5306
|
}
|
|
5057
5307
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5058
|
-
details[open] summary { margin-bottom: 8px; }
|
|
5308
|
+
details[open] summary { margin-bottom: 8px; }`,$c=`
|
|
5059
5309
|
const $ = (id) => document.getElementById(id);
|
|
5060
5310
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5061
5311
|
|
|
@@ -5275,7 +5525,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5275
5525
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5276
5526
|
|
|
5277
5527
|
refresh();
|
|
5278
|
-
`;function
|
|
5528
|
+
`;function Fr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zr({peers:a,localToken:n}))}async function Ur(t,e,a){try{let n=t.method==="GET"?void 0:await Fc(t),r=jc(),o={"GET /api/admin/graph/state":()=>Oc(r),"POST /api/admin/graph/classifications/approve":()=>Nc(r,n),"POST /api/admin/graph/classifications/reject":()=>Dc(r,n),"POST /api/admin/graph/nodes":()=>Hc(r,n),"PATCH /api/admin/graph/nodes":()=>Bc(r,n),"DELETE /api/admin/graph/nodes":()=>zc(r,n),"PUT /api/admin/graph/schema":()=>qc(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){ca(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();ca(e,200,l)}catch(n){ca(e,400,{error:n?.message||"graph op failed"})}}function jc(){let t=ne(),e=Pc(process.cwd(),t.graph.baseDir);return new Ja({baseDir:e})}function Oc(t){let e=ne(),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 Nc(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Wr(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=da(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Dc(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Wr(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Wr(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 Hc(t,e){let a=qr(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?qr(String(e.parentId)):null,o=da({[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 Bc(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=da({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function zc(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function qc(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 da(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 qr(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function ca(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Fc(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 Gr=`
|
|
5279
5529
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
5280
5530
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
5281
5531
|
<p class="apv__lead">What you asked agents for that is not finished, oldest first. Nothing leaves this list by getting old: close it as done, or drop it.</p>
|
|
@@ -5292,7 +5542,7 @@ refresh();
|
|
|
5292
5542
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5293
5543
|
</form>
|
|
5294
5544
|
</details>
|
|
5295
|
-
</section>`,
|
|
5545
|
+
</section>`,Xr=`
|
|
5296
5546
|
.apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
|
|
5297
5547
|
.apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
|
|
5298
5548
|
.apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
|
|
@@ -5301,7 +5551,7 @@ refresh();
|
|
|
5301
5551
|
.apv__state.is-needs_attention { color: var(--ax-err); }
|
|
5302
5552
|
.apv__state.is-waiting_owner { color: var(--ax-amber-ink); }
|
|
5303
5553
|
.apv__req input[type=text].apv__evidence { flex: 1 1 220px; min-width: 0; font: inherit; font-size: 13px; padding: 8px 10px; border-radius: var(--ax-radius-sm); border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-text); }
|
|
5304
|
-
`,
|
|
5554
|
+
`,Kr=`
|
|
5305
5555
|
(function(){
|
|
5306
5556
|
var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
|
|
5307
5557
|
function $(id){ return document.getElementById(id); }
|
|
@@ -5396,7 +5646,7 @@ load();
|
|
|
5396
5646
|
document.addEventListener('apv:decided', load);
|
|
5397
5647
|
setInterval(function(){ if (document.visibilityState === 'visible' && !$('req-section').contains(document.activeElement)) load(); }, 60000);
|
|
5398
5648
|
})();
|
|
5399
|
-
`;function
|
|
5649
|
+
`;function Jr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
5400
5650
|
<header class="apv__head">
|
|
5401
5651
|
<div>
|
|
5402
5652
|
<h1>Approvals</h1>
|
|
@@ -5418,7 +5668,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !$('req-se
|
|
|
5418
5668
|
<ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
|
|
5419
5669
|
<p id="apv-snoozed" class="apv__foot"></p>
|
|
5420
5670
|
|
|
5421
|
-
${
|
|
5671
|
+
${Gr}
|
|
5422
5672
|
|
|
5423
5673
|
<details class="apv__settings" id="apv-settings">
|
|
5424
5674
|
<summary>Settings: expiry, later, daily digest</summary>
|
|
@@ -5433,7 +5683,7 @@ ${xr}
|
|
|
5433
5683
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5434
5684
|
</form>
|
|
5435
5685
|
</details>
|
|
5436
|
-
</div>`;return
|
|
5686
|
+
</div>`;return L({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Uc+Xr,scripts:`${e}<script>${Wc}</script><script>${Kr}</script>`})}var Uc=`
|
|
5437
5687
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
5438
5688
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
5439
5689
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -5482,7 +5732,7 @@ ${xr}
|
|
|
5482
5732
|
@media (max-width: 560px) {
|
|
5483
5733
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
5484
5734
|
}
|
|
5485
|
-
`,
|
|
5735
|
+
`,Wc=`
|
|
5486
5736
|
(function(){
|
|
5487
5737
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
5488
5738
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -5650,7 +5900,7 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
5650
5900
|
load();
|
|
5651
5901
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
5652
5902
|
})();
|
|
5653
|
-
`;var
|
|
5903
|
+
`;var We="/api/admin/approvals/requests",Vr=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Yr(t,e,a,n){try{return await Gc(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Gc(t,e,a,n){if(t==="GET"&&e===We){let r=Yt(n);return{status:200,body:{items:r?r.listOpen():[],settings:Vt(n.configPath)}}}if(t==="POST"&&e===`${We}/close`){let r=typeof a.id=="string"?a.id:"",o=a.action;if(!r||o!=="done"&&o!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let s=Yt(n),i=s?.get(r);if(!s||!i||i.state==="candidate")return{status:404,body:{error:`no request "${r}"`}};let l=o==="done"?typeof a.evidence=="string"?a.evidence:"":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return s.close(r,o==="done"?"done":"dropped",l,n.now??Date.now())?{status:200,body:{ok:!0,message:o==="done"?`${r} closed as done`:`${r} dropped`}}:{status:409,body:{error:`${r} is already closed`}}}if(t==="POST"&&e===`${We}/settings`){let r={},o=i=>{let l=a[i];if(l!==void 0){if(typeof l!="number"||!(l>0))throw new Error(`${i} must be a positive number`);return l}};typeof a.enabled=="boolean"&&(r.enabled=a.enabled),r.from=Vr(a.from),r.channels=Vr(a.channels),r.staleAfterHours=o("staleAfterHours"),r.retentionDays=o("retentionDays");let s=await mn(r,{configPath:n.configPath,reload:n.reload});return s.success?{status:200,body:{ok:!0,settings:Vt(n.configPath)}}:{status:400,body:{error:s.error}}}return{status:404,body:{error:"Not found"}}}var Xc=["yes","no","later"];function Z(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Tt(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 Qr(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Jr({peers:e,localToken:a}))}async function Zr(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 Z(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(We)){let i=await Yr(o,a,o==="POST"?await Tt(t):{},s);return Z(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=rt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return Z(e,200,{...i,settings:ke(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Tt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Xc.includes(c))return Z(e,400,{error:"send { key, action: yes | no | later }"}),!0;let u=ke(s.configPath),p=await ot(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:u.laterHours,by:"operator (dashboard)"});return p.ok?(Z(e,200,{ok:!0,message:p.message}),!0):(Z(e,409,{error:p.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Tt(t),l=fn(s,typeof i.key=="string"?i.key:"",!!ke(s.configPath).popup?.enabled);return l.ok?(Z(e,200,{ok:!0,message:l.message}),!0):(Z(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Tt(t),l={},c=p=>{let f=i[p];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${p} must be a positive number`);return f}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let p=i.destination.trim();if(!p)l.destination=null;else{let f=Fn(p);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let u=await Un(l,{configPath:s.configPath,reload:s.reload});return u.success?(Z(e,200,{ok:!0,settings:ke(s.configPath)}),!0):(Z(e,400,{error:u.error}),!0)}}catch(i){return Z(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return Z(e,404,{error:"Not found"}),!0}import{resolve as Vc}from"path";import{existsSync as Yc}from"fs";import Qc from"better-sqlite3";function eo(t={}){let e=`<div class="ax-obs">
|
|
5654
5904
|
<header class="ax-obs__head">
|
|
5655
5905
|
<h1>Health</h1>
|
|
5656
5906
|
<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>
|
|
@@ -5772,7 +6022,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
5772
6022
|
</div>
|
|
5773
6023
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
5774
6024
|
</section>
|
|
5775
|
-
</div>`;return
|
|
6025
|
+
</div>`;return L({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Kc,scripts:`<script>${Jc}</script>`})}var Kc=`
|
|
5776
6026
|
.ax-obs { padding: 16px 24px; }
|
|
5777
6027
|
.ax-obs__head { margin-bottom: 16px; }
|
|
5778
6028
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -5889,7 +6139,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
5889
6139
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
5890
6140
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
5891
6141
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
5892
|
-
`,
|
|
6142
|
+
`,Jc=`
|
|
5893
6143
|
(function(){
|
|
5894
6144
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
5895
6145
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -6273,23 +6523,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6273
6523
|
|
|
6274
6524
|
load(current);
|
|
6275
6525
|
})();
|
|
6276
|
-
`;var
|
|
6526
|
+
`;var no={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 ro(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function pa(t){let e=no[ro(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 Zc(){let t=Vc(process.cwd(),".agentx/db.sqlite");if(!Yc(t))return null;try{let e=new Qc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function oo(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(eo({peers:a}))}function ed(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 me(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function so(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Zc();if(!r)return me(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ed(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6277
6527
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
6278
6528
|
FROM route_traces
|
|
6279
6529
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6280
6530
|
ORDER BY at DESC LIMIT @limit
|
|
6281
|
-
`,
|
|
6531
|
+
`,u=r.db.prepare(c).all(l);return me(e,200,{rows:u}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6282
6532
|
SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
|
|
6283
6533
|
FROM rotations
|
|
6284
6534
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6285
6535
|
ORDER BY rotated_at DESC LIMIT @limit
|
|
6286
|
-
`,
|
|
6536
|
+
`,u=r.db.prepare(c).all(l);return me(e,200,{rows:u}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6287
6537
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
6288
6538
|
FROM task_history
|
|
6289
6539
|
WHERE ${i.join(" AND ")}
|
|
6290
6540
|
ORDER BY started_at DESC LIMIT @limit
|
|
6291
|
-
`,
|
|
6292
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6541
|
+
`,p=r.db.prepare(c).all(l).map(f=>({...f,plain:io(f.error)}));return me(e,200,{rows:p}),!0}if(n==="summary"||n==="overview")return me(e,200,td(r.db)),!0;if(n==="activity")return me(e,200,ad(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=to(i.searchParams.get("range"));return me(e,200,ao(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=to(i.searchParams.get("range")),c=ao(r.db,l),u=nd(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(u),!0}return me(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return me(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function io(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(`
|
|
6542
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function td(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,u=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),p=_=>u.length?u[Math.min(u.length-1,Math.floor(u.length*_))].duration_ms:0,f=p(.5),h=p(.95),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,I)=>_+pa(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,I)=>_+pa(I),0),g=t.prepare(`
|
|
6293
6543
|
SELECT agent_id,
|
|
6294
6544
|
COUNT(*) AS tasks,
|
|
6295
6545
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -6307,12 +6557,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6307
6557
|
WHERE started_at >= ?
|
|
6308
6558
|
GROUP BY channel
|
|
6309
6559
|
ORDER BY tasks DESC
|
|
6310
|
-
`).all(a),
|
|
6560
|
+
`).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),x=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),v=m.filter(_=>!x.has(_)),b=t.prepare(`
|
|
6311
6561
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
6312
6562
|
FROM task_history
|
|
6313
6563
|
WHERE status='error' AND started_at >= ?
|
|
6314
6564
|
ORDER BY started_at DESC LIMIT 5
|
|
6315
|
-
`).all(o).map(
|
|
6565
|
+
`).all(o).map(_=>({..._,plain:io(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:f,p95DurationMs:h,spendToday:E,spendDelta:E-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:b}}function ad(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(`
|
|
6316
6566
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
6317
6567
|
COUNT(*) AS tasks,
|
|
6318
6568
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -6339,7 +6589,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6339
6589
|
WHERE started_at >= @since
|
|
6340
6590
|
GROUP BY agent_id
|
|
6341
6591
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
6342
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
6592
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function to(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 ao(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
6343
6593
|
SELECT day, agent_id, model,
|
|
6344
6594
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
6345
6595
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -6347,37 +6597,37 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6347
6597
|
FROM usage_daily
|
|
6348
6598
|
${a}
|
|
6349
6599
|
ORDER BY day
|
|
6350
|
-
`).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,
|
|
6600
|
+
`).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,u=0,p=0,f=0,h=0,k=0,E=0,S=0,g={},d={};for(let T of n){let M=pa(T),P=ro(T.model),j=no[P],B=(T.tier2_input_tokens||0)/1e6*j.input*.5+(T.tier2_output_tokens||0)/1e6*j.output*.5+(T.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(T.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,se=(T.input_tokens||0)+(T.tier2_input_tokens||0),F=(T.output_tokens||0)+(T.tier2_output_tokens||0),ae=(T.cache_read_tokens||0)+(T.tier2_cache_read_tokens||0),Y=(T.cache_create_tokens||0)+(T.tier2_cache_create_tokens||0);p+=M,T.day>=s&&(u+=M,k+=T.tasks||0),T.day>=i&&T.day<s&&(S+=M,E+=T.tasks||0),T.day===r&&(l+=M),T.day===o&&(c+=M),T.day===r&&(f+=B),T.day>=s&&(h+=B);let N=g[T.day]||(g[T.day]={date:T.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});N.tasks+=T.tasks||0,N.input+=se,N.output+=F,N.cacheRead+=ae,N.cacheCreate+=Y,N.cost+=M,N.tier2+=B;let ie=N.agents[T.agent_id]||(N.agents[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});ie.tasks+=T.tasks||0,ie.cost+=M,ie.tier2+=B,ie.input+=se,ie.output+=F,ie.cacheRead+=ae,ie.cacheCreate+=Y,T.model&&(ie.model=T.model);let U=d[T.agent_id]||(d[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});U.tasks+=T.tasks||0,U.cost+=M,U.tier2+=B,U.input+=se,U.output+=F,U.cacheRead+=ae,U.cacheCreate+=Y,T.model&&(U.model=T.model)}let m=Object.values(g).sort((T,M)=>T.date<M.date?-1:1),x=0,v=0,w=0,b=0,_=0,I=0;for(let T of m)x+=T.tasks,v+=T.input,w+=T.output,b+=T.cacheRead,_+=T.cacheCreate,I+=T.cost;let C=Object.entries(d).map(([T,M])=>({agent_id:T,...M,tokens:M.input+M.output+M.cacheRead+M.cacheCreate})).sort((T,M)=>M.cost-T.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:u,spend30d:p,tier2Today:f,tier2_7d:h,tier2PctToday:l>0?f/l:0,spendRange:I,avgDailyRange:m.length?I/m.length:0,tasksRange:x,tokensRange:v+w+b+_,cacheHitRange:b+v>0?b/(b+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(u-S)/S:0,tasksDeltaWoW:E>0?(k-E)/E:0},days:m,perAgent:C}}function nd(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+`
|
|
6351
6601
|
`+a.join(`
|
|
6352
6602
|
`)+`
|
|
6353
|
-
`}import{resolve as
|
|
6603
|
+
`}import{resolve as rd}from"path";import{existsSync as od}from"fs";import sd from"better-sqlite3";function id(){let t=rd(process.cwd(),".agentx/intent/ledger.sqlite");if(!od(t))return null;try{let e=new sd(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-lo>6e4&&(lo=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var lo=0;function Te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ld(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 co(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=id();if(!r)return Te(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ld(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),u=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let p=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,E=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${p}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
|
|
6354
6604
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
6355
6605
|
LEFT JOIN intent_resolutions r
|
|
6356
6606
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6357
6607
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
6358
|
-
`).get().n;return
|
|
6608
|
+
`).get().n;return Te(e,200,{since:s??null,eventsBySource:h,totalDecisions:k,decisionsByOutcome:E,totalDivergences:S,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let p=[],f={limit:u};s!==void 0&&(p.push("ts >= @since"),f.since=s),i&&(p.push("source = @source"),f.source=i),l&&(p.push("project = @project"),f.project=l);let h=`
|
|
6359
6609
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
6360
6610
|
FROM intent_events
|
|
6361
|
-
${
|
|
6611
|
+
${p.length?"WHERE "+p.join(" AND "):""}
|
|
6362
6612
|
ORDER BY ts DESC LIMIT @limit
|
|
6363
|
-
`;return
|
|
6613
|
+
`;return Te(e,200,{rows:r.db.prepare(h).all(f)}),!0}if(n==="divergences"){let p=[],f={limit:u};s!==void 0&&(p.push("ts >= @since"),f.since=s),i&&(p.push("source = @source"),f.source=i);let h=`
|
|
6364
6614
|
SELECT ts, source, decided_by,
|
|
6365
6615
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
6366
6616
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
6367
6617
|
event_id
|
|
6368
6618
|
FROM intent_divergences
|
|
6369
|
-
${
|
|
6619
|
+
${p.length?"WHERE "+p.join(" AND "):""}
|
|
6370
6620
|
ORDER BY ts DESC LIMIT @limit
|
|
6371
|
-
`;return
|
|
6621
|
+
`;return Te(e,200,{rows:r.db.prepare(h).all(f)}),!0}if(n==="active"){let p=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],f={limit:u};i&&(p.push("e.source = @source"),f.source=i);let h=`
|
|
6372
6622
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
6373
6623
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
6374
6624
|
FROM intent_decisions d
|
|
6375
6625
|
JOIN intent_events e ON e.id = d.event_id
|
|
6376
6626
|
LEFT JOIN intent_resolutions r
|
|
6377
6627
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6378
|
-
WHERE ${
|
|
6628
|
+
WHERE ${p.join(" AND ")}
|
|
6379
6629
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
6380
|
-
`;return
|
|
6630
|
+
`;return Te(e,200,{rows:r.db.prepare(h).all(f)}),!0}return Te(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Te(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function po(t={}){return L({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
6381
6631
|
<header class="ax-led__head">
|
|
6382
6632
|
<h1>Intent ledger</h1>
|
|
6383
6633
|
<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>
|
|
@@ -6582,7 +6832,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6582
6832
|
}
|
|
6583
6833
|
load();
|
|
6584
6834
|
})();
|
|
6585
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
6835
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function uo(t={}){return L({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
6586
6836
|
<header class="ax-cost__head">
|
|
6587
6837
|
<div>
|
|
6588
6838
|
<h1>Cost</h1>
|
|
@@ -7155,7 +7405,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7155
7405
|
load();
|
|
7156
7406
|
setInterval(load, 30000);
|
|
7157
7407
|
})();
|
|
7158
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7408
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function mo(t={}){let e=`<div class="ax-pj__root">
|
|
7159
7409
|
<aside class="ax-pj__list">
|
|
7160
7410
|
<header>
|
|
7161
7411
|
<h2>Projects</h2>
|
|
@@ -7182,7 +7432,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7182
7432
|
</header>
|
|
7183
7433
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
7184
7434
|
</section>
|
|
7185
|
-
</div>`;return
|
|
7435
|
+
</div>`;return L({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:cd,scripts:`<script>${dd}</script>`})}var cd=`
|
|
7186
7436
|
.ax-pj__root {
|
|
7187
7437
|
display: grid;
|
|
7188
7438
|
grid-template-columns: 360px 1fr;
|
|
@@ -7369,7 +7619,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7369
7619
|
}
|
|
7370
7620
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
7371
7621
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
7372
|
-
`,
|
|
7622
|
+
`,dd=`
|
|
7373
7623
|
(function(){
|
|
7374
7624
|
const $ = (sel) => document.querySelector(sel);
|
|
7375
7625
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -8019,31 +8269,31 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8019
8269
|
load();
|
|
8020
8270
|
});
|
|
8021
8271
|
})();
|
|
8022
|
-
`;import{resolve as na,join as $c}from"path";import{existsSync as ra,readdirSync as Pc,readFileSync as jc}from"fs";import Oc from"better-sqlite3";var Hr=String.raw`[\w.-]+(?:/[\w.-]+)+`,yc=new RegExp(`^(?:chat:)?(${Hr}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),wc=new RegExp(`^\\[(?:GitLab|GitHub) (${Hr}) `);function Dr(t){if(!t)return null;let e=t.match(yc);return e?e[1]:null}function ea(t){if(!t)return null;let e=t.trimStart().match(wc);return e?e[1]:null}function vt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Dr(typeof n?.chatId=="string"?n.chatId:null)??Dr(e)??ea(a)}function kc(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var _c=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Sc=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ec=t=>/^issue/i.test(t)?"issue":"mr";function Tc(t){let e=t.subject.match(_c)??t.inputPreview.trimStart().match(Sc);return e?{kind:Ec(e[1]),n:Number(e[2])}:null}function Ac(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 Br(t){if(!kc(t.projectId))return[];let e=Tc(t);return e?[e]:Ac(t.inputPreview)}var Cc=6e4,Ic=5*6e4,Mc=40,zr=6,qr=new Map;function Fr(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 Br(n)){let s=bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Mc)return[...e.values()]}}return[...e.values()]}async function Ur(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=bt(s.project,s.ref),l=qr.get(i);l&&n-l.at<(s.github?Ic:Cc)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=zr)await Promise.all(o.slice(s,s+zr).map(async i=>{let l=bt(i.project,i.ref),c=null;try{c=i.github?await Lc(i,e,a):await Rc(i,e,a)}catch{}qr.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Wr(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 Rc(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 Wr(`${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 Lc(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 Wr(`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}fi();var ta=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Gr(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=Na(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=ta(o.from,80);if(s){a.callback={from:s,status:ta(o.status,20)??"done"};let i=ta(o.peer,80);i&&(a.callback.peer=i)}}return a}function oa(){let t=na(process.cwd(),".agentx/intent/ledger.sqlite");if(!ra(t))return null;try{let e=new Oc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Xr>6e4&&(Xr=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Xr=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Nc(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Pe)return s}return"workflow"}return t}function Vr(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 Dc(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 Yr(t,e,a){return Va(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 Hc(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:G(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!aa(l))return{id:l,name:l,avatar:G(l),kind:"a2a"}}let i=o||r||s;if(i&&!aa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:G(i),kind:zc(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&&!aa(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Kr(p);return{id:c,name:l||i||c,avatar:G(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:G(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:G(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:G(i),kind:Kr(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:G(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:G(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:G(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:G(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:G(o),kind:"whatsapp"}}}return null}var Bc={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function zc(t,e){let a=Bc[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Kr(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function aa(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function G(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function Qr(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}
|
|
8272
|
+
`;import{resolve as ha,join as Ed}from"path";import{existsSync as ga,readdirSync as Sd,readFileSync as Td}from"fs";import Ad from"better-sqlite3";var ho=String.raw`[\w.-]+(?:/[\w.-]+)+`,pd=new RegExp(`^(?:chat:)?(${ho}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),ud=new RegExp(`^\\[(?:GitLab|GitHub) (${ho}) `);function fo(t){if(!t)return null;let e=t.match(pd);return e?e[1]:null}function ua(t){if(!t)return null;let e=t.trimStart().match(ud);return e?e[1]:null}function At(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():fo(typeof n?.chatId=="string"?n.chatId:null)??fo(e)??ua(a)}function md(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Ct(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var fd=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,hd=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,gd=t=>/^issue/i.test(t)?"issue":"mr";function xd(t){let e=t.subject.match(fd)??t.inputPreview.trimStart().match(hd);return e?{kind:gd(e[1]),n:Number(e[2])}:null}function vd(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 go(t){if(!md(t.projectId))return[];let e=xd(t);return e?[e]:vd(t.inputPreview)}var bd=6e4,yd=5*6e4,wd=40,xo=6,vo=new Map;function bo(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 go(n)){let s=Ct(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=wd)return[...e.values()]}}return[...e.values()]}async function yo(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Ct(s.project,s.ref),l=vo.get(i);l&&n-l.at<(s.github?yd:bd)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=xo)await Promise.all(o.slice(s,s+xo).map(async i=>{let l=Ct(i.project,i.ref),c=null;try{c=i.github?await _d(i,e,a):await kd(i,e,a)}catch{}vo.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function wo(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 kd(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 wo(`${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 _d(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 wo(`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}Pi();var ma=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function ko(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=Ga(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=ma(o.from,80);if(s){a.callback={from:s,status:ma(o.status,20)??"done"};let i=ma(o.peer,80);i&&(a.callback.peer=i)}}return a}function xa(){let t=ha(process.cwd(),".agentx/intent/ledger.sqlite");if(!ga(t))return null;try{let e=new Ad(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-_o>6e4&&(_o=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var _o=0;function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Ne={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 Cd(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Ne)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Ne)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Ne)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 Ne)return s}return"workflow"}return t}function To(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 Id(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 Ao(t,e,a){return on(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 Md(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:X(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&&!fa(l))return{id:l,name:l,avatar:X(l),kind:"a2a"}}let i=o||r||s;if(i&&!fa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:X(i),kind:Rd(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&&!fa(i||l||"")){let u=typeof n.channel=="string"?n.channel:"",p=Eo(u);return{id:c,name:l||i||c,avatar:X(l||i||c),kind:p}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:X(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:X(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:X(i),kind:Eo(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:X(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:X(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:X(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:X(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:X(o),kind:"whatsapp"}}}return null}var Ld={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Rd(t,e){let a=Ld[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Eo(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function fa(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 X(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 Co(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}
|
|
8023
8273
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
8024
|
-
${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
|
|
8274
|
+
${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 $d(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 Io(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
8025
8275
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
8026
8276
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
8027
|
-
`).all(r),s=new Map,i=new Map;if(o.length>0){let b=o.map(M=>M.id),
|
|
8277
|
+
`).all(r),s=new Map,i=new Map;if(o.length>0){let b=o.map(M=>M.id),_=b.map((M,P)=>`@id${P}`).join(","),I=Object.fromEntries(b.map((M,P)=>[`id${P}`,M])),C=t.prepare(`
|
|
8028
8278
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
8029
|
-
FROM intent_decisions WHERE event_id IN (${
|
|
8279
|
+
FROM intent_decisions WHERE event_id IN (${_}) ORDER BY decided_at ASC
|
|
8030
8280
|
`).all(I);for(let M of C)s.has(M.event_id)||s.set(M.event_id,[]),s.get(M.event_id).push(M);let T=t.prepare(`
|
|
8031
8281
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
8032
|
-
FROM intent_resolutions WHERE decision_event_id IN (${
|
|
8033
|
-
`).all(I);for(let M of T)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,c=new Map,
|
|
8282
|
+
FROM intent_resolutions WHERE decision_event_id IN (${_})
|
|
8283
|
+
`).all(I);for(let M of T)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,c=new Map,u=new Map,p=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],E=Kt(e?.business??{});for(let b of o){let _=null;try{_=JSON.parse(b.raw_json)}catch{}let I=Ao(b.source,_,k),C=Co(b.source,_),T=ko(_),M=b.project??At(_,b.subject,C),P=null,j=null;I?(P=I.client,j=I.project||`${I.client}/_chat`):M&&(P=at(M,h),j=M);let B=Cd(b.source,b.intent||"",_),se=Ne[B]||{label:B,color:"#6b7280"};u.has(B)||u.set(B,{id:B,label:se.label,color:se.color});let F="__system",ae,Y=Md(b.source,b.intent||"",_);if(Y){F=Y.id,ae=Y.kind;let N=I?.displayName||Y.name;(!p.has(Y.id)||I?.displayName)&&p.set(Y.id,{id:Y.id,name:N,avatar:X(N),kind:Y.kind})}else p.has("__system")||p.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(b.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let ie=`${b.id}|${N.decided_by}`,U=i.get(ie),qa=N.decided_at,Fa=U?.resolved_at??null,zt=Fa===null,Mi=U?.duration_ms??(zt?n-qa:0),Li=zt?"active":U?.status==="error"||U?.status==="fail"?"error":"completed",Q,ze;if(P)Q=P,ze=j;else{let qt=E.get(N.agent_id);qt?(Q=qt,ze=`${qt}/_${b.source}`):(Q="unmapped",ze=`unmapped/_${b.source}`)}l.has(Q)||l.set(Q,{id:Q,name:Q,color:To(Q),projects:[]}),c.has(Q)||c.set(Q,new Set),c.get(Q).add(ze),f.push({id:`${b.id}|${N.decided_by}`,agentId:N.agent_id,clientId:Q,projectId:ze,channelId:B,initiatorId:F,initiatorKind:ae,subject:$d(b.subject),intent:b.intent||"",startedAt:qa,resolvedAt:Fa,duration:Mi,active:zt,outcome:Li,tokens:0,inputPreview:C,system:Id(N.agent_id,e),...T})}}let S=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,_)=>b.id.localeCompare(_.id)),g=[],d=new Set;if(e){let b=e.business??{},_=I=>{let C=b.orgChart?.[I]?.role,T=C?b.roles?.[C]?.title:void 0;return typeof T=="string"&&T.trim()?T.trim():void 0};for(let[I,C]of Object.entries(e.agents||{})){let T={id:I,name:C.name||I,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:_(I)};g.push(T),d.add(I)}}for(let b of f)d.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),d.add(b.agentId));g.sort((b,_)=>b.id.localeCompare(_.id));let m=[],x=new Set;for(let[b,_]of Object.entries(Ne))m.push({id:b,label:_.label,color:_.color}),x.add(b);for(let b of u.values())x.has(b.id)||m.push(b);let v=[...p.values()];v.find(b=>b.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let w=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:S,agents:g,channels:m,initiators:v,dispatches:f,forges:{gitlab:typeof w=="string"?w:void 0,github:"https://github.com"}}}function va(t){let e=xa();if(!e)return null;try{return Io(e.db,ve,t)}finally{e.close()}}function Mo(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:u}of t){l.gitlab??=u.forges?.gitlab,l.github??=u.forges?.github,u.now>s&&(s=u.now),u.windowH>i&&(i=u.windowH);for(let p of u.clients){let f=e.get(p.id);if(!f)e.set(p.id,{...p,projects:[...p.projects]});else{let h=Array.from(new Set([...f.projects,...p.projects])).sort();e.set(p.id,{...f,projects:h})}}for(let p of u.agents)a.has(p.id)||a.set(p.id,p);for(let p of u.channels)n.has(p.id)||n.set(p.id,p);for(let p of u.initiators)r.has(p.id)||r.set(p.id,p);for(let p of u.dispatches){let f=Pd(p);if(f.clientId!==p.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:To(f.clientId),projects:[]}),f.projectId!==p.projectId){let h=e.get(f.clientId);h.projects.includes(f.projectId)||e.set(f.clientId,{...h,projects:[...h.projects,f.projectId].sort()})}o.push({...f,nodeId:c,id:`${c}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,u)=>c.id.localeCompare(u.id)),agents:[...a.values()].sort((c,u)=>c.id.localeCompare(u.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,u)=>u.startedAt-c.startedAt)}}function Pd(t){if(t.clientId!=="unmapped")return t;let e=ua(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:at(e,a)}}async function It(t){let e=ve?.channels?.gitlab,a=await yo(bo(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ve=null;function Lo(t){ve=t}async function Ro(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=xa();if(!n)return fe(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=$o(parseInt(r.searchParams.get("hours")||"6",10));fe(e,200,await It(Io(n.db,ve,o)))}catch(r){fe(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var jd=5e3;async function ba(t,e,a,n=va){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
|
|
8034
8284
|
|
|
8035
|
-
`);let r=new URL(t.url||"/","http://_"),o
|
|
8285
|
+
`);let r=new URL(t.url||"/","http://_"),o=$o(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
|
|
8036
8286
|
|
|
8037
|
-
`)}catch{i()}},25e3);try{for(;!s;){try{let
|
|
8038
|
-
`),e.write(`data: ${JSON.stringify(
|
|
8287
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let u=await n(o),p=u&&await It(u);if(s)break;p?(e.write(`event: snapshot
|
|
8288
|
+
`),e.write(`data: ${JSON.stringify(p)}
|
|
8039
8289
|
|
|
8040
8290
|
`)):e.write(`event: error
|
|
8041
8291
|
data: ${JSON.stringify({error:"ledger not available"})}
|
|
8042
8292
|
|
|
8043
|
-
`)}catch(
|
|
8044
|
-
data: ${JSON.stringify({error:
|
|
8293
|
+
`)}catch(u){e.write(`event: error
|
|
8294
|
+
data: ${JSON.stringify({error:u?.message??String(u)})}
|
|
8045
8295
|
|
|
8046
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
8296
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<jd;)await new Promise(u=>setTimeout(u,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function $o(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Od(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=ha(process.cwd(),".agentx/task-history",t,n);if(!ga(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=ha(process.cwd(),".agentx/task-history",t,o);return ga(s)?So(s,e,a):null}return So(r,e,a)}function So(t,e,a){let n=null,r=1/0;for(let o of Sd(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Td(Ed(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let u=Date.parse(i);if(!Number.isFinite(u))continue;l=u}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function Po(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 fe(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=xa();if(!l)return fe(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 fe(e,404,{error:"event not found"}),!0;let u=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(!u)return fe(e,404,{error:"decision not found"}),!0;let p=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(c.raw_json)}catch{}let h=Co(c.source,f),k=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||h,E=null,S=null;if(u.agent_id){let w=Od(u.agent_id,u.decided_at);if(w){typeof w.responseText=="string"&&(E=w.responseText);let b=w.transcript;Array.isArray(b)&&(S=b.length)}}let g=ve?.business?.projects??[],d=ve?.business?.contactMap??[],m=Kt(ve?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Ao(c.source,f,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||At(f,c.subject,h)){let w=c.project||At(f,c.subject,h);x={client:at(w,g),project:w,via:c.project?`project namespace prefix (${w})`:`forge path in chat id / message (${w})`}}else if(u.agent_id){let w=m.get(u.agent_id);w&&(x={client:w,project:`${w}/_${c.source}`,via:`orgChart fallback (agent ${u.agent_id} reports up to a PM whose project belongs to ${w})`})}fe(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:u.decided_by,agentId:u.agent_id,outcome:u.outcome,reason:u.reason,startedAt:u.decided_at,resolvedAt:p?.resolved_at??null,durationMs:p?.duration_ms??null,input:k,response:E,transcriptLen:S,resolutionStatus:p?.status??null,resultSummary:p?.result_summary??null,attribution:x})}catch(c){fe(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Bd,readFileSync as zd}from"fs";import{resolve as Oo}from"path";Wt();function jo(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=Nd.replace(/__AGENT_ID__/g,O(e));return L({title:`AgentX \xB7 ${O(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${O(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Dd,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>${Hd}</script>`})}var Nd=`
|
|
8047
8297
|
<!-- Breadcrumb -->
|
|
8048
8298
|
<div class="ax-crumb">
|
|
8049
8299
|
<a href="/admin">Settings</a>
|
|
@@ -8632,7 +8882,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
|
8632
8882
|
</div>
|
|
8633
8883
|
</div>
|
|
8634
8884
|
</div>
|
|
8635
|
-
`,
|
|
8885
|
+
`,Dd=`
|
|
8636
8886
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
8637
8887
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
8638
8888
|
* primitives live in components.css.ts. */
|
|
@@ -8751,7 +9001,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
8751
9001
|
|
|
8752
9002
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
8753
9003
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
8754
|
-
`,
|
|
9004
|
+
`,Hd=`
|
|
8755
9005
|
const $ = (id) => document.getElementById(id);
|
|
8756
9006
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
8757
9007
|
|
|
@@ -9607,15 +9857,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
9607
9857
|
/* ===== Boot ===== */
|
|
9608
9858
|
initOptsToggles();
|
|
9609
9859
|
loadAgent();
|
|
9610
|
-
`;function
|
|
9611
|
-
`);return
|
|
9612
|
-
`);return
|
|
9860
|
+
`;function No(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(jo({agentId:a,peers:n,localToken:r}))}async function Do(t,e,a){try{let n=t.method==="GET"?void 0:await cp(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){Mt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,p={"GET ":()=>Ge(i),"PATCH ":()=>qd(i,n),"PATCH capability":()=>Wd(i,n),"POST mcp":()=>Fd(i,n),"DELETE mcp":()=>Ud(i,n),"GET identity":()=>Gd(i),"GET identity/file":()=>Xd(i,String(o.path||"")),"PUT identity/file":()=>Kd(i,n),"GET skills":()=>Jd(i),"POST skills":()=>Vd(i,n),"DELETE skills":()=>Yd(i,n),"GET skills/tree":()=>Qd(i,String(o.slug||"")),"GET skills/file":()=>Zd(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>ep(i,n),"GET skills/deps":()=>tp(i,String(o.slug||"")),"POST skills/install":()=>ap(i,n,t),"POST skills/deps":()=>np(i,n,t),"GET channels":()=>rp(i),"GET activity":()=>op(i,t),"GET handovers":()=>sp(i),"POST handovers":()=>ip(i,n),"DELETE handovers":()=>lp(n)}[c];if(!p){Mt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await p();Mt(e,200,f)}catch(n){Mt(e,400,{error:n?.message||"agent op failed"})}}function Ho(){let t=Oo(process.cwd(),"agentx.json");return Bd(t)?JSON.parse(zd(t,"utf-8")):null}function K(t){let e=Ho();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 Ge(t){let{def:e,cfg:a}=K(t),n=e.workspace?$e(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 qd(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:Ge(t)}}function Fd(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:Ge(t)}}function Ud(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:Ge(t)}}function Wd(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:Ge(t)}}function Gd(t){let{def:e}=K(t);return $e(e.workspace)}function Xd(t,e){if(!e)throw new Error("path query param required");let{def:a}=K(t);return st(a.workspace,e)}function Kd(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=K(t);return it(n.workspace,a,String(e?.content??""))}function Jd(t){let{def:e}=K(t),a=$e(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Vd(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=K(t);return lt(n.workspace,a,{title:e?.title,content:e?.content})}function Yd(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=K(t);return ct(n.workspace,a)}function Qd(t,e){if(!e)throw new Error("slug query param required");let{def:a}=K(t),n=An(a.workspace,e),r=dt(a.workspace,e);return{slug:e,tree:n,deps:r}}function Zd(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=K(t);return Cn(n.workspace,e,a)}function ep(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=K(t);return In(r.workspace,a,n,String(e?.content??""))}function tp(t,e){if(!e)throw new Error("slug query param required");let{def:a}=K(t);return dt(a.workspace,e)}async function ap(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=Bo(e?.worker),{def:o}=K(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(`
|
|
9861
|
+
`);return zo(a,r,s,`install-${n}:${Date.now()}`)}async function np(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Bo(e?.worker),{def:o}=K(t),s=dt(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=Oo(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(`
|
|
9862
|
+
`);return zo(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Bo(t){if(t&&typeof t=="string")return t;let e=ne();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function zo(t,e,a,n){let r=ne(),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(),u;try{u=JSON.parse(c)}catch{u={content:c}}if(!l.ok)throw new Error(u?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:u?.taskId,content:u?.content,duration:u?.duration,error:u?.error}}function rp(t){let e=Ho(),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 op(t,e){try{let n=(ne().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 ya(){return new Va}function sp(t){let e=ya(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function ip(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=ya().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 lp(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:ya().remove(e,a,n)?"Released":"No active handover for that chat"}}function Mt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function cp(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 Ae={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 qo=[{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 wa(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Ae)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
9613
9863
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
9614
9864
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
9615
9865
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
9616
9866
|
<main id="grid" class="ax-live__body"></main>
|
|
9617
9867
|
</div>
|
|
9618
|
-
`;return
|
|
9868
|
+
`;return L({title:`${Ae.brand} \xB7 ${Ae.subtitle}`,activeTab:"live",subtitle:Ae.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:dp,scripts:e+`<script>${pp}</script>`,headExtras:`<script>
|
|
9619
9869
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
9620
9870
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
9621
9871
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -9626,7 +9876,7 @@ loadAgent();
|
|
|
9626
9876
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
9627
9877
|
right.insertBefore(extras, right.firstChild);
|
|
9628
9878
|
});
|
|
9629
|
-
</script>`})}var
|
|
9879
|
+
</script>`})}var dp=`
|
|
9630
9880
|
/* --- Page frame --- */
|
|
9631
9881
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
9632
9882
|
|
|
@@ -9833,7 +10083,7 @@ loadAgent();
|
|
|
9833
10083
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
9834
10084
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
9835
10085
|
}
|
|
9836
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
10086
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,pp=`
|
|
9837
10087
|
'use strict';
|
|
9838
10088
|
|
|
9839
10089
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -10404,7 +10654,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10404
10654
|
});
|
|
10405
10655
|
}
|
|
10406
10656
|
|
|
10407
|
-
`;var
|
|
10657
|
+
`;var Fo=`
|
|
10408
10658
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
10409
10659
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
10410
10660
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -10578,7 +10828,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10578
10828
|
.mx-summary{max-width:56vw}
|
|
10579
10829
|
}
|
|
10580
10830
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
10581
|
-
`;var
|
|
10831
|
+
`;var Uo=`<script>
|
|
10582
10832
|
window.MX=(function(){
|
|
10583
10833
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
10584
10834
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -10687,7 +10937,7 @@ window.MX=(function(){
|
|
|
10687
10937
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
10688
10938
|
setHealth:setHealth,get:get};
|
|
10689
10939
|
})();
|
|
10690
|
-
</script>`;var
|
|
10940
|
+
</script>`;var Wo=`<script>
|
|
10691
10941
|
window.MXD=(function(){
|
|
10692
10942
|
function el(id){return document.getElementById(id)}
|
|
10693
10943
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -10901,7 +11151,7 @@ window.MXD=(function(){
|
|
|
10901
11151
|
|
|
10902
11152
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
10903
11153
|
})();
|
|
10904
|
-
</script>`;var
|
|
11154
|
+
</script>`;var Go=`<script>
|
|
10905
11155
|
(function(){
|
|
10906
11156
|
var LANES=[
|
|
10907
11157
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -11217,7 +11467,7 @@ window.MXD=(function(){
|
|
|
11217
11467
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
11218
11468
|
load();
|
|
11219
11469
|
})();
|
|
11220
|
-
</script>`;var
|
|
11470
|
+
</script>`;var Xo=`<script>
|
|
11221
11471
|
(function(){
|
|
11222
11472
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
11223
11473
|
var esc=MX.esc;
|
|
@@ -11395,7 +11645,7 @@ window.MXD=(function(){
|
|
|
11395
11645
|
}
|
|
11396
11646
|
load();setInterval(load,5000);
|
|
11397
11647
|
})();
|
|
11398
|
-
</script>`;var
|
|
11648
|
+
</script>`;var Ko=`
|
|
11399
11649
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
11400
11650
|
.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}
|
|
11401
11651
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -11436,7 +11686,7 @@ window.MXD=(function(){
|
|
|
11436
11686
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
11437
11687
|
.mx-rt-name{max-width:100%}
|
|
11438
11688
|
}
|
|
11439
|
-
`,
|
|
11689
|
+
`,Jo=`<script>
|
|
11440
11690
|
(function(){
|
|
11441
11691
|
var root=document.getElementById('mx-routines');
|
|
11442
11692
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -11563,7 +11813,7 @@ window.MXD=(function(){
|
|
|
11563
11813
|
syncBar();
|
|
11564
11814
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
11565
11815
|
})();
|
|
11566
|
-
</script>`;var
|
|
11816
|
+
</script>`;var Vo=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Yo=`<script>
|
|
11567
11817
|
(function(){
|
|
11568
11818
|
var root=document.getElementById('mx-feed');
|
|
11569
11819
|
if(!root)return;
|
|
@@ -11638,17 +11888,17 @@ window.MXD=(function(){
|
|
|
11638
11888
|
}
|
|
11639
11889
|
load();setInterval(load,5000);
|
|
11640
11890
|
})();
|
|
11641
|
-
</script>`;var
|
|
11891
|
+
</script>`;var ee={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 te(t,e,a,n,r=""){return G({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var up=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],mp=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],fp=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Qo(t){let e=ut({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">
|
|
11642
11892
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
11643
|
-
${
|
|
11893
|
+
${mp.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("")}
|
|
11644
11894
|
</div>
|
|
11645
11895
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
11646
|
-
${
|
|
11896
|
+
${fp.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
11647
11897
|
</div>
|
|
11648
11898
|
</div>
|
|
11649
11899
|
<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">
|
|
11650
11900
|
<section class="mx-section" aria-labelledby="mx-lanes-title">
|
|
11651
|
-
${ee
|
|
11901
|
+
${te(ee.activity,"What ran","One lane per origin. Each lane is scaled to its own peak so a quiet channel stays readable next to a busy one. Select a column for the day behind it.","mx-lanes-title")}
|
|
11652
11902
|
<div id="mx-lanes"><div class="mx-empty">Loading activity...</div></div>
|
|
11653
11903
|
<div class="mx-axis" id="mx-axis"></div>
|
|
11654
11904
|
<p class="mx-note">Coloured bars are runs that finished; the red cap on a column is the failures inside that day. Select any column for what ran that day, down to a single conversation.</p>
|
|
@@ -11656,32 +11906,32 @@ window.MXD=(function(){
|
|
|
11656
11906
|
|
|
11657
11907
|
<div class="mx-two">
|
|
11658
11908
|
<section class="mx-section" aria-labelledby="mx-origins-title">
|
|
11659
|
-
${ee
|
|
11909
|
+
${te(ee.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
|
|
11660
11910
|
<div class="mx-bars" id="mx-origins"><div class="mx-empty">Loading...</div></div>
|
|
11661
11911
|
</section>
|
|
11662
11912
|
<section class="mx-section" aria-labelledby="mx-causes-title">
|
|
11663
|
-
${ee
|
|
11913
|
+
${te(ee.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
|
|
11664
11914
|
<div class="mx-bars" id="mx-causes"><div class="mx-empty">Loading...</div></div>
|
|
11665
11915
|
<p class="mx-note" id="mx-cause-note"></p>
|
|
11666
11916
|
</section>
|
|
11667
11917
|
</div>
|
|
11668
11918
|
|
|
11669
11919
|
<section class="mx-section" aria-labelledby="mx-scatter-title">
|
|
11670
|
-
${ee
|
|
11920
|
+
${te(ee.effort,"Effort against output","Every recurring job, plotted as runtime spent against tokens produced on its successful runs. Both axes are logarithmic.","mx-scatter-title")}
|
|
11671
11921
|
<div class="mx-scatter" id="mx-scatter"><div class="mx-empty">Loading jobs...</div></div>
|
|
11672
11922
|
<div class="mx-legend" id="mx-scatter-legend"></div>
|
|
11673
11923
|
<p class="mx-note">Bubble size is the number of runs. Anything not healthy is labelled on the chart; select it for the attempt history behind the verdict.</p>
|
|
11674
11924
|
</section>
|
|
11675
11925
|
</div>`,r=`<div class="mx-view" id="mx-view-lifetime" role="tabpanel" aria-labelledby="mx-tab-lifetime" hidden>
|
|
11676
11926
|
<section class="mx-section" aria-labelledby="mx-threads-title">
|
|
11677
|
-
${ee
|
|
11927
|
+
${te(ee.lifetime,"Thread lifetimes","A thread is one agent talking on one channel in one conversation. The bar is its real first-to-last span; each tick is a session cut. Select one for its turns, tokens and time.","mx-threads-title")}
|
|
11678
11928
|
<div class="mx-chips" id="mx-thread-chips"></div>
|
|
11679
11929
|
<div id="mx-threads"><div class="mx-empty">Loading threads...</div></div>
|
|
11680
11930
|
<p class="mx-note">Select a thread to walk its runs, then a run to see which tools it touched. Grey ticks are stale cuts, amber ticks are context-full cuts.</p>
|
|
11681
11931
|
</section>
|
|
11682
11932
|
|
|
11683
11933
|
<section class="mx-section" aria-labelledby="mx-rot-title">
|
|
11684
|
-
${ee
|
|
11934
|
+
${te(ee.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
|
|
11685
11935
|
<div class="mx-bars" id="mx-rotations"><div class="mx-empty">Loading...</div></div>
|
|
11686
11936
|
<p class="mx-note" id="mx-rot-note"></p>
|
|
11687
11937
|
</section>
|
|
@@ -11689,39 +11939,39 @@ window.MXD=(function(){
|
|
|
11689
11939
|
<p id="mx-updated" class="mx-updated" aria-live="polite">Connecting to the fleet...</p>
|
|
11690
11940
|
|
|
11691
11941
|
<section class="mx-section" aria-labelledby="mx-auto-title">
|
|
11692
|
-
${ee
|
|
11942
|
+
${te(ee.schedules,"Today's automations","Persisted attempts are authoritative. Select a schedule to inspect its latest result and runtime.","mx-auto-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-run-count">0 schedules</span><button class="ax-btn ax-btn--ghost mx-show-all" id="mx-show-all" type="button" hidden>Show all</button></div>')}
|
|
11693
11943
|
<div class="ax-stack" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
|
|
11694
11944
|
</section>
|
|
11695
11945
|
|
|
11696
11946
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
11697
|
-
${ee
|
|
11947
|
+
${te(ee.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>')}
|
|
11698
11948
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
11699
|
-
${
|
|
11949
|
+
${up.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11700
11950
|
</div>
|
|
11701
11951
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
11702
11952
|
</section>
|
|
11703
11953
|
|
|
11704
11954
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
11705
|
-
${ee
|
|
11955
|
+
${te(ee.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>')}
|
|
11706
11956
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
11707
|
-
${
|
|
11957
|
+
${Vo.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11708
11958
|
</div>
|
|
11709
11959
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
11710
11960
|
</section>
|
|
11711
11961
|
|
|
11712
11962
|
<div class="mx-columns">
|
|
11713
11963
|
<section class="mx-section" aria-labelledby="mx-active-title">
|
|
11714
|
-
${ee
|
|
11964
|
+
${te(ee.activity,"Activity provenance","Who initiated current work and where it is running.","mx-active-title",'<span class="ax-tab-count" id="mx-active-count">0 active</span>')}
|
|
11715
11965
|
<div class="ax-stack" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
|
|
11716
11966
|
</section>
|
|
11717
11967
|
<section class="mx-section" aria-labelledby="mx-nodes-title">
|
|
11718
|
-
${ee
|
|
11968
|
+
${te(ee.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
|
|
11719
11969
|
<div class="ax-stack" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
|
|
11720
11970
|
</section>
|
|
11721
11971
|
</div>
|
|
11722
11972
|
|
|
11723
11973
|
<section class="mx-section" aria-labelledby="mx-agents-title">
|
|
11724
|
-
${ee
|
|
11974
|
+
${te(ee.agents,"Agents and skills","Runtime, model, installed skills, and task totals by node.","mx-agents-title",'<span class="ax-tab-count" id="mx-agent-count">0 agents</span>')}
|
|
11725
11975
|
<div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
|
|
11726
11976
|
</section>
|
|
11727
11977
|
</div>`,s=`${e}<main class="mx-content">
|
|
@@ -11737,7 +11987,7 @@ window.MXD=(function(){
|
|
|
11737
11987
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
11738
11988
|
</header>
|
|
11739
11989
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
11740
|
-
</aside>`;return
|
|
11990
|
+
</aside>`;return L({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Fo+Ko,scripts:Uo+hp+Wo+Go+Jo+Xo+Yo})}var hp=`<script>
|
|
11741
11991
|
(function(){
|
|
11742
11992
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
11743
11993
|
var range=document.getElementById('mx-range');
|
|
@@ -11765,7 +12015,7 @@ window.MXD=(function(){
|
|
|
11765
12015
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
11766
12016
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
11767
12017
|
})();
|
|
11768
|
-
</script>`;async function
|
|
12018
|
+
</script>`;async function Zo(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 gp(s,e.days)}function gp(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,u=0,p=0,f=0,h=0,k=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let m=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])m[x][0]+=d[x]?.[0]||0,m[x][1]+=d[x]?.[1]||0;n.set(d.day,m)}for(let d of g.origins){let m=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};m.runs+=d.runs,m.errors+=d.errors,m.hours+=d.hours,r.set(d.channel,m)}for(let d of g.causes){let m=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};m.count+=d.count;for(let x of d.agents)m.agents.includes(x)||m.agents.push(x);m.example||(m.example=d.example),o.set(d.cause,m)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,u+=g.rotations.tokenSum||0,p+=g.rotations.tokenSamples||0,f=Math.max(f,g.rotations.maxTokens),h+=g.retention.traces,k+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let E=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:E.length?Math.min(...E):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:u,tokenSamples:p,maxTokens:f},retention:{traces:h,tracesWithSteps:k}}}async function es(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 ts(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 xp(s,e.day)}function xp(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 as(t={}){let e=`
|
|
11769
12019
|
<select id="boardPicker" title="Switch board"></select>
|
|
11770
12020
|
<div class="search">
|
|
11771
12021
|
<span class="icon">\u2315</span>
|
|
@@ -11866,7 +12116,7 @@ window.MXD=(function(){
|
|
|
11866
12116
|
</footer>
|
|
11867
12117
|
</div>
|
|
11868
12118
|
</div>
|
|
11869
|
-
<script src="/sortable.min.js"></script>`;return
|
|
12119
|
+
<script src="/sortable.min.js"></script>`;return L({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:vp,scripts:`<script>${bp}</script>`,headExtras:`<script>
|
|
11870
12120
|
// The boards page has its own connection dot + wants body height:100%
|
|
11871
12121
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
11872
12122
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -11882,7 +12132,7 @@ window.MXD=(function(){
|
|
|
11882
12132
|
right.insertBefore(dot, right.firstChild);
|
|
11883
12133
|
}
|
|
11884
12134
|
});
|
|
11885
|
-
</script>`})}var
|
|
12135
|
+
</script>`})}var vp=`
|
|
11886
12136
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
11887
12137
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
11888
12138
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -12135,7 +12385,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
12135
12385
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
12136
12386
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
12137
12387
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
12138
|
-
`,
|
|
12388
|
+
`,bp=`
|
|
12139
12389
|
'use strict';
|
|
12140
12390
|
const state = {
|
|
12141
12391
|
boards: [], current: null, items: {},
|
|
@@ -13188,9 +13438,9 @@ function appendEvents(events) {
|
|
|
13188
13438
|
}
|
|
13189
13439
|
|
|
13190
13440
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
13191
|
-
`;function
|
|
13441
|
+
`;function ns(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
13192
13442
|
<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>
|
|
13193
|
-
${
|
|
13443
|
+
${qo.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${O(n.alias)}</span>`:"";return`<article class="term"><h3>${O(n.term)}${r}</h3><p>${O(n.definition)}</p></article>`}).join("")}`;return L({title:`${Ae.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:yp})}var yp=`
|
|
13194
13444
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
13195
13445
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
13196
13446
|
.lead {
|
|
@@ -13220,7 +13470,7 @@ article.term .alias {
|
|
|
13220
13470
|
}
|
|
13221
13471
|
article.term p {
|
|
13222
13472
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
13223
|
-
}`;function
|
|
13473
|
+
}`;function rs(t={}){let e=`<div class="ax-wf__root">
|
|
13224
13474
|
<aside class="ax-wf__list">
|
|
13225
13475
|
<header>
|
|
13226
13476
|
<h2>Workflows</h2>
|
|
@@ -13297,7 +13547,7 @@ article.term p {
|
|
|
13297
13547
|
</aside>
|
|
13298
13548
|
</div>
|
|
13299
13549
|
|
|
13300
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return
|
|
13550
|
+
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return L({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:wp,scripts:`<script>${z({workflowHealth:rn})}${kp}</script>`})}var wp=`
|
|
13301
13551
|
.ax-wf__root {
|
|
13302
13552
|
display: grid;
|
|
13303
13553
|
grid-template-columns: 340px 1fr;
|
|
@@ -13681,7 +13931,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13681
13931
|
font-size: 12px; z-index: 50;
|
|
13682
13932
|
}
|
|
13683
13933
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
13684
|
-
`,
|
|
13934
|
+
`,kp=`
|
|
13685
13935
|
(() => {
|
|
13686
13936
|
const $ = (sel) => document.querySelector(sel)
|
|
13687
13937
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -14470,7 +14720,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14470
14720
|
setInterval(refresh, 15000)
|
|
14471
14721
|
})
|
|
14472
14722
|
})();
|
|
14473
|
-
`;function
|
|
14723
|
+
`;function os(t={}){let e=`<div class="ax-proc__root">
|
|
14474
14724
|
<header class="ax-proc__header">
|
|
14475
14725
|
<h1>Procedures</h1>
|
|
14476
14726
|
<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>
|
|
@@ -14514,7 +14764,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14514
14764
|
<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>
|
|
14515
14765
|
<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>
|
|
14516
14766
|
</section>
|
|
14517
|
-
</div>`;return
|
|
14767
|
+
</div>`;return L({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:_p,scripts:`<script>${Ep}</script>`})}var _p=`
|
|
14518
14768
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
14519
14769
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14520
14770
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -14540,7 +14790,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14540
14790
|
.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); }
|
|
14541
14791
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
14542
14792
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
14543
|
-
|
|
14793
|
+
`,Ep=`
|
|
14544
14794
|
(function(){
|
|
14545
14795
|
function $(sel){ return document.querySelector(sel) }
|
|
14546
14796
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -14640,7 +14890,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14640
14890
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
14641
14891
|
else bootAll()
|
|
14642
14892
|
})();
|
|
14643
|
-
`;function
|
|
14893
|
+
`;function ss(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
14644
14894
|
data-task-id="${O(t.taskId)}"
|
|
14645
14895
|
data-agent-id="${O(t.agentId)}"
|
|
14646
14896
|
data-node-url="${O(t.nodeUrl)}"
|
|
@@ -14683,7 +14933,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14683
14933
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
14684
14934
|
</div>
|
|
14685
14935
|
</footer>
|
|
14686
|
-
</div>`;return
|
|
14936
|
+
</div>`;return L({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Sp,scripts:`<script>${Tp}</script>`})}var Sp=`
|
|
14687
14937
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
14688
14938
|
the sticky topbar. Breathe. */
|
|
14689
14939
|
.ax-task-page {
|
|
@@ -14825,7 +15075,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14825
15075
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
14826
15076
|
}
|
|
14827
15077
|
|
|
14828
|
-
`,
|
|
15078
|
+
`,Tp=`
|
|
14829
15079
|
(function () {
|
|
14830
15080
|
var root = document.querySelector('.ax-task-page');
|
|
14831
15081
|
if (!root) return;
|
|
@@ -15210,7 +15460,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15210
15460
|
});
|
|
15211
15461
|
|
|
15212
15462
|
})();
|
|
15213
|
-
`;function
|
|
15463
|
+
`;function is(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
15214
15464
|
data-agent-id="${O(t.agentId)}"
|
|
15215
15465
|
data-agent-name="${O(e)}"
|
|
15216
15466
|
data-node-url="${O(t.nodeUrl)}">
|
|
@@ -15239,7 +15489,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15239
15489
|
<div class="ax-history__list" id="hist-list">
|
|
15240
15490
|
<div class="ax-history__empty">loading\u2026</div>
|
|
15241
15491
|
</div>
|
|
15242
|
-
</div>`;return
|
|
15492
|
+
</div>`;return L({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ap,scripts:`<script>${Cp}</script>`})}var Ap=`
|
|
15243
15493
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
15244
15494
|
flush against the sticky topbar. */
|
|
15245
15495
|
.ax-history {
|
|
@@ -15291,7 +15541,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15291
15541
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
15292
15542
|
}
|
|
15293
15543
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
15294
|
-
`,
|
|
15544
|
+
`,Cp=`
|
|
15295
15545
|
(function () {
|
|
15296
15546
|
var root = document.querySelector('.ax-history');
|
|
15297
15547
|
if (!root) return;
|
|
@@ -15391,26 +15641,26 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15391
15641
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
15392
15642
|
});
|
|
15393
15643
|
})();
|
|
15394
|
-
`;function
|
|
15644
|
+
`;function cs(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 De(t,e,l=>ls(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Mp(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?De(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"])?De(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"])?De(t,e,l=>{let c=Gt.safeParse(l);if(!c.success)return R(e,200,{ok:!1,issues:c.error.issues.map(p=>({path:p.path.join("."),message:p.message}))});let u=Xt(c.data).map(p=>({path:"",message:p}));return R(e,200,{ok:u.length===0,issues:u,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 De(t,e,u=>ls(e,a,u,{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 Ip=["mesh"];function ls(t,e,a,n){let r=Gt.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=Xt(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 u of Ip)!(u in l)&&u in c&&(o[u]=c[u])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),u=l?.yamlPath,p=!!u||/yaml round-trip failed/.test(c);return R(t,p?409:500,{error:p?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:p?"yaml-authored":"save-failed",...u?{path:u}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),R(t,200,{workflow:i})}function Mp(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,u=r.get("summary")==="1"||r.get("summary")==="true",p=a.runs.list({workflowId:c,limit:l});if(!u)return R(e,200,{runs:p});let f=p.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return De(t,e,c=>{let u=c?.status;return u!=="paused"&&u!=="running"&&u!=="canceled"?R(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,u)?R(e,200,{ok:!0,runId:l,status:u}):R(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return Lp(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 Lp(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)}
|
|
15395
15645
|
|
|
15396
|
-
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(
|
|
15646
|
+
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(u);try{e.end()}catch{}};t.on("close",s);let i=p=>{if(!o)try{e.write(`data: ${JSON.stringify(p)}
|
|
15397
15647
|
|
|
15398
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function je(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){L(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{L(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{L(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>L(e,400,{error:"body read failed",message:r.message})),!0}function L(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Pp}from"fs";import{createRequire as jp}from"module";import{deflateSync as zd}from"zlib";var qd=[41,121,255],Fd=[255,255,255],jo=new Map;function pa(t){let e=jo.get(t);return e||(e=Wd(t,Ud(t)),jo.set(t,e)),e}function Ud(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?Fd:qd;a.set(c,o*e+1+s*3)}return a}function Wd(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]),da("IHDR",a),da("IDAT",zd(e)),da("IEND",Buffer.alloc(0))])}function da(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(Xd(n)),Buffer.concat([a,n,r])}var Gd=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 Xd(t){let e=4294967295;for(let a of t)e=Gd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function kt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Kd(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:kt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:kt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:kt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Jd(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:kt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Vd=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Oo(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let h=Yd(s.searchParams.get("timezone")),w=await o.snapshot({date:Qd(h),timezone:h});return a==="/api/app/activity"?ue(e,200,{ts:w.ts,tasks:Jd(w.nodes)}):ue(e,200,{ts:w.ts,nodes:w.nodes.map(Kd)})}if(n==="GET"&&a==="/api/app/approvals")return ue(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Vd);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await Ee(t)}catch(h){return ue(e,400,{error:h.message})}let p=Ue(c.node);if(!p)return ue(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,m;if(i){let h=Ue(c.taskId);if(!h)return ue(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")m=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let _=Ue(c.message);if(!_)return ue(e,400,{error:"message is required"});m=await o.nodePost(p,w,{message:_,sender:u})}}else if(a==="/api/app/nodes/restart")m=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")m=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=Ue(c.cronId);if(!h||typeof c.enabled!="boolean")return ue(e,400,{error:"cronId and enabled (true or false) are required"});m=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=Ue(c.key),w=c.action;if(!h||w!=="yes"&&w!=="no"&&w!=="later")return ue(e,400,{error:"key and action (yes, no or later) are required"});m=await o.decide(p,h,w,u)}return ue(e,m.status,m.body)}function Ue(t){return typeof t=="string"?t.trim():""}function Yd(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Qd(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function Ee(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function ue(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Zd=2048,No=/^[A-Za-z0-9_-]{8,256}$/;async function Do(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return K(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):ep()});if(n==="GET"&&a==="/api/app/alerts")return K(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return K(e,404,{error:"not found"});if(!s||l)return K(e,503,{error:l});let c;try{c=await Ee(t)}catch(h){return K(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),w=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return K(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return K(e,400,{error:`${w} must be true or false`});let E={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),E[ce[g].field]=c[ce[g].field];return K(e,200,{ok:!0,...E})}let p=tp(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return K(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return K(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!No.test(u)||typeof m!="string"||!No.test(m)?K(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?K(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),K(e,200,{ok:!0}))}function ep(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function tp(t,e){if(typeof t!="string"||t.length>Zd)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Da();var Bo=50,ap=280;async function zo(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=np(await o.recent(Bo))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Ho(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Ho(e,404,{error:"not found"})}function qo(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||z(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=Me();return r?new _n(r):null}}}function np(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:ua(typeof n.summary=="string"?n.summary:"",ap),by:typeof n.agentId=="string"?ua(n.agentId,100):null,node:ua(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,Bo)}function ua(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Ho(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var rp="operator",op=50,Fo=4,Uo=500;function sp(t){let e={channel:"app",chatId:t.chatId,sender:rp,...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 Wo(t,e,a,n){let{path:r,body:o}=sp(e),s="",i=!1,l=[],c=new Map,p=(u,m,h)=>{let w=u!=="done",_=i?{text:Ze(m,w),artifacts:[]}:Qe(m,le.perMessage,w),{cleanText:E,ui:g}=u==="done"?tt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ma(g);return{status:u,text:E,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of lp(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<op){let w={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(w),h.id&&c.set(String(h.id),w)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return p("error",s,ip(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 ip(t){let e=String(t||"The agent could not answer.");return qa(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ma(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,Fo).map(s=>s.slice(0,Uo));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Fo).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Uo)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*lp(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,`
|
|
15648
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,u=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==c&&(c=p.updatedAt,i(p))},2e3);return!0}function De(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 cu}from"fs";import{createRequire as du}from"module";var Rp=2048,ds=/^[A-Za-z0-9_-]{8,256}$/;async function ps(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 J(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):$p()});if(n==="GET"&&a==="/api/app/alerts")return J(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 J(e,404,{error:"not found"});if(!s||l)return J(e,503,{error:l});let c;try{c=await gt(t)}catch(h){return J(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),k=h.map(g=>ce[g].field).join(", "),E=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return J(e,400,{error:`send ${E}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return J(e,400,{error:`${k} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),S[ce[g].field]=c[ce[g].field];return J(e,200,{ok:!0,...S})}let u=Pp(c.endpoint,o.allowedHosts);if(!u){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return J(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return J(e,200,{ok:!0,removed:s.unsubscribe(u,r.id)});let p=c.keys?.p256dh,f=c.keys?.auth;return typeof p!="string"||!ds.test(p)||typeof f!="string"||!ds.test(f)?J(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?J(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:u,p256dh:p,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),J(e,200,{ok:!0}))}function $p(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Pp(t,e){if(typeof t!="string"||t.length>Rp)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 J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Xa();var ms=50,jp=280;async function fs(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=Op(await o.recent(ms))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return us(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return us(e,404,{error:"not found"})}function hs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||q(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=ye();return r?new Rn(r):null}}}function Op(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:"",jp),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,ms)}function ka(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function us(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Np="operator",Dp=50,gs=4,xs=500;function Hp(t){let e={channel:"app",chatId:t.chatId,sender:Np,...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 vs(t,e,a,n){let{path:r,body:o}=Hp(e),s="",i=!1,l=[],c=new Map,u=(p,f,h)=>{let k=p!=="done",E=i?{text:tt(f,k),artifacts:[]}:et(f,le.perMessage,k),{cleanText:S,ui:g}=p==="done"?nt(E.text):{cleanText:E.text,ui:void 0},d=i?void 0:_a(g);return{status:p,text:S,tools:l,files:E.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let p=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let f=await p.json().then(h=>h?.error).catch(()=>"");return u("error",s,f||`AgentX answered HTTP ${p.status}.`)}for await(let f of zp(p.body)){n(f.event,f.data);let h=f.data??{};if(f.event==="start")i=h.rich===!1;else if(f.event==="text"&&typeof h.text=="string")s+=h.text;else if(f.event==="tool"&&h.status==="start"&&l.length<Dp){let k={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(k),h.id&&c.set(String(h.id),k)}else if(f.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(f.event==="done")return u("done",typeof h.content=="string"&&h.content?h.content:s);if(f.event==="error")return u("error",s,Bp(h.error))}}return a.aborted?u("stopped",s):u("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?u("stopped",s):u("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function Bp(t){let e=String(t||"The agent could not answer.");return Ya(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function _a(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}});let r=(t.quickReplies??[]).slice(0,gs).map(s=>s.slice(0,xs));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,gs).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,xs)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*zp(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,`
|
|
15399
15649
|
`);let s;for(;(s=n.indexOf(`
|
|
15400
15650
|
|
|
15401
|
-
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let
|
|
15402
|
-
`))
|
|
15403
|
-
`))}}catch{}}}}finally{e.releaseLock()}}var
|
|
15651
|
+
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let u of i.split(`
|
|
15652
|
+
`))u.startsWith("event:")?l=u.slice(6).trim():u.startsWith("data:")&&c.push(u.slice(5).replace(/^ /,""));if(c.length)try{yield{event:l,data:JSON.parse(c.join(`
|
|
15653
|
+
`))}}catch{}}}}finally{e.releaseLock()}}var Lt=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}
|
|
15404
15654
|
data: ${JSON.stringify(s)}
|
|
15405
15655
|
|
|
15406
15656
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
15407
15657
|
|
|
15408
|
-
`)},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
|
|
15409
|
-
`)){let n=
|
|
15410
|
-
`).map(
|
|
15658
|
+
`)},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 ys(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=qp(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:Ea(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Ea(t,e=120){for(let a of t.split(`
|
|
15659
|
+
`)){let n=ws(a);if(n)return Sa(n,e)}return""}function qp(t,e=120){let a=t.split(`
|
|
15660
|
+
`).map(ws).filter(Boolean);return a.length?Sa(a[a.length-1],e):""}function ws(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Sa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Rt=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function $t(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var bs=140;function Pt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Ea(r||"",bs-18)||"something went wrong."}`:Ea(n,bs)||"Answered.";return{deviceId:t,title:Sa(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var _s=8e3,Up=/^[A-Za-z0-9_.:-]{1,64}$/,Ce=new Map,Ta=new Map,Ia=new Rt;function Es(){return Ia}async function Ss(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??Ia;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await Ts(o)});let i=o.store();if(!i)return D(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),D(e,200,{conversations:ys(r.id,Xp(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),D(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return D(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let u=i.get(r.id,decodeURIComponent(l[1]));if(!u)return D(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,u.id);let p=Ce.get(u.id);return D(e,200,{...u,running:!!p,...p?{partial:{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let u=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=u&&Ce.get(u.id);if(!u||!p)return D(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,u.id),As(e);let{id:f,title:h,node:k,nodeName:E,agent:S,agentName:g}=u;return e.write(Aa("conversation",{id:f,title:h,node:k,nodeName:E,agent:S,agentName:g})),e.write(Aa("resume",{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return D(e,404,{error:"not found"});let c;try{c=await gt(t,64*1024)}catch(u){return D(e,400,{error:u.message})}if(a==="/api/app/chat/stop"){let u=i.get(r.id,String(c.conversationId??""));if(!u)return D(e,404,{error:"no such conversation"});let p=Ce.get(u.id);return p?(p.ac.abort(),Ca(u,o,r.name),D(e,200,{stopped:!0})):await Ca(u,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await Gp(e,c,r,i,o),!0}function Wp(t,e,a){let n=He(e.url),r=new Set,o=[];for(let s of t){let i=He(s.url),l=a.find(p=>He(p.peerUrl)===i);l&&r.add(l.peer);let c=i===n,u=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:u.map(p=>{let f=Array.isArray(p.runningTasks)?p.runningTasks.length:0;return{id:p.id,name:p.name||p.id,busy:f>0||(p.active??0)>0,running:f,...p.color?{color:p.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Ts(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Wp(e.nodes,t.daemon,a)}async function Gp(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>_s){D(t,400,{error:`message must be 1\u2013${_s} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let k=typeof e.node=="string"?e.node:"",E=typeof e.agent=="string"?e.agent:"";if(!Up.test(E)){D(t,400,{error:"pick an agent"});return}let S=(await Ts(r)).find(d=>d.target===k);if(!S){D(t,400,{error:`unknown node "${k}"`});return}if(!S.online){D(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===E);if(!g){D(t,400,{error:`no agent "${E}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:E,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Ce.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new Lt(r.orphanLimitMs??18e5);Ce.set(s.id,i);let{id:l,title:c,node:u,nodeName:p,agent:f,agentName:h}=s;Ta.set(l,{id:l,deviceId:a.id,title:c,agent:f,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),As(t),t.write(Aa("conversation",{id:l,title:c,node:u,nodeName:p,agent:f,agentName:h})),i.attach(t);try{let k=e.spoken===!0,E=await vs(r.daemon,{node:u,agent:f,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(m,x)=>i.broadcast(m,x));i.orphaned&&(E.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ca(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:E.text,status:E.status,at:Date.now(),...E.error?{error:E.error}:{},...E.ui?{ui:E.ui}:{},...E.tools.length?{tools:E.tools}:{}},E.files)??[];i.broadcast("final",{status:E.status,content:E.text,...E.error?{error:E.error}:{},...E.ui?{ui:E.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:E.status,attached:g,appOpen:(r.presence??Ia).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&$t(d)&&r.notifyFinish(Pt(a.id,s,E.status,E.text,E.error)).catch(()=>{})}finally{Ce.delete(l),Ta.delete(l),i.finish()}}function Xp(){let t=[];for(let[e,a]of Ta){let n=Ce.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function As(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Aa(t,e){return`event: ${t}
|
|
15411
15661
|
data: ${JSON.stringify(e)}
|
|
15412
15662
|
|
|
15413
|
-
`}async function va(t,e,a){try{let n=Oe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Oe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Oe(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Oe(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as hp}from"stream";var gp=/^\/api\/app\/files\/([^/]+)$/,xp=15e3;async function as(t,e,a,n,r,o){let s=gp.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ae(e,405,{error:"GET only"});let i=o.store();if(!i)return Ae(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return Ae(e,404,{error:"no such file"});let p=await vp(c.node,o);if(!p)return Ae(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),xp),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${on}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Ae(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return Ae(e,f,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let w=Number(h.headers.get("content-length")||0);if(w>le.bytes)return u.abort(),Ae(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...sn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(w)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let E=0,g=hp.fromWeb(h.body);return g.on("data",d=>{E+=d.length,E>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function vp(t,e){if(t==="local")return{url:ts(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ts(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ts(t){return t.replace(/\/+$/,"")}function Ae(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var rs=8e3;async function os(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return J(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!hn(h))return J(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let w=fn(t.headers["x-audio-duration-ms"]);if(w)return t.resume(),J(e,w.status,{error:w.error});let _=await Re(t,mn.bytes);if(!_)return J(e,413,{error:gn()});if(!_.length)return J(e,400,{error:"The recording is empty."});let E={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return ns(e,o.daemon,"/voice/transcribe",_,E,18e4)}let s,i=await Re(t,64*1024);if(!i)return J(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return J(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return J(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return J(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,rs):"";if(!p.trim())return J(e,400,{error:"text is required"});if(!yp(c.messages,p))return J(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return ns(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function ns(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(bp(l)?.endpoints)?J(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return J(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function bp(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function yp(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===rs&&a.content.startsWith(e)))}var wp=new Set(["ring","offer","answer","ice","hangup"]),At=/^[A-Za-z0-9_-]{4,64}$/,kp=128*1024;async function ss(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return $(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return $(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return $(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=He(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>He(String(h?.name??""))!==p),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return $(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,kp);if(!l)return $(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=_p(c,r.nodeName);if(typeof p=="string")return $(e,400,{error:p});let u=is(p.to);if(u&&p.kind==="ring"){let m=await We(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return $(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return $(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return At.test(l)?Sp(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):$(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,4096);if(!l)return $(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!At.test(p))return $(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await We(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return $(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return $(e,405,{error:"GET"});let l=await We(o,s,"GET","/calls/asking");if(l.status>=300)return $(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return $(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return $(e,405,{error:"POST"});let l=await We(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return $(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!At.test(l))return $(e,400,{error:"callId is required"});let c=await We(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return $(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return $(e,404,{error:"not found"})}function is(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function We(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 _p(t,e){let a=String(t?.kind??"");if(!wp.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!At.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:")&&!is(r))return"to must be bot:<agent id> for an agent";if(He(r)===He(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function Sp(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?$(e,503,{error:"Calls are off on this computer."}):$(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ep={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},Ct=class{constructor(e=Ep,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},Tp="That code didn't work. Check it, or run agentx app pair for a new one.",Ap=400;async function ls(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await Ee(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await Cp(a,e.minMs??Ap),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:Tp}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function Cp(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function ya(t,e){if(!t)return"absent";let a=en(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var It=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 ds(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=cs(t.headers["sec-fetch-mode"]),n.site=cs(t.headers["sec-fetch-site"]),n}function cs(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var ps=`
|
|
15663
|
+
`}async function Ca(t,e,a){try{let n=He(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=He(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>He(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 He(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Kp}from"stream";var Jp=/^\/api\/app\/files\/([^/]+)$/,Vp=15e3;async function Is(t,e,a,n,r,o){let s=Jp.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ie(e,405,{error:"GET only"});let i=o.store();if(!i)return Ie(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 Ie(e,404,{error:"no such file"});let u=await Yp(c.node,o);if(!u)return Ie(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let p=new AbortController;e.on("close",()=>p.abort());let f=setTimeout(()=>p.abort(),Vp),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${u.url}${hn}?${d}`,{method:n,headers:{...u.token?{Authorization:`Bearer ${u.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return Ie(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return Ie(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return p.abort(),Ie(e,413,{error:"the file is too large"});let E=h.headers.get("content-range");if(e.writeHead(h.status,{...gn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&E?{"Content-Range":E}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Kp.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 Yp(t,e){if(t==="local")return{url:Cs(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Cs(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Cs(t){return t.replace(/\/+$/,"")}function Ie(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 Ls=8e3;async function Rs(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return V(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!En(h))return V(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=_n(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),V(e,k.status,{error:k.error});let E=await Re(t,kn.bytes);if(!E)return V(e,413,{error:Sn()});if(!E.length)return V(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 Ms(e,o.daemon,"/voice/transcribe",E,S,18e4)}let s,i=await Re(t,64*1024);if(!i)return V(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return V(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return V(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return V(e,404,{error:"no such conversation"});let u=typeof s?.text=="string"?s.text.slice(0,Ls):"";if(!u.trim())return V(e,400,{error:"text is required"});if(!Zp(c.messages,u))return V(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${c.agentName||c.agent}: ${u}`:u,f={agent:c.agent,text:p,...c.node!=="local"?{peer:c.node}:{}};return Ms(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function Ms(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(Qp(l)?.endpoints)?V(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 V(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function V(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function Qp(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Zp(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Ls&&a.content.startsWith(e)))}var eu=new Set(["ring","offer","answer","ice","hangup"]),jt=/^[A-Za-z0-9_-]{4,64}$/,tu=128*1024;async function $s(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return $(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return $(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return $(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),u=qe(r.nodeName),p=(Array.isArray(c.peers)?c.peers:[]).filter(h=>qe(String(h?.name??""))!==u),f=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return $(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:p,agents:f,camera:c.camera??null})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,tu);if(!l)return $(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let u=au(c,r.nodeName);if(typeof u=="string")return $(e,400,{error:u});let p=Ps(u.to);if(p&&u.kind==="ring"){let f=await Xe(o,s,"POST","/webrtc/camera/watch",{callId:u.callId,agentId:p});return $(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(u),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return $(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.status}.`})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return jt.test(l)?nu(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):$(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,4096);if(!l)return $(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let u=String(c?.callId??"");if(!jt.test(u))return $(e,400,{error:"callId is required"});let p=typeof c?.note=="string"?c.note:"",f=await Xe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(u)}/look`,{note:p},18e4);return $(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return $(e,405,{error:"GET"});let l=await Xe(o,s,"GET","/calls/asking");if(l.status>=300)return $(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(u=>({id:u.id,agentId:u.agentId,reason:u.reason,createdAt:u.createdAt}));return $(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Xe(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return $(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!jt.test(l))return $(e,400,{error:"callId is required"});let c=await Xe(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return $(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return $(e,404,{error:"not found"})}function Ps(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Xe(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 au(t,e){let a=String(t?.kind??"");if(!eu.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!jt.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:")&&!Ps(r))return"to must be bot:<agent id> for an agent";if(qe(r)===qe(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 nu(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?$(e,503,{error:"Calls are off on this computer."}):$(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var js=`
|
|
15414
15664
|
(function () {
|
|
15415
15665
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
15416
15666
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -15654,7 +15904,7 @@ data: ${JSON.stringify(e)}
|
|
|
15654
15904
|
setInterval(refresh, 15000);
|
|
15655
15905
|
refresh();
|
|
15656
15906
|
})();
|
|
15657
|
-
`;var
|
|
15907
|
+
`;var Os=`
|
|
15658
15908
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
15659
15909
|
.fx-head h2 { margin: 4px 0 0; }
|
|
15660
15910
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -15711,7 +15961,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15711
15961
|
}
|
|
15712
15962
|
.fx-error:empty { display: none; }
|
|
15713
15963
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
15714
|
-
`;var
|
|
15964
|
+
`;var Ns=`
|
|
15715
15965
|
(function () {
|
|
15716
15966
|
var panel = document.getElementById('panel-alerts');
|
|
15717
15967
|
if (!panel) return;
|
|
@@ -15892,7 +16142,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15892
16142
|
refresh();
|
|
15893
16143
|
loadRecent();
|
|
15894
16144
|
})();
|
|
15895
|
-
`;var
|
|
16145
|
+
`;var Ds=`
|
|
15896
16146
|
(function () {
|
|
15897
16147
|
var panel = document.getElementById('panel-alerts');
|
|
15898
16148
|
if (!panel) return;
|
|
@@ -16005,7 +16255,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16005
16255
|
}
|
|
16006
16256
|
load();
|
|
16007
16257
|
})();
|
|
16008
|
-
`;var
|
|
16258
|
+
`;var Hs=`
|
|
16009
16259
|
(function () {
|
|
16010
16260
|
var panel = document.getElementById('panel-chat');
|
|
16011
16261
|
var V = window.AXChatView;
|
|
@@ -16277,7 +16527,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16277
16527
|
var last = recall('ax-chat-conv');
|
|
16278
16528
|
if (!fromHash() && last) openConversation(last);
|
|
16279
16529
|
})();
|
|
16280
|
-
`;var
|
|
16530
|
+
`;var Bs=`
|
|
16281
16531
|
window.AXChatView = (function () {
|
|
16282
16532
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
16283
16533
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -16558,7 +16808,7 @@ window.AXChatView = (function () {
|
|
|
16558
16808
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
16559
16809
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
16560
16810
|
})();
|
|
16561
|
-
`;var
|
|
16811
|
+
`;var zs=`
|
|
16562
16812
|
window.AXChatSheets = function (o) {
|
|
16563
16813
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
16564
16814
|
function loadPicker() {
|
|
@@ -16604,7 +16854,7 @@ window.AXChatSheets = function (o) {
|
|
|
16604
16854
|
});
|
|
16605
16855
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
16606
16856
|
};
|
|
16607
|
-
`;var
|
|
16857
|
+
`;var qs=`
|
|
16608
16858
|
window.AXChatLog = function (o) {
|
|
16609
16859
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
16610
16860
|
function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
|
|
@@ -16667,7 +16917,7 @@ window.AXChatLog = function (o) {
|
|
|
16667
16917
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
16668
16918
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
16669
16919
|
};
|
|
16670
|
-
`;var
|
|
16920
|
+
`;var Fs=`
|
|
16671
16921
|
(function () {
|
|
16672
16922
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
16673
16923
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -16817,7 +17067,7 @@ window.AXChatLog = function (o) {
|
|
|
16817
17067
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
16818
17068
|
poll();
|
|
16819
17069
|
})();
|
|
16820
|
-
`;var
|
|
17070
|
+
`;var Us=`
|
|
16821
17071
|
.cs { margin: 0 -2px; }
|
|
16822
17072
|
.cs[hidden] { display: none; }
|
|
16823
17073
|
.cs-list {
|
|
@@ -16873,7 +17123,7 @@ window.AXChatLog = function (o) {
|
|
|
16873
17123
|
@media (prefers-reduced-motion: reduce) {
|
|
16874
17124
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
16875
17125
|
}
|
|
16876
|
-
`;function
|
|
17126
|
+
`;function Ws(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 Gs(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Xs=`
|
|
16877
17127
|
body { height: 100dvh; }
|
|
16878
17128
|
main { min-height: 0; }
|
|
16879
17129
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -16983,7 +17233,7 @@ main { min-height: 0; }
|
|
|
16983
17233
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
16984
17234
|
}
|
|
16985
17235
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
16986
|
-
`;var
|
|
17236
|
+
`;var Ks=`
|
|
16987
17237
|
window.AXOrb = (function () {
|
|
16988
17238
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
16989
17239
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -17114,7 +17364,7 @@ window.AXOrb = (function () {
|
|
|
17114
17364
|
}
|
|
17115
17365
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
17116
17366
|
})();
|
|
17117
|
-
`;var
|
|
17367
|
+
`;var Js=`
|
|
17118
17368
|
window.AXVoiceIO = (function () {
|
|
17119
17369
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
17120
17370
|
var ac = null, playing = null;
|
|
@@ -17232,7 +17482,7 @@ window.AXVoiceIO = (function () {
|
|
|
17232
17482
|
|
|
17233
17483
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
17234
17484
|
})();
|
|
17235
|
-
`;var
|
|
17485
|
+
`;var Vs=`
|
|
17236
17486
|
(function () {
|
|
17237
17487
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
17238
17488
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -17440,7 +17690,7 @@ window.AXVoiceIO = (function () {
|
|
|
17440
17690
|
idle();
|
|
17441
17691
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
17442
17692
|
})();
|
|
17443
|
-
`;var
|
|
17693
|
+
`;var Ys=`
|
|
17444
17694
|
.vx {
|
|
17445
17695
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
17446
17696
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -17476,7 +17726,7 @@ window.AXVoiceIO = (function () {
|
|
|
17476
17726
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
17477
17727
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
17478
17728
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
17479
|
-
`;var
|
|
17729
|
+
`;var Qs=`
|
|
17480
17730
|
<main class="card">
|
|
17481
17731
|
<h1>This phone isn't paired</h1>
|
|
17482
17732
|
<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>
|
|
@@ -17490,7 +17740,7 @@ window.AXVoiceIO = (function () {
|
|
|
17490
17740
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
17491
17741
|
</form>
|
|
17492
17742
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
17493
|
-
</main>`,
|
|
17743
|
+
</main>`,Zs=`
|
|
17494
17744
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
17495
17745
|
.pair-form label { font-weight: 600; }
|
|
17496
17746
|
.pair-form input {
|
|
@@ -17512,7 +17762,7 @@ window.AXVoiceIO = (function () {
|
|
|
17512
17762
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
17513
17763
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
17514
17764
|
}
|
|
17515
|
-
`,
|
|
17765
|
+
`,ei=`
|
|
17516
17766
|
(function () {
|
|
17517
17767
|
var form = document.getElementById('pair-form');
|
|
17518
17768
|
var input = document.getElementById('pair-code');
|
|
@@ -17604,7 +17854,7 @@ window.AXVoiceIO = (function () {
|
|
|
17604
17854
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
17605
17855
|
}
|
|
17606
17856
|
})();
|
|
17607
|
-
`;
|
|
17857
|
+
`;var ti=`
|
|
17608
17858
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
17609
17859
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
17610
17860
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -17613,7 +17863,7 @@ window.AXVoiceIO = (function () {
|
|
|
17613
17863
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
17614
17864
|
</div>
|
|
17615
17865
|
<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>
|
|
17616
|
-
</div>`,
|
|
17866
|
+
</div>`,ai=`
|
|
17617
17867
|
.pair-form .scan-btn {
|
|
17618
17868
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
17619
17869
|
}
|
|
@@ -17642,7 +17892,7 @@ window.AXVoiceIO = (function () {
|
|
|
17642
17892
|
}
|
|
17643
17893
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
17644
17894
|
body.scanning { overflow: hidden; }
|
|
17645
|
-
`,
|
|
17895
|
+
`,ni=`
|
|
17646
17896
|
(function () {
|
|
17647
17897
|
var openBtn = document.getElementById('scan-btn');
|
|
17648
17898
|
var box = document.getElementById('scan');
|
|
@@ -17808,7 +18058,7 @@ body.scanning { overflow: hidden; }
|
|
|
17808
18058
|
document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
|
|
17809
18059
|
window.addEventListener('pagehide', close);
|
|
17810
18060
|
})();
|
|
17811
|
-
`;var
|
|
18061
|
+
`;var Ma=`
|
|
17812
18062
|
.cam { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; background: var(--ax-bg); }
|
|
17813
18063
|
.cam[hidden] { display: none; }
|
|
17814
18064
|
.cam-live {
|
|
@@ -17850,7 +18100,7 @@ body.scanning { overflow: hidden; }
|
|
|
17850
18100
|
border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
|
|
17851
18101
|
}
|
|
17852
18102
|
.cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
|
|
17853
|
-
`;var
|
|
18103
|
+
`;var ri='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',oi=`
|
|
17854
18104
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
17855
18105
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
17856
18106
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -17875,7 +18125,7 @@ body.scanning { overflow: hidden; }
|
|
|
17875
18125
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
17876
18126
|
</div>
|
|
17877
18127
|
</div>
|
|
17878
|
-
</div>`,
|
|
18128
|
+
</div>`,si=`
|
|
17879
18129
|
(function () {
|
|
17880
18130
|
var btn = document.getElementById('cam-btn');
|
|
17881
18131
|
var sheet = document.getElementById('cam');
|
|
@@ -18144,7 +18394,7 @@ body.scanning { overflow: hidden; }
|
|
|
18144
18394
|
});
|
|
18145
18395
|
window.addEventListener('pagehide', function () { stop(); });
|
|
18146
18396
|
})();
|
|
18147
|
-
`;var
|
|
18397
|
+
`;var ii=`
|
|
18148
18398
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
18149
18399
|
<div class="cam-askbar-text">
|
|
18150
18400
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -18154,7 +18404,7 @@ body.scanning { overflow: hidden; }
|
|
|
18154
18404
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
18155
18405
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
18156
18406
|
</div>
|
|
18157
|
-
</div>`,
|
|
18407
|
+
</div>`,li=`
|
|
18158
18408
|
.cam-askbar[hidden] { display: none; }
|
|
18159
18409
|
.cam-askbar {
|
|
18160
18410
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -18169,7 +18419,7 @@ body.scanning { overflow: hidden; }
|
|
|
18169
18419
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
18170
18420
|
}
|
|
18171
18421
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
18172
|
-
`,
|
|
18422
|
+
`,ci=`
|
|
18173
18423
|
(function () {
|
|
18174
18424
|
var bar = document.getElementById('cam-ask-bar');
|
|
18175
18425
|
if (!bar) return;
|
|
@@ -18239,8 +18489,8 @@ body.scanning { overflow: hidden; }
|
|
|
18239
18489
|
setInterval(poll, 5000);
|
|
18240
18490
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
18241
18491
|
})();
|
|
18242
|
-
`;function
|
|
18243
|
-
${
|
|
18492
|
+
`;function di(t,e){let a={width:1280,height:720,frameRate:15},n=t||a;return{audio:!1,video:{facingMode:{ideal:e==="user"?"user":"environment"},width:{ideal:n.width||a.width},height:{ideal:n.height||a.height},frameRate:{ideal:n.frameRate||a.frameRate}}}}function pi(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 La=`
|
|
18493
|
+
${z({afterUnauthorized:fr})}
|
|
18244
18494
|
var CACHE = 'agentx-app-v3';
|
|
18245
18495
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
18246
18496
|
self.addEventListener('install', function (e) {
|
|
@@ -18331,7 +18581,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
18331
18581
|
return self.clients.openWindow(target);
|
|
18332
18582
|
}));
|
|
18333
18583
|
});
|
|
18334
|
-
`;var
|
|
18584
|
+
`;var ru="<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 Ra(t){return`<meta charset="utf-8">
|
|
18335
18585
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
18336
18586
|
<meta name="theme-color" content="#2979FF">
|
|
18337
18587
|
<meta name="referrer" content="no-referrer">
|
|
@@ -18342,55 +18592,55 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
18342
18592
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
18343
18593
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
18344
18594
|
<title>${t}</title>
|
|
18345
|
-
${
|
|
18346
|
-
<style>${
|
|
18595
|
+
${ru}
|
|
18596
|
+
<style>${pt}${iu}</style>`}var ui=[{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 mi(){let t=ui.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}">${a.label}</button>`).join(""),e=ui.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
18347
18597
|
<h2>${a.label}</h2>
|
|
18348
18598
|
<p class="soon">${a.soon}</p>
|
|
18349
18599
|
</section>`).join("");return`<!doctype html>
|
|
18350
18600
|
<html lang="en">
|
|
18351
|
-
<head>${
|
|
18601
|
+
<head>${Ra("AgentX")}<style>${lu}${Os}${Xs}${Us}${Ys}${Ma}${li}</style></head>
|
|
18352
18602
|
<body>
|
|
18353
18603
|
<header class="bar">
|
|
18354
18604
|
<div>
|
|
18355
18605
|
<h1>AgentX</h1>
|
|
18356
18606
|
<p id="who" class="who">Connecting\u2026</p>
|
|
18357
18607
|
</div>
|
|
18358
|
-
<div class="bar-btns">${
|
|
18608
|
+
<div class="bar-btns">${ri}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
|
|
18359
18609
|
</header>
|
|
18360
18610
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
18361
|
-
${
|
|
18611
|
+
${ii}
|
|
18362
18612
|
<main>${e}</main>
|
|
18363
18613
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
18364
|
-
${
|
|
18365
|
-
<script>${
|
|
18366
|
-
<script>${
|
|
18367
|
-
<script>${
|
|
18368
|
-
<script>${
|
|
18369
|
-
<script>${
|
|
18370
|
-
<script>${
|
|
18371
|
-
<script>${bs}</script>
|
|
18372
|
-
<script>${U({cameraConstraints:Us,shareClock:Ws})}${Bs}</script>
|
|
18614
|
+
${oi}
|
|
18615
|
+
<script>${ou}</script>
|
|
18616
|
+
<script>${js}</script>
|
|
18617
|
+
<script>${Ns}</script>
|
|
18618
|
+
<script>${Ds}</script>
|
|
18619
|
+
<script>${z({markdownToHtml:Pn})}${Bs}${qs}${zs}${Hs}</script>
|
|
18620
|
+
<script>${z({queueSpeech:Ws,nextSpeech:Gs})}${Ks}${Js}${Vs}</script>
|
|
18373
18621
|
<script>${Fs}</script>
|
|
18622
|
+
<script>${z({cameraConstraints:di,shareClock:pi})}${si}</script>
|
|
18623
|
+
<script>${ci}</script>
|
|
18374
18624
|
</body>
|
|
18375
|
-
</html>`}function
|
|
18625
|
+
</html>`}function fi(){return`<!doctype html>
|
|
18376
18626
|
<html lang="en">
|
|
18377
|
-
<head>${
|
|
18627
|
+
<head>${Ra("Pair \xB7 AgentX")}</head>
|
|
18378
18628
|
<body>
|
|
18379
18629
|
<main class="card">
|
|
18380
18630
|
<h1>Pairing this phone\u2026</h1>
|
|
18381
18631
|
<p id="msg" role="status">One moment.</p>
|
|
18382
18632
|
</main>
|
|
18383
|
-
<script>${
|
|
18633
|
+
<script>${su}</script>
|
|
18384
18634
|
</body>
|
|
18385
|
-
</html>`}function
|
|
18635
|
+
</html>`}function hi(){return`<!doctype html>
|
|
18386
18636
|
<html lang="en">
|
|
18387
|
-
<head>${
|
|
18388
|
-
<body>${
|
|
18389
|
-
<script>${
|
|
18390
|
-
<script>${
|
|
18391
|
-
<script>${
|
|
18637
|
+
<head>${Ra("Not paired \xB7 AgentX")}<style>${Zs}${ai}</style></head>
|
|
18638
|
+
<body>${Qs}${ti}
|
|
18639
|
+
<script>${z({mayBounce:hr,formatPairInput:kt,parsePairScan:gr})}</script>
|
|
18640
|
+
<script>${ei}</script>
|
|
18641
|
+
<script>${ni}</script>
|
|
18392
18642
|
</body>
|
|
18393
|
-
</html>`}function
|
|
18643
|
+
</html>`}function gi(){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 ou=`
|
|
18394
18644
|
(function () {
|
|
18395
18645
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
18396
18646
|
function select(tab, focus, keepHash) {
|
|
@@ -18460,7 +18710,7 @@ ${Hs}
|
|
|
18460
18710
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
18461
18711
|
}
|
|
18462
18712
|
})();
|
|
18463
|
-
`,
|
|
18713
|
+
`,su=`
|
|
18464
18714
|
(function () {
|
|
18465
18715
|
var msg = document.getElementById('msg');
|
|
18466
18716
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -18477,7 +18727,7 @@ ${Hs}
|
|
|
18477
18727
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
18478
18728
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
18479
18729
|
})();
|
|
18480
|
-
`,
|
|
18730
|
+
`,iu=`
|
|
18481
18731
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
18482
18732
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
18483
18733
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -18489,7 +18739,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
18489
18739
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
18490
18740
|
.muted { color: var(--ax-text-2); }
|
|
18491
18741
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
18492
|
-
|
|
18742
|
+
`,lu=`
|
|
18493
18743
|
body { display: flex; flex-direction: column; }
|
|
18494
18744
|
.bar {
|
|
18495
18745
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -18527,8 +18777,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
18527
18777
|
}
|
|
18528
18778
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
18529
18779
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
18530
|
-
`;var
|
|
18531
|
-
`;
|
|
18780
|
+
`;var Ot="agentx_app",pu=400*86400,uu=new xt,mu=new Ee;async function xi(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new W;if(n==="GET"){if(a==="/app/manifest.webmanifest")return he(e,200,"application/manifest+json",gi());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),he(e,200,"text/javascript; charset=utf-8",La);if(a==="/app/icon-192.png")return he(e,200,"image/png",je(192),"public, max-age=86400");if(a==="/app/icon-512.png")return he(e,200,"image/png",je(512),"public, max-age=86400");if(a==="/app/pair")return he(e,200,"text/html; charset=utf-8",fi());if(a==="/app/qr.js"){let i=fu();return i?he(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Me(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=$a(Je(t),o);return i?(e.setHeader("Set-Cookie",Pa(Je(t))),Me(e,200,{device:i.name})):Me(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Kn(t,{codes:r.pairCodes??new ht,limiter:r.pairLimiter??uu,verify:l=>$a(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Pa(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Me(e,i.status,i.body)}let s=$a(hu(t),o);if(!s){let i=Je(t);return(r.rejectLog??mu).record(a.slice(0,120),wt(t,Pe(ja(t,Ot),o),i?Pe(i,o):null)),a==="/app"?he(e,401,"text/html; charset=utf-8",hi()):Me(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=ja(t,Ot);return i&&!Je(t)&&e.setHeader("Set-Cookie",Pa(i)),he(e,200,"text/html; charset=utf-8",mi())}return n==="GET"&&a==="/api/app/me"?Me(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Xn(t,e,a,n,s.name,r.fleet)||r.push&&await ps(t,e,a,n,s,r.push)||r.announce&&await fs(t,e,a,n,s,r.announce)||r.chat&&await Ss(t,e,a,n,s,r.chat)||r.chat&&await Is(t,e,a,n,s,r.chat)||r.voice&&await Rs(t,e,a,n,s,r.voice)||r.camera&&await $s(t,e,a,n,r.camera)?!0:Me(e,404,{error:"not found"})}var Ke;function fu(){if(Ke!==void 0)return Ke;try{let t=du(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
18781
|
+
`;Ke=Buffer.concat([Buffer.from(a),cu(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ke=null}return Ke}function $a(t,e){if(!t)return null;let a=e.verify(t);return a&&we(a,"app")?a:null}function Pa(t){return`${Ot}=${t}; Path=/; Max-Age=${pu}; HttpOnly; Secure; SameSite=Lax`}function hu(t){return Je(t)??ja(t,Ot)}function Je(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ja(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 he(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Me(t,e,a){return he(t,e,"application/json",JSON.stringify(a))}import{randomBytes as vi}from"crypto";var Le={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},gu=/^[a-f0-9]{32}$/,xu=/^c[a-z0-9]{8,32}$/,vu=/^#[0-9a-fA-F]{6}$/;function Oa(t){return xu.test(t)}var Ve=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
18532
18782
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
18533
18783
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
18534
18784
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -18541,39 +18791,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
18541
18791
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
18542
18792
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
18543
18793
|
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 (
|
|
18544
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return
|
|
18545
|
-
(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(!
|
|
18794
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Oa(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)}${vi(4).toString("hex")}`,{color:s,...i}=a,l=s&&vu.test(s)?s:void 0,c={id:o,title:yu(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
18795
|
+
(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(!Oa(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(bu);return{...bi(n),messages:r}}list(e,a=Le.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
18546
18796
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
18547
18797
|
(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
|
|
18548
|
-
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{...
|
|
18798
|
+
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{...bi(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Oa(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,
|
|
18549
18799
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
18550
18800
|
FROM app_chat_conversations c
|
|
18551
18801
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
18552
18802
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
18553
|
-
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>
|
|
18803
|
+
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>Le.content?n.content.slice(0,Le.content)+`
|
|
18554
18804
|
|
|
18555
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,
|
|
18556
|
-
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),
|
|
18557
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let
|
|
18558
|
-
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,
|
|
18559
|
-
(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(!
|
|
18805
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Le.toolsPerMessage),l=[];for(let f of r){if(l.length>=Le.filesPerMessage)break;let h=f.filename.trim(),k=tn(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let E=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:vi(16).toString("hex"),name:E,mime:k.mime,kind:k.kind,path:h})}let c=l.map(f=>({id:f.id,name:f.name,mime:f.mime,kind:f.kind})),u=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
18806
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,c.length?JSON.stringify(c):null,n.at),p=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
|
|
18807
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let f of l)p.run(f.id,a,Number(u.lastInsertRowid),f.path,f.name,f.mime,f.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
18808
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Le.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
|
|
18809
|
+
(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(!gu.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
18560
18810
|
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 = ?
|
|
18561
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,
|
|
18811
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Le.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 bi(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 bu(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 yu(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var wu=4e3,Na=100,ku=15,yi=t=>t.replace(/\/+$/,""),Nt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=wu){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,Na);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??ku)-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>=Na&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Na}); 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||yi(l)!==yi(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=_u(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let p=c.row.status,f=!!this.deps.finishAlerts?.(s),h={status:p,attached:!1,appOpen:this.deps.presence.open(s),enabled:f};return this.deps.notifyFinish&&$t(h)&&this.deps.notifyFinish(Pt(s,i,p,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function _u(t,e){let a=t.plain?{text:tt(t.text,!1),artifacts:[]}:et(t.text,le.perMessage,!1),{cleanText:n,ui:r}=nt(a.text),o=t.plain?void 0:_a(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Eu(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Eu(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Xa();function ub(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,Ou(h,t))}catch(k){console.error(` Board "${h.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Ye(process.cwd(),t.workflows.dir):void 0,c=new Qa(l?{baseDir:l}:void 0),u=new Za(l?{baseDir:l,nodeId:i}:{nodeId:i}),p=new en(l?{baseDir:l}:void 0);Lo(t),bn({business:t.business?.enabled===!0});let f=Su(async(h,k)=>{try{await Ru(h,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:u,workflowLayouts:p})}catch(E){y(k,500,{error:E.message||"internal error"})}});Zu(t).start(),f.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
18562
18812
|
Live dashboard: http://${h}:${n}
|
|
18563
18813
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
18564
18814
|
Kanban dashboard: http://${h}:${n}
|
|
18565
|
-
`),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var au=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function nu(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ln(t.headers)==="foreign"&&cn(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 Ys(t,e,r,o,{nodeName:a.config.node?.name,fleet:si(a.config),push:oi(a.config),announce:qo(a.config),chat:ii(a.config),voice:Eu(a.config),camera:Tu(a.config)}))return;if(o==="GET"&&au.has(r)&&Bn("page",r),o==="GET"&&r==="/"){let d=Rn();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ca({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ao({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ca({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await be(a.config);if(!d){y(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let k="";t.on("data",b=>k+=b),t.on("end",()=>v(k)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await be(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await xe(t):void 0,v=x?.node??f,k=v?d.find(I=>I.url===v):d[0];if(!k){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",S=await fetch(k.url+r+b,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,S.status,await S.json().catch(()=>({error:`HTTP ${S.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await xe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await be(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vn({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Jn({peers:H(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wn({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,f=setTimeout(()=>d.abort(),8e3);try{let x=Ka(await be(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await Xa(t)):void 0,S=await fetch(v.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,S.status,await S.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(_o({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Co({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Io({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mo({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mn({}));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(Ro({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:H(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lo({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Ln(t,e);return}if(o==="POST"&&r==="/api/setup"){await $n(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Pn(t,e);return}if(o==="GET"&&r==="/admin"){ir(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){_r(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){fr(t,e,H(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Mr(t,e,H(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Lu(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await ia(t,e,r,x=>ci(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),v=x.indexOf("::");if(v>0){let k=x.slice(0,v),b=x.slice(v+2),S=a.config.node?.id||a.config.node?.name||"local";if(k===S)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(I){let C=Ve(I.url.replace(/\/+$/,""),a.config);if(C){await ai(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let f=Ve(d,a.config);if(!f){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await ai(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Rr(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await $u(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-6EWW7NC2.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(jr({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Pr(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Or({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nr({peers:H(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await du(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 ao(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ia(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ro(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){io(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ne,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await lr(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,un()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Sr(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await hr(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await lo(t,e,r);return}if(r.startsWith("/api/admin/")){await cr(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(Yn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let f=Mu("web/"+d);try{let x=await Ru(f),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ne(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await Ne(a.config,{date:d,timezone:f});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(f,x,v,k)=>{let b=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(k,b)):x};try{let f=await be(a.config);y(e,200,await So(f,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,v,k,b)=>{let S=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(S)?Math.max(k,Math.min(b,S)):v};try{let x=await be(a.config);y(e,200,await To(x,{day:d,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,k]=[f.get("kind"),f.get("key")];if(!v||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await Eo(e,await be(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){xu(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!f||!x||!v){y(e,400,{error:"node, agent, task query params required"});return}await vu(t,e,a,f,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await wu(e,a,f,x,v,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!f||!x||v!=="cancel"&&v!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await ku(t,e,a,f,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await La(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await xe(t);try{let f=await Cu(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(!bu(t,e,[`agent:${d}`]))return;await yu(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ne,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await pu(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 La(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(S=>({name:S.name,url:S.url,token:S.token}))],v={flag:!1},k=[];t.on("close",()=>{v.flag=!0;for(let S of k)try{S.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
18815
|
+
`),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 Lu=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Ru(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(xn(t.headers)==="foreign"&&vn(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 Sr(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>a.config.people,db:()=>ye(),linkFor:(d,m)=>ur(d,m,{gitlab:a.config.channels.gitlab?.host})})||await xi(t,e,r,o,{nodeName:a.config.node?.name,fleet:Ti(a.config),push:Si(a.config),announce:hs(a.config),chat:Ai(a.config),voice:em(a.config),camera:tm(a.config)}))return;if(o==="GET"&&Lu.has(r)&&Zn("page",r),o==="GET"&&r==="/"){let d=Hn();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(wa({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(as({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wa({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await be(a.config);if(!d){y(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",b=>w+=b),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await be(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await ge(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",_=await fetch(w.url+r+b,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.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 ge(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,w)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await be(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,m.status,await m.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(cr({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lr({peers:H(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rr({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=nn(await be(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await an(t)):void 0,_=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,_.status,await _.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qo({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ns({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rs({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(os({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Dn({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ss({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers:H(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(is({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Bn(t,e);return}if(o==="POST"&&r==="/api/setup"){await zn(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await qn(t,e);return}if(o==="GET"&&r==="/admin"){Or(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Qr(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Fr(t,e,H(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}oo(t,e,H(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await im(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await ba(t,e,r,x=>Ii(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),b=x.slice(v+2),_=a.config.node?.id||a.config.node?.name||"local";if(w===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=Qe(I.url.replace(/\/+$/,""),a.config);if(C){await ki(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=Qe(d,a.config);if(!m){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await ki(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await so(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await lm(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-GS2ZHLWU.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(po({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await co(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(uo({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mo({peers:H(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await Hu(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 Ro(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ba(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Po(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){No(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new W,v=m?x.verify(m):null;if(!v||!we(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Nr(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,wn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Zr(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await Ur(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Do(t,e,r);return}if(r.startsWith("/api/admin/")){await Dr(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(Tr);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 m=om("web/"+d);try{let x=await sm(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Be(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),m=n.searchParams.get("timezone")||"UTC",x=await Be(a.config,{date:d,timezone:m});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let b=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(w,b)):x};try{let m=await be(a.config);y(e,200,await Zo(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){y(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,b)=>{let _=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(_)?Math.max(w,Math.min(b,_)):v};try{let x=await be(a.config);y(e,200,await ts(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("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 m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,b]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,b]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await es(e,await be(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Gu(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){y(e,400,{error:"node, agent, task query params required"});return}await Xu(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){y(e,400,{error:"node and agent query params required"});return}await Vu(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Yu(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await za(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();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 m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){y(e,m.status,{error:`HTTP ${m.status}`});return}y(e,200,await m.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ge(t);try{let m=await nm(a.config,d);y(e,200,m)}catch(m){y(e,502,{error:m.message||"draft failed"})}return}let u=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(u&&o==="POST"){let d=u[1];if(!Ku(t,e,[`agent:${d}`]))return;await Ju(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new W,v=m?x.verify(m):null;if(!v||!we(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Bu(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 za(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(_=>({name:_.name,url:_.url,token:_.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let _ of w)try{_.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
18566
18816
|
|
|
18567
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let
|
|
18817
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let _ of x)(async()=>{let I={Accept:"text/event-stream"};_.token&&(I.Authorization=`Bearer ${_.token}`);let C=new AbortController;w.push(C);try{let T=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:I,signal:C.signal});if(!T.ok||!T.body)return;let M=T.body.getReader(),P=new TextDecoder,j="";for(;!v.flag;){let{done:B,value:se}=await M.read();if(B)break;j+=P.decode(se,{stream:!0});let F;for(;(F=j.indexOf(`
|
|
18568
18818
|
|
|
18569
|
-
`))>=0;){let
|
|
18819
|
+
`))>=0;){let ae=j.slice(0,F);if(j=j.slice(F+2),v.flag)break;try{e.write(ae+`
|
|
18570
18820
|
|
|
18571
|
-
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),
|
|
18572
|
-
`;
|
|
18821
|
+
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),b=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(P=>({url:P.url,token:P.token}))],I=await Promise.all(_.map(async P=>{let j={};P.token&&(j.Authorization=`Bearer ${P.token}`);try{let B=new AbortController,se=setTimeout(()=>B.abort(),5e3);try{let F=await fetch(`${P.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:j,signal:B.signal});if(!F.ok)return[];let ae=await F.json();return Array.isArray(ae.runs)?ae.runs:[]}finally{clearTimeout(se)}}catch{return[]}})),C=new Map;for(let P of w)C.set(P.id,P);for(let P of I)for(let j of P)C.set(j.id,j);let T=Array.from(C.values()).sort((P,j)=>P.updatedAt<j.updatedAt?1:-1).slice(0,m),M=v?T.map(P=>ju(P)):T;y(e,200,{runs:M})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let d=decodeURIComponent(f[1]),m=a.workflowRuns.get(d);if(m){y(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let w={};v.token&&(w.Authorization=`Bearer ${v.token}`);let b=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:w});if(b.ok){y(e,200,await b.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${m}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,v)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await ge(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,w)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&cs(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let w=Jt(m);if(!w)return!0;let b=new W().verify(w);if(!b)return y(x,401,{error:"invalid or revoked token"}),!1;for(let _ of v)if(!we(b,_))return y(x,403,{error:`token missing scope: ${_}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let d=a.sources.get(k[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(E&&o==="GET"){let d=a.sources.get(E[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,m]=S,x=decodeURIComponent(m),v=a.boards.find(C=>C.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){y(e,503,{error:`board "${d}" source unavailable`});return}let b=await ge(t),_=v.columns.find(C=>C.id===b.to),I=v.columns.find(C=>C.id===b.from);if(!_){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await Pu(w,x,I,_),Da({actor:Ha(t),action:"move",boardId:d,itemId:x,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,v=a.boards.find(b=>b.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:b,totals:_}=await $u(v,w,n.searchParams);y(e,200,{columns:b,totals:_});return}if(o==="GET"&&x){try{let b=typeof w.getItem=="function"?await w.getItem(x):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&x){let b=await ge(t);try{let _=typeof w.updateItem=="function"?await w.updateItem(x,b):null;if(!_){y(e,501,{error:"update unsupported"});return}Da({actor:Ha(t),action:"update",boardId:d,itemId:x,payload:b}),y(e,200,_)}catch(_){y(e,502,{error:_.message})}return}if(o==="POST"&&!x){let b=await ge(t);if(!b.title){y(e,400,{error:"title required"});return}if(!w.capabilities.create||!w.create){y(e,400,{error:`source ${w.type} does not support create`});return}try{let _=await w.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});Da({actor:Ha(t),action:"create",boardId:d,itemId:_.id,payload:{title:b.title}}),y(e,201,_)}catch(_){y(e,502,{error:_.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 $u(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let m of t.columns)d[m.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),u=t.columns.some(d=>d.kind!=="closed"),p=t.columns.some(d=>d.kind==="closed"),f=u?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=p?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let d of t.columns)k[d.id]=[];let E=t.columns.find(d=>d.kind==="closed");for(let d of h)E&&k[E.id].push({...d,stage:E.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=Ua(d,S);if(!m)continue;let x=k[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(k))k[d]=k[d].filter(m=>m.assignee===i);for(let d of Object.keys(k))k[d].sort((m,x)=>{let v=(m.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let g=Object.fromEntries(Object.entries(k).map(([d,m])=>[d,m.length]));return{columns:k,totals:g}}async function Pu(t,e,a,n){let r=Wa(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 ju(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 Ou(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 Tn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Da(t){try{let e=Ye(process.cwd(),".agentx");_i(e)||Au(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
18822
|
+
`;Tu(Ye(e,"board-audit.jsonl"),a)}catch{}}function Ha(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Nu=2e3;async function Du(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",i=g=>{let d=new AbortController,m=setTimeout(()=>d.abort(),Nu),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let w=v.ok?await v.json().catch(()=>{}):void 0;return{ok:w!==void 0,json:async()=>w}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,u,p,f,h,k,E]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(p&&p.ok){let g=await p.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(f&&f.ok){let g=await f.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(k&&k.ok){let g=await k.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,sn.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(E&&E.ok){let g=await E.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Wu(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(u?.ok?await u.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Dt=null;function Hu(t){if(Dt)return Dt;let e=Ye(process.cwd(),".agentx/wiki");return Dt=ar({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Dt}async function Bt(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 Bu(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||q(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function be(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=q(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:q(a,l)})}let s=await Bt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:q(a,i.url)});return[...o.values()]}var zu=3e3,qu=6e3,Fu=5*6e4,Ba=new Map,Ht=new Map;function Be(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Ht.get(a);if(n)return n;let r=(async()=>{let o=await be(t,AbortSignal.timeout(zu)),s=await Promise.all(o.map(async i=>{let l=await Du(i.url,i.token,AbortSignal.timeout(qu),e);return e?l:Uu(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Ht.delete(a));return Ht.set(a,r),r}function Uu(t,e,a=Date.now()){if(e.reachable&&!e.error)return Ba.set(t,{node:e,at:a}),e;let n=Ba.get(t);return!n||a-n.at>Fu?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function mb(){Ba.clear(),Ht.clear()}function Wu(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 Gu(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}
|
|
18573
18823
|
data: ${JSON.stringify(c)}
|
|
18574
18824
|
|
|
18575
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await
|
|
18576
|
-
${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
|
|
18825
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Be(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 Xu(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await Bt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let E of k)i.add(E.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=q(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let u=new AbortController,p;try{p=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:u.signal})}catch(k){y(e,502,{error:k.message||"upstream connect failed"});return}if(!p.ok||!p.body){y(e,p.status||502,{error:`upstream HTTP ${p.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=p.body.getReader();(async()=>{try{for(;;){let{value:k,done:E}=await f.read();if(E)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{u.abort();try{e.end()}catch{}})}function Ku(t,e,a){let n=Jt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new W().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!we(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Ju(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 ge(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||{}}})}),u=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(u)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function Vu(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let p of e.config.dashboard.daemons)i.add(p.url.replace(/\/+$/,""));try{let p=await Bt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of p)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=q(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let u=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let p=await fetch(`${s}${u}`,{headers:c}),f=await p.text();t.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(p){y(t,502,{error:p.message||"upstream fetch failed"})}}async function Yu(t,e,a,n,r,o){await za(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function za(t,e,a,n,r){let o={};try{o=await ge(t)??{}}catch{}let s=await Ei(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Ei(t,e,a,n){let r=(c,u)=>({status:c,text:JSON.stringify(u),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 Bt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let u of c)s.add(u.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=q(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 Si(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=pn(e.keysFile);return{store:()=>{let r=ye();return r?new $n(r):null},publicKey:()=>un(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Ti(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Be(t,n),async nodePost(n,r,o){let s=await Ei(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=rt({root:process.cwd()}).items.map(wi)}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=Qe(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(wi)}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=ke(),u=await ot({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return u.ok?{status:200,body:{ok:!0,message:u.message}}:{status:409,body:{error:u.error}}}let l=Qe(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}function Ai(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=q(t.dashboard,e),n=Ti(t);return{store:()=>{let r=ye();return r?new Ve(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:Ka(process.cwd())??void 0},snapshot:()=>Be(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=>q(t.dashboard,r.replace(/\/+$/,"")),...Qu(t,e,a)}}function Qu(t,e,a){let n=Si(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}
|
|
18826
|
+
${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 Zu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>q(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Ai(t);return new Nt({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 Be(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:Es(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function em(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=ye();return a?new Ve(a):null},daemon:{url:e,token:q(t.dashboard,e)}}}function tm(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:q(t.dashboard,e)},nodeName:t.node.name}}function wi(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 am=`
|
|
18577
18827
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
18578
18828
|
|
|
18579
18829
|
Title pattern:
|
|
@@ -18605,16 +18855,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
18605
18855
|
Shape:
|
|
18606
18856
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
18607
18857
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
18608
|
-
`;async function
|
|
18858
|
+
`;async function nm(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):
|
|
18609
18859
|
- ${r.knownLabels.slice(0,60).join(`
|
|
18610
18860
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
18611
|
-
`),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:
|
|
18861
|
+
`),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:am}})});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 u=(c.content||"").toString(),p=rm(u);if(!p||typeof p.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+u.slice(0,400));let f=Array.isArray(p.labels)?p.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:p.title.trim(),description:(p.description||"").toString(),labels:f,assigneeUsername:typeof p.assigneeUsername=="string"?p.assigneeUsername:void 0,kind:typeof p.kind=="string"?p.kind:void 0,raw:u}}function rm(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 om(t){let e=Mu(Iu(import.meta.url));return Ye(e,t)}async function sm(t){return Cu(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ge(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 Ci(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:Ci(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 im(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await It(await Ii(r,a.config)))}async function Ii(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=va(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=Qe(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,u=setTimeout(()=>c.abort(),8e3);try{let p=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return p.ok?{nodeId:i.name||i.url,snap:await p.json()}:null}finally{clearTimeout(u)}}catch{return null}}));for(let i of s)i&&n.push(i);return Mo(n)}async function lm(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let p=process.env.HOME||"",f=[p&&`${p}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=f.find(k=>_i(k));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:f}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
|
|
18612
18862
|
|
|
18613
|
-
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=
|
|
18614
|
-
`))>=0;){let h=i.slice(0,
|
|
18863
|
+
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=p=>{i+=p.toString("utf8");let f;for(;(f=i.indexOf(`
|
|
18864
|
+
`))>=0;){let h=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
|
|
18615
18865
|
data: ${h.replace(/\n/g," ")}
|
|
18616
18866
|
|
|
18617
18867
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
18618
18868
|
|
|
18619
|
-
`)}catch{}},15e3),
|
|
18620
|
-
//# sourceMappingURL=board-dashboard-
|
|
18869
|
+
`)}catch{}},15e3),u=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",u),s.on("exit",u),s.on("error",u)}async function ki(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((p,f)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>p(Buffer.concat(h))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let u=t.headers["x-requested-with"];u&&(l["X-Requested-With"]=Array.isArray(u)?u[0]:u),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let p=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await p.arrayBuffer());e.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(p){y(e,502,{error:`proxy to peer failed: ${p?.message||p}`,target:r})}}function Qe(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Ci(n),token:n.dashboardToken||n.token}:null}export{Wu as applyAttachSessions,Du as fetchDaemonAgents,Ru as handleBoardRequest,mb as resetLiveCaches,be as resolveNodeTargets,ub as startBoardDashboard,Uu as withLastGood};
|
|
18870
|
+
//# sourceMappingURL=board-dashboard-65HGTFRC.js.map
|