agentix-cli 0.52.1 → 0.54.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-X6FGYBLX.js → App-VRTLAPRF.js} +2 -2
- package/dist/{ChatApp-XMUOXQ2M.js → ChatApp-YENWPZT4.js} +2 -2
- package/dist/{agent-KKVMU3VB.js → agent-HVUGHYBF.js} +2 -2
- package/dist/{board-dashboard-KETIFTBD.js → board-dashboard-3XJVYDB3.js} +729 -191
- package/dist/board-dashboard-3XJVYDB3.js.map +1 -0
- package/dist/chunk-2D3RYIDU.js +3 -0
- package/dist/chunk-2D3RYIDU.js.map +1 -0
- package/dist/{chunk-H7R3F2CO.js → chunk-2TJYZF4E.js} +2 -2
- package/dist/chunk-33QV5O6P.js +7 -0
- package/dist/chunk-33QV5O6P.js.map +1 -0
- package/dist/{chunk-MHBUAU2B.js → chunk-37EABIOJ.js} +2 -2
- package/dist/chunk-3RCFUIYR.js +29 -0
- package/dist/chunk-3RCFUIYR.js.map +1 -0
- package/dist/{chunk-B5UA3X6E.js → chunk-3W2KMI5O.js} +2 -2
- package/dist/{chunk-3IUU4YFI.js → chunk-4FFWNPFX.js} +5 -5
- package/dist/chunk-4FFWNPFX.js.map +1 -0
- package/dist/{chunk-7BQQWI4T.js → chunk-4HNHHKJF.js} +2 -2
- package/dist/chunk-6JHA3ZE6.js +1111 -0
- package/dist/chunk-6JHA3ZE6.js.map +1 -0
- package/dist/{chunk-76NNONUJ.js → chunk-BKDUCPZ3.js} +2 -2
- package/dist/{chunk-64UYAWAK.js → chunk-BMSPRUEJ.js} +33 -33
- package/dist/chunk-BMSPRUEJ.js.map +1 -0
- package/dist/{chunk-NKSCUCVZ.js → chunk-ENRJ2QEH.js} +2 -2
- package/dist/{chunk-AWRRBNWQ.js → chunk-HQMISQ7L.js} +2 -2
- package/dist/{chunk-E57WKMRR.js → chunk-KLDGJSR5.js} +2 -2
- package/dist/{ntfy-ZY2NPGBA.js → chunk-KZKDVIOE.js} +3 -3
- package/dist/chunk-KZKDVIOE.js.map +1 -0
- package/dist/{chunk-7NF45XCM.js → chunk-M67AN4J7.js} +2 -2
- package/dist/{chunk-WKTFP3SK.js → chunk-NO2HOK4B.js} +2 -2
- package/dist/chunk-QD6IICK7.js +2 -0
- package/dist/chunk-QD6IICK7.js.map +1 -0
- package/dist/{chunk-QDPLR3SB.js → chunk-QX4R5WY7.js} +2 -2
- package/dist/{chunk-QZ4M2KAC.js → chunk-QYHABRLM.js} +2 -2
- package/dist/{chunk-AKAM4BNC.js → chunk-TLFJVLVQ.js} +166 -160
- package/dist/chunk-TLFJVLVQ.js.map +1 -0
- package/dist/{chunk-YS3Z2Z64.js → chunk-UYMK3XNB.js} +44 -45
- package/dist/chunk-UYMK3XNB.js.map +1 -0
- package/dist/{chunk-7M7VJMGP.js → chunk-WLRHL2P7.js} +2 -2
- package/dist/chunk-WWMFNLKD.js +10 -0
- package/dist/chunk-WWMFNLKD.js.map +1 -0
- package/dist/{chunk-YPPTPBBV.js → chunk-XWU7O3S5.js} +2 -2
- package/dist/{chunk-XOUIZBAQ.js → chunk-ZOJUHPD5.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-N4XQEAVL.js +2 -0
- package/dist/{compaction-NWPBPWY2.js → compaction-H5U32UU6.js} +2 -2
- package/dist/{config-FGCJVXYX.js → config-KHKIY6LI.js} +2 -2
- package/dist/config-mutator-ZZKFQ7HJ.js +2 -0
- package/dist/doctor-QICAXIQB.js +2 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/memory-extract-F76BE6KA.js +2 -0
- package/dist/ntfy-52EXHVMD.js +2 -0
- package/dist/program-ZWNGK3RB.js +2 -0
- package/dist/{promote-NBFF7ZIW.js → promote-H6ZHJXTY.js} +2 -2
- package/dist/push-HEDA6P3B.js +2 -0
- package/dist/push-HEDA6P3B.js.map +1 -0
- package/dist/push-keys-2DTD7YNQ.js +2 -0
- package/dist/push-store-LXTYULUF.js +2 -0
- package/dist/query-FTE4FLYK.js +2 -0
- package/dist/registry-HDOFVNRK.js +2 -0
- package/dist/{request-planner-ZEXFARZE.js → request-planner-ABD4WIGM.js} +2 -2
- package/dist/{review-candidates-F2HNH2TZ.js → review-candidates-B6574GOJ.js} +2 -2
- package/dist/{routing-XSRZ7V23.js → routing-BGKZOHOA.js} +2 -2
- package/dist/schedule-tool-UDHXTKWV.js +2 -0
- package/dist/scheduler-NQM3HVUY.js +2 -0
- package/dist/scheduler-NQM3HVUY.js.map +1 -0
- package/dist/{seat-IPDLEUI5.js → seat-VGST5AQB.js} +2 -2
- package/dist/seat-VGST5AQB.js.map +1 -0
- package/dist/{select-BYOX63CR.js → select-Y7SBUCGJ.js} +2 -2
- package/dist/set-enabled-ARKMDLXN.js +2 -0
- package/dist/set-enabled-ARKMDLXN.js.map +1 -0
- package/dist/{tool-WW4YCMSP.js → tool-5EVYUN2G.js} +2 -2
- package/dist/wiki-GREI2TSP.js +2 -0
- package/dist/wiki-GREI2TSP.js.map +1 -0
- package/package.json +3 -1
- package/dist/board-dashboard-KETIFTBD.js.map +0 -1
- package/dist/chunk-3IUU4YFI.js.map +0 -1
- package/dist/chunk-64UYAWAK.js.map +0 -1
- package/dist/chunk-6BXKZY76.js +0 -7
- package/dist/chunk-6BXKZY76.js.map +0 -1
- package/dist/chunk-7PK32QT5.js +0 -1107
- package/dist/chunk-7PK32QT5.js.map +0 -1
- package/dist/chunk-AKAM4BNC.js.map +0 -1
- package/dist/chunk-HRBKSZ34.js +0 -2
- package/dist/chunk-HRBKSZ34.js.map +0 -1
- package/dist/chunk-WCNKTV6G.js +0 -28
- package/dist/chunk-WCNKTV6G.js.map +0 -1
- package/dist/chunk-YS3Z2Z64.js.map +0 -1
- package/dist/client-AVQSLPIZ.js +0 -2
- package/dist/config-mutator-5JSG3CHW.js +0 -2
- package/dist/doctor-VITHTLEC.js +0 -2
- package/dist/memory-extract-MGGXIZTE.js +0 -2
- package/dist/ntfy-ZY2NPGBA.js.map +0 -1
- package/dist/program-MNFDOQGQ.js +0 -2
- package/dist/query-XCXR57IV.js +0 -2
- package/dist/registry-5ZP3ZNSH.js +0 -2
- package/dist/schedule-tool-AKCVLCWK.js +0 -2
- package/dist/scheduler-BEGZJWJU.js +0 -2
- package/dist/wiki-IVJJQUKB.js +0 -2
- /package/dist/{App-X6FGYBLX.js.map → App-VRTLAPRF.js.map} +0 -0
- /package/dist/{ChatApp-XMUOXQ2M.js.map → ChatApp-YENWPZT4.js.map} +0 -0
- /package/dist/{agent-KKVMU3VB.js.map → agent-HVUGHYBF.js.map} +0 -0
- /package/dist/{chunk-H7R3F2CO.js.map → chunk-2TJYZF4E.js.map} +0 -0
- /package/dist/{chunk-MHBUAU2B.js.map → chunk-37EABIOJ.js.map} +0 -0
- /package/dist/{chunk-B5UA3X6E.js.map → chunk-3W2KMI5O.js.map} +0 -0
- /package/dist/{chunk-7BQQWI4T.js.map → chunk-4HNHHKJF.js.map} +0 -0
- /package/dist/{chunk-76NNONUJ.js.map → chunk-BKDUCPZ3.js.map} +0 -0
- /package/dist/{chunk-NKSCUCVZ.js.map → chunk-ENRJ2QEH.js.map} +0 -0
- /package/dist/{chunk-AWRRBNWQ.js.map → chunk-HQMISQ7L.js.map} +0 -0
- /package/dist/{chunk-E57WKMRR.js.map → chunk-KLDGJSR5.js.map} +0 -0
- /package/dist/{chunk-7NF45XCM.js.map → chunk-M67AN4J7.js.map} +0 -0
- /package/dist/{chunk-WKTFP3SK.js.map → chunk-NO2HOK4B.js.map} +0 -0
- /package/dist/{chunk-QDPLR3SB.js.map → chunk-QX4R5WY7.js.map} +0 -0
- /package/dist/{chunk-QZ4M2KAC.js.map → chunk-QYHABRLM.js.map} +0 -0
- /package/dist/{chunk-7M7VJMGP.js.map → chunk-WLRHL2P7.js.map} +0 -0
- /package/dist/{chunk-YPPTPBBV.js.map → chunk-XWU7O3S5.js.map} +0 -0
- /package/dist/{chunk-XOUIZBAQ.js.map → chunk-ZOJUHPD5.js.map} +0 -0
- /package/dist/{client-AVQSLPIZ.js.map → client-N4XQEAVL.js.map} +0 -0
- /package/dist/{compaction-NWPBPWY2.js.map → compaction-H5U32UU6.js.map} +0 -0
- /package/dist/{config-FGCJVXYX.js.map → config-KHKIY6LI.js.map} +0 -0
- /package/dist/{config-mutator-5JSG3CHW.js.map → config-mutator-ZZKFQ7HJ.js.map} +0 -0
- /package/dist/{doctor-VITHTLEC.js.map → doctor-QICAXIQB.js.map} +0 -0
- /package/dist/{memory-extract-MGGXIZTE.js.map → memory-extract-F76BE6KA.js.map} +0 -0
- /package/dist/{program-MNFDOQGQ.js.map → ntfy-52EXHVMD.js.map} +0 -0
- /package/dist/{promote-NBFF7ZIW.js.map → program-ZWNGK3RB.js.map} +0 -0
- /package/dist/{query-XCXR57IV.js.map → promote-H6ZHJXTY.js.map} +0 -0
- /package/dist/{registry-5ZP3ZNSH.js.map → push-keys-2DTD7YNQ.js.map} +0 -0
- /package/dist/{routing-XSRZ7V23.js.map → push-store-LXTYULUF.js.map} +0 -0
- /package/dist/{schedule-tool-AKCVLCWK.js.map → query-FTE4FLYK.js.map} +0 -0
- /package/dist/{scheduler-BEGZJWJU.js.map → registry-HDOFVNRK.js.map} +0 -0
- /package/dist/{request-planner-ZEXFARZE.js.map → request-planner-ABD4WIGM.js.map} +0 -0
- /package/dist/{review-candidates-F2HNH2TZ.js.map → review-candidates-B6574GOJ.js.map} +0 -0
- /package/dist/{seat-IPDLEUI5.js.map → routing-BGKZOHOA.js.map} +0 -0
- /package/dist/{wiki-IVJJQUKB.js.map → schedule-tool-UDHXTKWV.js.map} +0 -0
- /package/dist/{select-BYOX63CR.js.map → select-Y7SBUCGJ.js.map} +0 -0
- /package/dist/{tool-WW4YCMSP.js.map → tool-5EVYUN2G.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as ma}from"./chunk-WWMFNLKD.js";import{a as ba}from"./chunk-GUJB53QU.js";import{a as T,b as va,c as ya,d as wa,e as ka,f as ye,g as _a,h as Sa,i as Ta,j as Ca,k as Aa}from"./chunk-UYMK3XNB.js";import{a as Ea}from"./chunk-Z3IP66SL.js";import{a as fa,b as ve,d as $,e as P,j as Be,k as ze,l as V,m as q,n as qe,o as ha,p as ga,q as xa}from"./chunk-KAFO5QZR.js";import{E as fe,F as na,G as ra,L as ia,N as be,O as Pe,P as Oe,Q as De,R as Ne,S as la,T as da,U as ca,V as He,X as pa,_ as ua,a as Vt,c as je,d as it,e as Yt,i as Qt,k as J,l as me,m as lt,x as Le,y as Re}from"./chunk-3RCFUIYR.js";import{g as Kt,h as Jt}from"./chunk-ENRJ2QEH.js";import{o as Zt,r as ea}from"./chunk-S7CVSKOX.js";import{a as oa,b as sa}from"./chunk-LQRBGQIR.js";import"./chunk-3W2KMI5O.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ta,c as aa}from"./chunk-2D3RYIDU.js";import{a as Ut,c as ot,d as st,h as Wt,i as Gt,j as Xt}from"./chunk-HQMISQ7L.js";import"./chunk-WP6KLXTP.js";import{a as qt}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-QYHABRLM.js";import"./chunk-ZOJUHPD5.js";import"./chunk-AFRHKA7B.js";import"./chunk-4HNHHKJF.js";import"./chunk-QD6IICK7.js";import"./chunk-WLRHL2P7.js";import{b as Ft}from"./chunk-XWU7O3S5.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-37EABIOJ.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as Bt,b as zt,c as Ir,m as K,p as rt}from"./chunk-4FFWNPFX.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function dt(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 Ma(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:dt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var Y={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"/>'},he=(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>",Fe=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+he(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ia(t={}){return $({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 sa}from"./chunk-GUJB53QU.js";import{a as C,b as ia,c as la,d as da,e
|
|
|
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">${he(Y.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${he(Y.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{a as sa}from"./chunk-GUJB53QU.js";import{a as C,b as ia,c as la,d as da,e
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${Fe(Y.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
|
+
${Fe(Y.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
|
+
${Fe(Y.pulse,"In motion","run-count")}
|
|
35
35
|
<div id="running" class="bf-col"></div>
|
|
36
36
|
</aside>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
${
|
|
39
|
+
${Fe(Y.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${
|
|
41
|
+
<div class="bf-search">${he(Y.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 @@ ${De(Y.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">${he(Y.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">${he(Y.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>${he(Y.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 @@ ${De(Y.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css
|
|
88
|
+
</div>`,css:$r,scripts:`<script>${ve({decayOf:dt,rankByDecay:Ma})}const ICON = ${JSON.stringify(Y)};${jr}</script>`})}var $r=`
|
|
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
|
+
}`,jr=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 ct(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,d),p.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let p=1;p<r.length;p++){let m=r[p].from-r[p-1].to;m<d&&(d=m,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function pt(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 $a(t,e=[],a){let{bands:n,gaps:r}=ct(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(I=>l.startedAt>=I.from&&l.startedAt<=I.to);if(d===-1)continue;let p=n[d],m=p.to-p.from||1,f=(l.startedAt-p.from)/m*100,y=Math.min(Math.max((l.durationMs||0)/m*100,1.2),100-f),S=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};S.runs.push({...l,band:d,track:0,left:f,width:y,marks:o.get(l.id)??[]}),s.set(l.laneKey,S)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>pt(l.runs.filter(m=>m.band===p))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Lr}from"crypto";import{readFileSync as Rr,statSync as Pr}from"fs";import{resolve as Or,dirname as Dr}from"path";import{fileURLToPath as Nr}from"url";var ja=new Map;function Ue(t){let e=ja.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Dr(Nr(import.meta.url)),r=Or(n,"web",t),o=Pr(r),s=o.size<8e6?Lr("sha1").update(Rr(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return ja.set(t,a),a}var te={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"/>'},We=(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>",Hr=[["agent","Agent",te.bot],["client","Client",te.user],["project","Project",te.folder],["channel","Channel",te.route],["node","Node",te.mesh]],La={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 Ra(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return $({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">${La[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",te.timeline],["map","Map",te.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",te.timeline],["map","Map",te.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${We(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":""}>${We(te.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
|
+
${Hr.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${We(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">${We(te.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="${Ue("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Br,scripts:`<script>${ve({computeBands:ct,packTracks:pt,buildTimeline:$a})}const ICON = ${JSON.stringify(te)};const SUB = ${JSON.stringify(La)};${zr}</script>`})}var Br=`
|
|
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
|
+
`,zr=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 Pa(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return $({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:qr,scripts:`<script src="${Ue("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var qr=`
|
|
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,10 @@ 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 Vi}from"http";import{appendFileSync as Yi,existsSync as sr,mkdirSync as Qi}from"fs";import{readFile as Zi}from"fs/promises";import{fileURLToPath as el}from"url";import{dirname as tl,resolve as Te}from"path";pr();var Ea='/*! 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 Be,readFileSync as Ta,writeFileSync as Ca,rmSync as Kl,mkdirSync as Mr,copyFileSync as Ir,readdirSync as $r}from"fs";import{resolve as ve}from"path";Je();var ae={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 Sa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Le({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.`})+Re([{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">');return $({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Sr()+na,css:Cr,scripts:`${e}<script>${ra}
|
|
1047
|
-
${
|
|
1048
|
-
${
|
|
1049
|
-
${
|
|
1046
|
+
`;import{createServer as kl}from"http";import{appendFileSync as _l,existsSync as Sr,mkdirSync as Sl}from"fs";import{readFile as El}from"fs/promises";import{fileURLToPath as Tl}from"url";import{dirname as Cl,resolve as Ie}from"path";Ir();var Oa='/*! 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 Ge,readFileSync as Na,writeFileSync as Ha,rmSync as Cd,mkdirSync as Kr,copyFileSync as Jr,readdirSync as Vr}from"fs";import{resolve as we}from"path";rt();var ae={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 Da(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Be({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+ze([{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">');return $({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ur()+ha,css:Gr,scripts:`${e}<script>${ga}
|
|
1047
|
+
${xa}
|
|
1048
|
+
${Fr}
|
|
1049
|
+
${Xr}</script>`})}var Fr=`
|
|
1050
1050
|
(function(){
|
|
1051
1051
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1052
1052
|
async function refresh() {
|
|
@@ -1107,8 +1107,8 @@ ${Ar}</script>`})}var Er=`
|
|
|
1107
1107
|
refresh();
|
|
1108
1108
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1109
1109
|
document.addEventListener('ax-config-saved', refresh);
|
|
1110
|
-
})();`;function
|
|
1111
|
-
`:"";return
|
|
1110
|
+
})();`;function Ur(){let t=sa().business?`<button data-tab="business">Business</button>
|
|
1111
|
+
`:"";return Wr.replace("__BUSINESS_TABS__",t)}var Wr=`
|
|
1112
1112
|
<div id="peer-banner" class="peer-banner">
|
|
1113
1113
|
<span class="label">Managing</span>
|
|
1114
1114
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -1252,7 +1252,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1252
1252
|
|
|
1253
1253
|
<section id="tab-agents" class="tab active">
|
|
1254
1254
|
${q({icon:ae.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."})}
|
|
1255
|
-
${
|
|
1255
|
+
${V({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>).`})}
|
|
1256
1256
|
<div id="agent-list" class="ax-stack"></div>
|
|
1257
1257
|
<div class="add-form">
|
|
1258
1258
|
<h3>Add a new agent</h3>
|
|
@@ -1275,7 +1275,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1275
1275
|
|
|
1276
1276
|
<section id="tab-channels" class="tab">
|
|
1277
1277
|
${q({icon:ae.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."})}
|
|
1278
|
-
${
|
|
1278
|
+
${V({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."})}
|
|
1279
1279
|
|
|
1280
1280
|
<details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
|
|
1281
1281
|
<summary class="primary">\u2699 Notifications routing</summary>
|
|
@@ -1360,10 +1360,10 @@ ${Ar}</script>`})}var Er=`
|
|
|
1360
1360
|
</div>
|
|
1361
1361
|
</details>
|
|
1362
1362
|
|
|
1363
|
-
<div id="ch-chatapps-label">${
|
|
1363
|
+
<div id="ch-chatapps-label">${qe({label:"Chat apps"})}</div>
|
|
1364
1364
|
<div class="ax-connectors" id="ch-chatapps"></div>
|
|
1365
1365
|
|
|
1366
|
-
<div id="ch-devtools-label">${
|
|
1366
|
+
<div id="ch-devtools-label">${qe({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
|
|
1367
1367
|
<div class="ax-connectors" id="ch-devtools"></div>
|
|
1368
1368
|
|
|
1369
1369
|
<!-- Active-channel configuration panes. One shows at a time; clicking
|
|
@@ -1382,7 +1382,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1382
1382
|
|
|
1383
1383
|
<section id="tab-crons" class="tab">
|
|
1384
1384
|
${q({icon:ae.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."})}
|
|
1385
|
-
${
|
|
1385
|
+
${V({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."})}
|
|
1386
1386
|
<div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
|
|
1387
1387
|
|
|
1388
1388
|
<div class="ax-builder">
|
|
@@ -1480,7 +1480,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1480
1480
|
|
|
1481
1481
|
<section id="tab-webhooks" class="tab">
|
|
1482
1482
|
${q({icon:ae.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."})}
|
|
1483
|
-
${
|
|
1483
|
+
${V({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.`})}
|
|
1484
1484
|
<div id="webhook-list" class="ax-stack"></div>
|
|
1485
1485
|
<div class="add-form">
|
|
1486
1486
|
<h3>Add a webhook</h3>
|
|
@@ -1501,8 +1501,8 @@ ${Ar}</script>`})}var Er=`
|
|
|
1501
1501
|
<section id="tab-mesh" class="tab">
|
|
1502
1502
|
${q({icon:ae.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."})}
|
|
1503
1503
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
1504
|
-
${
|
|
1505
|
-
${
|
|
1504
|
+
${V({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."})}
|
|
1505
|
+
${qe({label:"Connected peers"})}
|
|
1506
1506
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
1507
1507
|
<div class="add-form">
|
|
1508
1508
|
<h3>Add a peer</h3>
|
|
@@ -1530,7 +1530,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1530
1530
|
|
|
1531
1531
|
<section id="tab-business" class="tab">
|
|
1532
1532
|
${q({icon:ae.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."})}
|
|
1533
|
-
${
|
|
1533
|
+
${V({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.'})}
|
|
1534
1534
|
|
|
1535
1535
|
<div class="ax-stack" style="margin-top:14px">
|
|
1536
1536
|
<h3 style="margin:0 0 6px;font-size:13px">Org chart</h3>
|
|
@@ -1618,7 +1618,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1618
1618
|
|
|
1619
1619
|
<section id="tab-boards-cfg" class="tab">
|
|
1620
1620
|
${q({icon:ae.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."})}
|
|
1621
|
-
${
|
|
1621
|
+
${V({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.'})}
|
|
1622
1622
|
|
|
1623
1623
|
<div class="ax-stack" style="margin-top:14px">
|
|
1624
1624
|
<h3 style="margin:0 0 6px;font-size:13px">Boards</h3>
|
|
@@ -1643,7 +1643,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1643
1643
|
|
|
1644
1644
|
<section id="tab-actions" class="tab">
|
|
1645
1645
|
${q({icon:ae.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."})}
|
|
1646
|
-
${
|
|
1646
|
+
${V({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."})}
|
|
1647
1647
|
|
|
1648
1648
|
<div class="ax-stack" style="margin-top:14px">
|
|
1649
1649
|
<h3 style="margin:0 0 6px;font-size:13px">Registered actions</h3>
|
|
@@ -1699,7 +1699,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1699
1699
|
|
|
1700
1700
|
<section id="tab-tokens" class="tab">
|
|
1701
1701
|
${q({icon:ae.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."})}
|
|
1702
|
-
${
|
|
1702
|
+
${V({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."})}
|
|
1703
1703
|
<div id="token-list" class="ax-stack"></div>
|
|
1704
1704
|
<div class="add-form">
|
|
1705
1705
|
<h3>Mint a new token</h3>
|
|
@@ -1719,7 +1719,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1719
1719
|
|
|
1720
1720
|
<section id="tab-advanced" class="tab">
|
|
1721
1721
|
${q({icon:ae.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."})}
|
|
1722
|
-
${
|
|
1722
|
+
${V({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.`})}
|
|
1723
1723
|
|
|
1724
1724
|
<div class="ax-jv-toolbar">
|
|
1725
1725
|
<input class="ax-jv-search" id="jv-search" placeholder="Search keys & values\u2026" />
|
|
@@ -1745,7 +1745,7 @@ ${Ar}</script>`})}var Er=`
|
|
|
1745
1745
|
<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>
|
|
1746
1746
|
</section>
|
|
1747
1747
|
</main>
|
|
1748
|
-
`,
|
|
1748
|
+
`,Gr=`
|
|
1749
1749
|
|
|
1750
1750
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
1751
1751
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -1953,7 +1953,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
1953
1953
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
1954
1954
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
1955
1955
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
1956
|
-
`,
|
|
1956
|
+
`,Xr=`
|
|
1957
1957
|
const $ = (id) => document.getElementById(id);
|
|
1958
1958
|
let state = null;
|
|
1959
1959
|
|
|
@@ -4760,11 +4760,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
4760
4760
|
})();
|
|
4761
4761
|
|
|
4762
4762
|
refresh();
|
|
4763
|
-
`;function Aa(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Sa({peers:a,localToken:n}))}async function Ma(t,e){let a=ot();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Ia(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Wr(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await jr(t),r={"GET /api/admin/state":()=>Rr(),"POST /api/admin/agents":()=>Br(n),"PATCH /api/admin/agents":()=>zr(n),"DELETE /api/admin/agents":()=>qr(n),"POST /api/admin/agents/access":()=>Pr(n),"POST /api/admin/channels/telegram":()=>Fr(n),"DELETE /api/admin/channels/telegram":()=>ho(n),"POST /api/admin/channels/telegram/toggle":()=>go(n),"POST /api/admin/crons":()=>fo(n),"DELETE /api/admin/crons":()=>xo(n),"POST /api/admin/config/raw":()=>vo(n),"GET /api/admin/tokens":()=>Or(),"POST /api/admin/tokens":()=>Dr(n),"DELETE /api/admin/tokens":()=>Hr(n),"POST /api/admin/agents/test":()=>Nr(n),"POST /api/admin/agents/integrations":()=>Yr(n),"DELETE /api/admin/agents/integrations":()=>Qr(n),"PATCH /api/admin/agents/integrations":()=>Zr(n),"PATCH /api/admin/channels/telegram":()=>Ur(n),"POST /api/admin/channels/slack":()=>so(n),"POST /api/admin/channels/slack/toggle":()=>io(n),"POST /api/admin/channels/discord":()=>lo(n),"POST /api/admin/channels/discord/toggle":()=>co(n),"POST /api/admin/channels/gitlab":()=>po(n),"POST /api/admin/channels/gitlab/toggle":()=>uo(n),"GET /api/admin/channels/whatsapp/state":()=>ke("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>ke("/webrtc/history"),"POST /api/admin/actions":()=>$o(n),"DELETE /api/admin/actions":()=>jo(n),"POST /api/admin/actions/run":()=>Lo(n),"GET /api/admin/channels/whatsapp/chats":()=>ke("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>ke("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ne("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>mo(n),"POST /api/admin/webhooks":()=>eo(n),"PATCH /api/admin/webhooks":()=>to(n),"DELETE /api/admin/webhooks":()=>oo(n),"POST /api/admin/mesh/peers":()=>ao(n),"DELETE /api/admin/mesh/peers":()=>no(n),"POST /api/admin/mesh/toggle":()=>ro(n),"GET /api/admin/files":()=>Gr(t),"GET /api/admin/files/read":()=>Xr(t),"PUT /api/admin/files":()=>Kr(n),"POST /api/admin/files/skill":()=>Jr(n),"DELETE /api/admin/files/skill":()=>Vr(n),"POST /api/admin/business/orgchart":()=>bo(n),"DELETE /api/admin/business/orgchart":()=>yo(n),"POST /api/admin/business/project":()=>wo(n),"DELETE /api/admin/business/project":()=>Eo(n),"POST /api/admin/business/client":()=>ko(n),"DELETE /api/admin/business/client":()=>_o(n),"POST /api/admin/business/contact":()=>So(n),"DELETE /api/admin/business/contact":()=>To(n),"POST /api/admin/boards":()=>Co(n),"DELETE /api/admin/boards":()=>Ao(n),"POST /api/admin/boards/columns":()=>Mo(n),"DELETE /api/admin/boards/columns":()=>Io(n),"POST /api/admin/notifications":()=>Po(n),"POST /api/admin/screen":()=>Oo(n),"POST /api/admin/webhooks/triggers":()=>Do(n),"POST /api/admin/mesh/health":()=>Ro(n),"GET /api/admin/projects":()=>ke("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ne("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ne("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ne("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ne("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ne("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ne("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ne("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ne("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){nt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();nt(e,200,i)}catch(n){nt(e,400,{error:n.message||"admin op failed"})}}function nt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function jr(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 Lr(t){let e=ve(process.cwd(),t);if(!Be(e))return[];let a=[];for(let n of $r(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ta(ve(e,n.name),"utf-8")))}catch{}return a}function ot(){let t=ve(process.cwd(),"agentx.json");return Be(t)?JSON.parse(Ta(t,"utf-8")):null}function Rr(){let t=ot();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,u])=>({id:d,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(g=>{let f=g.credentials||{},b={};for(let[x,y]of Object.entries(f))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?b[x]=process.env[y]?"set":"unset":typeof y=="string"&&(b[x]="literal");return{kind:g.kind,label:g.label,enabled:g.enabled!==!1,credentials:f,credStatus:b,metadata:g.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,u])=>({id:d,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,u])=>({id:d,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.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}},m=t.dashboard?.daemonUrl||"http://localhost:18800",h=t.business||{},_={enabled:!!h.enabled,timezone:h.timezone||"UTC",orgChart:h.orgChart||{},projects:Array.isArray(h.projects)?h.projects:[],contactMap:Array.isArray(h.contactMap)?h.contactMap:[],clients:h.clients&&typeof h.clients=="object"?h.clients:{}},S=t.notifications||{},w={longTaskThreshold:S.longTaskThreshold??30,destination:S.destination||null,on:{taskComplete:S.on?.taskComplete!==!1,taskError:S.on?.taskError!==!1,taskQueued:!!S.on?.taskQueued},local:qt(S.local),ntfy:ha(t.channels?.ntfy)},E=[];try{E=Lr(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,g)=>u.id.localeCompare(g.id))}catch{}let T=(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,crons:l,webhooks:c,mesh:p,daemonUrl:m,nodeName:t.node?.name,business:_,boards:T,notifications:w,screen:ea(t.screen),actions:E}}function Pr(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function Or(){return new V().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 Dr(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 V().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Hr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new V().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Nr(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=K();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 Br(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=ja(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=ve(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let m={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(m.model=o),s&&(m.systemPrompt=s.slice(0,400)),p.agents[e]=m,`added agent "${e}"`}),c=ve(i,"CLAUDE.md");if(!Be(c))try{Mr(i,{recursive:!0}),Ca(c,`# ${a}
|
|
4763
|
+
`;function Ba(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:a,localToken:n}))}async function za(t,e){let a=ft();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function qa(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await po(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Yr(t),r={"GET /api/admin/state":()=>Zr(),"POST /api/admin/agents":()=>oo(n),"PATCH /api/admin/agents":()=>so(n),"DELETE /api/admin/agents":()=>io(n),"POST /api/admin/agents/access":()=>eo(n),"POST /api/admin/channels/telegram":()=>lo(n),"DELETE /api/admin/channels/telegram":()=>Lo(n),"POST /api/admin/channels/telegram/toggle":()=>Ro(n),"POST /api/admin/crons":()=>Po(n),"DELETE /api/admin/crons":()=>Oo(n),"POST /api/admin/config/raw":()=>Do(n),"GET /api/admin/tokens":()=>to(),"POST /api/admin/tokens":()=>ao(n),"DELETE /api/admin/tokens":()=>no(n),"POST /api/admin/agents/test":()=>ro(n),"POST /api/admin/agents/integrations":()=>xo(n),"DELETE /api/admin/agents/integrations":()=>bo(n),"PATCH /api/admin/agents/integrations":()=>vo(n),"PATCH /api/admin/channels/telegram":()=>co(n),"POST /api/admin/channels/slack":()=>To(n),"POST /api/admin/channels/slack/toggle":()=>Co(n),"POST /api/admin/channels/discord":()=>Ao(n),"POST /api/admin/channels/discord/toggle":()=>Mo(n),"POST /api/admin/channels/gitlab":()=>Io(n),"POST /api/admin/channels/gitlab/toggle":()=>$o(n),"GET /api/admin/channels/whatsapp/state":()=>Ee("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Ee("/webrtc/history"),"POST /api/admin/actions":()=>Vo(n),"DELETE /api/admin/actions":()=>Yo(n),"POST /api/admin/actions/run":()=>Qo(n),"GET /api/admin/channels/whatsapp/chats":()=>Ee("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Ee("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>oe("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>jo(n),"POST /api/admin/webhooks":()=>yo(n),"PATCH /api/admin/webhooks":()=>wo(n),"DELETE /api/admin/webhooks":()=>Eo(n),"POST /api/admin/mesh/peers":()=>ko(n),"DELETE /api/admin/mesh/peers":()=>_o(n),"POST /api/admin/mesh/toggle":()=>So(n),"GET /api/admin/files":()=>uo(t),"GET /api/admin/files/read":()=>mo(t),"PUT /api/admin/files":()=>fo(n),"POST /api/admin/files/skill":()=>ho(n),"DELETE /api/admin/files/skill":()=>go(n),"POST /api/admin/business/orgchart":()=>No(n),"DELETE /api/admin/business/orgchart":()=>Ho(n),"POST /api/admin/business/project":()=>Bo(n),"DELETE /api/admin/business/project":()=>Fo(n),"POST /api/admin/business/client":()=>zo(n),"DELETE /api/admin/business/client":()=>qo(n),"POST /api/admin/business/contact":()=>Uo(n),"DELETE /api/admin/business/contact":()=>Wo(n),"POST /api/admin/boards":()=>Go(n),"DELETE /api/admin/boards":()=>Xo(n),"POST /api/admin/boards/columns":()=>Ko(n),"DELETE /api/admin/boards/columns":()=>Jo(n),"POST /api/admin/notifications":()=>es(n),"POST /api/admin/screen":()=>ts(n),"POST /api/admin/webhooks/triggers":()=>as(n),"POST /api/admin/mesh/health":()=>Zo(n),"GET /api/admin/projects":()=>Ee("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>oe("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>oe("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>oe("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>oe("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>oe("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>oe("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>oe("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>oe("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ut(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ut(e,200,i)}catch(n){ut(e,400,{error:n.message||"admin op failed"})}}function ut(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Yr(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 Qr(t){let e=we(process.cwd(),t);if(!Ge(e))return[];let a=[];for(let n of Vr(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Na(we(e,n.name),"utf-8")))}catch{}return a}function ft(){let t=we(process.cwd(),"agentx.json");return Ge(t)?JSON.parse(Na(t,"utf-8")):null}function Zr(){let t=ft();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([c,u])=>({id:c,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(h=>{let g=h.credentials||{},w={};for(let[x,k]of Object.entries(g))typeof k=="string"&&/^[A-Z][A-Z0-9_]*$/.test(k)?w[x]=process.env[k]?"set":"unset":typeof k=="string"&&(w[x]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:g,credStatus:w,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([c,u])=>({id:c,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([c,u])=>({id:c,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(c=>({id:c.id,source:c.source,agentId:c.agentId,secretEnv:c.secretEnv||"",description:c.description||"",enabled:c.enabled!==!1,triggers:c.triggers&&typeof c.triggers=="object"?c.triggers:{},defaultWorkflow:c.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(c=>({url:c.url,name:c.name,hasToken:!!c.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},m=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},y={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:{}},S=t.notifications||{},I={longTaskThreshold:S.longTaskThreshold??30,destination:S.destination||null,on:{taskComplete:S.on?.taskComplete!==!1,taskError:S.on?.taskError!==!1,taskQueued:!!S.on?.taskQueued},local:Zt(S.local),ntfy:Ta(t.channels?.ntfy)},b=[];try{b=Qr(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,h)=>u.id.localeCompare(h.id))}catch{}let E=(Array.isArray(t.boards)?t.boards:[]).map(c=>({id:c.id,name:c.name,source:c.source||{type:"gitlab",projects:[]},primaryToolLabel:c.primaryToolLabel||"",timeRangeDays:c.timeRangeDays??30,closedWindowDays:c.closedWindowDays??30,columns:Array.isArray(c.columns)?c.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,crons:l,webhooks:d,mesh:p,daemonUrl:m,nodeName:t.node?.name,business:y,boards:E,notifications:I,screen:pa(t.screen),actions:b}}function eo(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}=T(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 to(){return new J().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 ao(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 J().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function no(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new J().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function ro(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=K();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(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function oo(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=Ua(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=we(process.cwd(),"agents",e),{summary:l}=T(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let m={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(m.model=o),s&&(m.systemPrompt=s.slice(0,400)),p.agents[e]=m,`added agent "${e}"`}),d=we(i,"CLAUDE.md");if(!Ge(d))try{Kr(i,{recursive:!0}),Ha(d,`# ${a}
|
|
4764
4764
|
|
|
4765
4765
|
${s||"You are "+a+"."}
|
|
4766
|
-
`)}catch{}return{summary:l}}function zr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=ja(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 qr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function Fr(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=C(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Ur(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function ke(t){let{url:e,headers:a}=st(),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 ne(t,e){let{url:a,headers:n}=st(),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 Wr(t,e){try{let{url:a,headers:n}=st(),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 st(){let t="http://127.0.0.1:18800",e={};try{let a=K();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function _e(t){let a=ot()?.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 rt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Gr(t){let e=rt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=fe(_e(e));return{agentId:e,...a}}function Xr(t){let e=rt(t,"agent").trim(),a=rt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ae(_e(e),a)}function Kr(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=Me(_e(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Jr(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=Ie(_e(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Vr(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=$e(_e(e),a);return{summary:`removed skill "${a}"`,...n}}function Yr(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Qr(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Zr(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(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 $a=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function eo(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(!$a.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(m=>m.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 to(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&$a.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 ao(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=C(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function no(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function ro(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function oo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function so(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=C(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function io(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function lo(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=C(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function co(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function po(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=C(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function uo(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function mo(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-BEGZJWJU.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 ho(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function go(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function fo(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=C(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function xo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=C(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function vo(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=ve(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Be(n))try{Ir(n,r)}catch{}Ca(n,JSON.stringify(a,null,2)+`
|
|
4767
|
-
`,"utf-8");try{let s=K().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 ja(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function bo(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function yo(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=C(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function wo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=C(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function ko(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=C(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function _o(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function Eo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=C(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function So(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=C(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function To(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=C(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function Co(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(m=>m.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let m=l.boards[c];return l.boards[c]={...m,...p,columns:m.columns,labels:m.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Ao(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=C(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Mo(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(m=>m.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(m=>m.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 Io(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=C(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function $o(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 jo(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 Lo(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 Ro(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=C(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function Po(t){let{summary:e}=C(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=Ft(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=ga(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 Oo(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=ta(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Do(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}Je();import{resolve as Bo}from"path";function La(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
4766
|
+
`)}catch{}return{summary:l}}function so(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=T(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=Ua(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 io(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=T(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 lo(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}=T(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 co(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=T(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 Ee(t){let{url:e,headers:a}=ht(),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 oe(t,e){let{url:a,headers:n}=ht(),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 po(t,e){try{let{url:a,headers:n}=ht(),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 ht(){let t="http://127.0.0.1:18800",e={};try{let a=K();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Te(t){let a=ft()?.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 mt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function uo(t){let e=mt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=be(Te(e));return{agentId:e,...a}}function mo(t){let e=mt(t,"agent").trim(),a=mt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Pe(Te(e),a)}function fo(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=Oe(Te(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function ho(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=De(Te(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function go(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=Ne(Te(e),a);return{summary:`removed skill "${a}"`,...n}}function xo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=T(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function bo(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}=T(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function vo(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}=T(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Fa=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function yo(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(!Fa.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=T(l=>{if(s){if(!(l.mesh?.peers||[]).find(m=>m.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 d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function wo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=T(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Fa.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 ko(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}=T(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 _o(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=T(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 So(t){let e=!!t?.enabled,{summary:a}=T(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 Eo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=T(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 To(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}=T(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 Co(t){let e=!!t?.enabled,{summary:a}=T(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 Ao(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}=T(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 Mo(t){let e=!!t?.enabled,{summary:a}=T(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 Io(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}=T(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 $o(t){let e=!!t?.enabled,{summary:a}=T(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 jo(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-NQM3HVUY.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 Lo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=T(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 Ro(t){let e=!!t?.enabled,{summary:a}=T(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 Po(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}=T(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 Oo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=T(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function Do(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=we(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Ge(n))try{Jr(n,r)}catch{}Ha(n,JSON.stringify(a,null,2)+`
|
|
4767
|
+
`,"utf-8");try{let s=K().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 Ua(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function No(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}=T(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function Ho(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=T(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 Bo(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}=T(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 zo(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}=T(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 qo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=T(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 Fo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=T(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 Uo(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}=T(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 Wo(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}=T(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 Go(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}=T(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(m=>m.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let m=l.boards[d];return l.boards[d]={...m,...p,columns:m.columns,labels:m.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Xo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=T(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 Ko(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}=T(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(m=>m.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let p=l.columns.findIndex(m=>m.id===a);return p>=0?(l.columns[p]={...l.columns[p],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Jo(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}=T(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 Vo(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 Yo(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 Qo(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 Zo(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}=T(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 es(t){let{summary:e}=T(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=ea(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=Ca(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 ts(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=T(a=>(a.screen=ua(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function as(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=T(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}rt();import{resolve as os}from"path";function Wa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
4768
4768
|
|
|
4769
4769
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
4770
4770
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -4819,7 +4819,7 @@ ${s||"You are "+a+"."}
|
|
|
4819
4819
|
<h2>Recent classifications</h2>
|
|
4820
4820
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
4821
4821
|
<div id="recent"></div>
|
|
4822
|
-
</section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
4822
|
+
</section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ns,scripts:`${e}<script>${rs}</script>`})}var ns=`
|
|
4823
4823
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
4824
4824
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
4825
4825
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -4923,7 +4923,7 @@ details {
|
|
|
4923
4923
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
4924
4924
|
}
|
|
4925
4925
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
4926
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
4926
|
+
details[open] summary { margin-bottom: 8px; }`,rs=`
|
|
4927
4927
|
const $ = (id) => document.getElementById(id);
|
|
4928
4928
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
4929
4929
|
|
|
@@ -5143,7 +5143,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5143
5143
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5144
5144
|
|
|
5145
5145
|
refresh();
|
|
5146
|
-
`;function
|
|
5146
|
+
`;function Xa(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wa({peers:a,localToken:n}))}async function Ka(t,e,a){try{let n=t.method==="GET"?void 0:await fs(t),r=ss(),o={"GET /api/admin/graph/state":()=>is(r),"POST /api/admin/graph/classifications/approve":()=>ls(r,n),"POST /api/admin/graph/classifications/reject":()=>ds(r,n),"POST /api/admin/graph/nodes":()=>cs(r,n),"PATCH /api/admin/graph/nodes":()=>ps(r,n),"DELETE /api/admin/graph/nodes":()=>us(r,n),"PUT /api/admin/graph/schema":()=>ms(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){gt(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();gt(e,200,l)}catch(n){gt(e,400,{error:n?.message||"graph op failed"})}}function ss(){let t=K(),e=os(process.cwd(),t.graph.baseDir);return new Ft({baseDir:e})}function is(t){let e=K(),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 ls(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ja(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=xt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function ds(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ja(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Ja(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 cs(t,e){let a=Ga(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Ga(String(e.parentId)):null,o=xt({[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 ps(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=xt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function us(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function ms(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 xt(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 Ga(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function gt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function fs(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 Va(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
5147
5147
|
<header class="apv__head">
|
|
5148
5148
|
<div>
|
|
5149
5149
|
<h1>Approvals</h1>
|
|
@@ -5176,7 +5176,7 @@ refresh();
|
|
|
5176
5176
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5177
5177
|
</form>
|
|
5178
5178
|
</details>
|
|
5179
|
-
</div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5179
|
+
</div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:hs,scripts:`${e}<script>${gs}</script>`})}var hs=`
|
|
5180
5180
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
5181
5181
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
5182
5182
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -5225,7 +5225,7 @@ refresh();
|
|
|
5225
5225
|
@media (max-width: 560px) {
|
|
5226
5226
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
5227
5227
|
}
|
|
5228
|
-
`,
|
|
5228
|
+
`,gs=`
|
|
5229
5229
|
(function(){
|
|
5230
5230
|
var state = { items: [], snoozed: 0, kind: '', showAll: false };
|
|
5231
5231
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson' };
|
|
@@ -5376,7 +5376,7 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
5376
5376
|
load();
|
|
5377
5377
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
5378
5378
|
})();
|
|
5379
|
-
`;var
|
|
5379
|
+
`;var xs=["yes","no","later"];function se(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Ya(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 Qa(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Va({peers:e,localToken:a}))}async function Za(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 se(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=Le(s,{includeSnoozed:n.searchParams.get("all")==="1"});return se(e,200,{...i,settings:ye(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Ya(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!xs.includes(d))return se(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=ye(s.configPath),m=await Re(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return m.ok?(se(e,200,{ok:!0,message:m.message}),!0):(se(e,409,{error:m.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Ya(t),l={},d=m=>{let f=i[m];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${m} must be a positive number`);return f}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let m=i.destination.trim();if(!m)l.destination=null;else{let f=_a(m);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Sa(l,{configPath:s.configPath,reload:s.reload});return p.success?(se(e,200,{ok:!0,settings:ye(s.configPath)}),!0):(se(e,400,{error:p.error}),!0)}}catch(i){return se(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return se(e,404,{error:"Not found"}),!0}import{resolve as ys}from"path";import{existsSync as ws}from"fs";import ks from"better-sqlite3";function en(t={}){let e=`<div class="ax-obs">
|
|
5380
5380
|
<header class="ax-obs__head">
|
|
5381
5381
|
<h1>Health</h1>
|
|
5382
5382
|
<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>
|
|
@@ -5498,7 +5498,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
5498
5498
|
</div>
|
|
5499
5499
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
5500
5500
|
</section>
|
|
5501
|
-
</div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
5501
|
+
</div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:bs,scripts:`<script>${vs}</script>`})}var bs=`
|
|
5502
5502
|
.ax-obs { padding: 16px 24px; }
|
|
5503
5503
|
.ax-obs__head { margin-bottom: 16px; }
|
|
5504
5504
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -5615,7 +5615,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
5615
5615
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
5616
5616
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
5617
5617
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
5618
|
-
`,
|
|
5618
|
+
`,vs=`
|
|
5619
5619
|
(function(){
|
|
5620
5620
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
5621
5621
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -5999,23 +5999,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
5999
5999
|
|
|
6000
6000
|
load(current);
|
|
6001
6001
|
})();
|
|
6002
|
-
`;var
|
|
6002
|
+
`;var nn={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 rn(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function bt(t){let e=nn[rn(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 _s(){let t=ys(process.cwd(),".agentx/db.sqlite");if(!ws(t))return null;try{let e=new ks(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function on(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(en({peers:a}))}function Ss(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 ie(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function sn(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=_s();if(!r)return ie(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Ss(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
|
|
6003
6003
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
6004
6004
|
FROM route_traces
|
|
6005
6005
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6006
6006
|
ORDER BY at DESC LIMIT @limit
|
|
6007
|
-
`,p=r.db.prepare(
|
|
6007
|
+
`,p=r.db.prepare(d).all(l);return ie(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
|
|
6008
6008
|
SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
|
|
6009
6009
|
FROM rotations
|
|
6010
6010
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
6011
6011
|
ORDER BY rotated_at DESC LIMIT @limit
|
|
6012
|
-
`,p=r.db.prepare(
|
|
6012
|
+
`,p=r.db.prepare(d).all(l);return ie(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
|
|
6013
6013
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
6014
6014
|
FROM task_history
|
|
6015
6015
|
WHERE ${i.join(" AND ")}
|
|
6016
6016
|
ORDER BY started_at DESC LIMIT @limit
|
|
6017
|
-
`,m=r.db.prepare(
|
|
6018
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6017
|
+
`,m=r.db.prepare(d).all(l).map(f=>({...f,plain:ln(f.error)}));return ie(e,200,{rows:m}),!0}if(n==="summary"||n==="overview")return ie(e,200,Es(r.db)),!0;if(n==="activity")return ie(e,200,Ts(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=tn(i.searchParams.get("range"));return ie(e,200,an(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=tn(i.searchParams.get("range")),d=an(r.db,l),p=Cs(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return ie(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ie(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function ln(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(`
|
|
6018
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Es(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),m=k=>p.length?p[Math.min(p.length-1,Math.floor(p.length*k))].duration_ms:0,f=m(.5),y=m(.95),I=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((k,A)=>k+bt(A),0),b=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((k,A)=>k+bt(A),0),E=t.prepare(`
|
|
6019
6019
|
SELECT agent_id,
|
|
6020
6020
|
COUNT(*) AS tasks,
|
|
6021
6021
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -6025,7 +6025,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6025
6025
|
WHERE started_at >= ?
|
|
6026
6026
|
GROUP BY agent_id
|
|
6027
6027
|
ORDER BY tasks DESC LIMIT 10
|
|
6028
|
-
`).all(a),
|
|
6028
|
+
`).all(a),c=t.prepare(`
|
|
6029
6029
|
SELECT COALESCE(channel, 'unknown') AS channel,
|
|
6030
6030
|
COUNT(*) AS tasks,
|
|
6031
6031
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -6033,12 +6033,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6033
6033
|
WHERE started_at >= ?
|
|
6034
6034
|
GROUP BY channel
|
|
6035
6035
|
ORDER BY tasks DESC
|
|
6036
|
-
`).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(
|
|
6036
|
+
`).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(k=>k.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(k=>k.agent_id)),g=u.filter(k=>!h.has(k)),x=t.prepare(`
|
|
6037
6037
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
6038
6038
|
FROM task_history
|
|
6039
6039
|
WHERE status='error' AND started_at >= ?
|
|
6040
6040
|
ORDER BY started_at DESC LIMIT 5
|
|
6041
|
-
`).all(o).map(
|
|
6041
|
+
`).all(o).map(k=>({...k,plain:ln(k.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:y,spendToday:I,spendDelta:I-b,idleAgentCount:g.length},perAgent:E,perChannel:c,idleAgents:g,recentErrors:x}}function Ts(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(`
|
|
6042
6042
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
6043
6043
|
COUNT(*) AS tasks,
|
|
6044
6044
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -6065,7 +6065,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6065
6065
|
WHERE started_at >= @since
|
|
6066
6066
|
GROUP BY agent_id
|
|
6067
6067
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
6068
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
6068
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function tn(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 an(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
6069
6069
|
SELECT day, agent_id, model,
|
|
6070
6070
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
6071
6071
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -6073,20 +6073,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6073
6073
|
FROM usage_daily
|
|
6074
6074
|
${a}
|
|
6075
6075
|
ORDER BY day
|
|
6076
|
-
`).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,
|
|
6076
|
+
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,m=0,f=0,y=0,S=0,I=0,b=0,E={},c={};for(let _ of n){let M=bt(_),L=rn(_.model),R=nn[L],H=(_.tier2_input_tokens||0)/1e6*R.input*.5+(_.tier2_output_tokens||0)/1e6*R.output*.5+(_.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(_.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,ee=(_.input_tokens||0)+(_.tier2_input_tokens||0),B=(_.output_tokens||0)+(_.tier2_output_tokens||0),D=(_.cache_read_tokens||0)+(_.tier2_cache_read_tokens||0),N=(_.cache_create_tokens||0)+(_.tier2_cache_create_tokens||0);m+=M,_.day>=s&&(p+=M,S+=_.tasks||0),_.day>=i&&_.day<s&&(b+=M,I+=_.tasks||0),_.day===r&&(l+=M),_.day===o&&(d+=M),_.day===r&&(f+=H),_.day>=s&&(y+=H);let G=E[_.day]||(E[_.day]={date:_.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});G.tasks+=_.tasks||0,G.input+=ee,G.output+=B,G.cacheRead+=D,G.cacheCreate+=N,G.cost+=M,G.tier2+=H;let z=G.agents[_.agent_id]||(G.agents[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});z.tasks+=_.tasks||0,z.cost+=M,z.tier2+=H,z.input+=ee,z.output+=B,z.cacheRead+=D,z.cacheCreate+=N,_.model&&(z.model=_.model);let X=c[_.agent_id]||(c[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});X.tasks+=_.tasks||0,X.cost+=M,X.tier2+=H,X.input+=ee,X.output+=B,X.cacheRead+=D,X.cacheCreate+=N,_.model&&(X.model=_.model)}let u=Object.values(E).sort((_,M)=>_.date<M.date?-1:1),h=0,g=0,w=0,x=0,k=0,A=0;for(let _ of u)h+=_.tasks,g+=_.input,w+=_.output,x+=_.cacheRead,k+=_.cacheCreate,A+=_.cost;let C=Object.entries(c).map(([_,M])=>({agent_id:_,...M,tokens:M.input+M.output+M.cacheRead+M.cacheCreate})).sort((_,M)=>M.cost-_.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:m,tier2Today:f,tier2_7d:y,tier2PctToday:l>0?f/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:h,tokensRange:g+w+x+k,cacheHitRange:x+g>0?x/(x+g):0,costPerTaskRange:h>0?A/h:0,spendDeltaWoW:b>0?(p-b)/b:0,tasksDeltaWoW:I>0?(S-I)/I:0},days:u,perAgent:C}}function Cs(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+`
|
|
6077
6077
|
`+a.join(`
|
|
6078
6078
|
`)+`
|
|
6079
|
-
`}import{resolve as
|
|
6079
|
+
`}import{resolve as As}from"path";import{existsSync as Ms}from"fs";import Is from"better-sqlite3";function $s(){let t=As(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ms(t))return null;try{let e=new Is(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-dn>6e4&&(dn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var dn=0;function ge(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function js(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 cn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=$s();if(!r)return ge(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=js(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let m=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",y=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,I=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),b=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${m}`).get({since:s}).n,E=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),c=r.db.prepare(`
|
|
6080
6080
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
6081
6081
|
LEFT JOIN intent_resolutions r
|
|
6082
6082
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6083
6083
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
6084
|
-
`).get().n;return
|
|
6084
|
+
`).get().n;return ge(e,200,{since:s??null,eventsBySource:y,totalDecisions:S,decisionsByOutcome:I,totalDivergences:b,divergencesBySource:E,inFlight:c}),!0}if(n==="events"){let m=[],f={limit:p};s!==void 0&&(m.push("ts >= @since"),f.since=s),i&&(m.push("source = @source"),f.source=i),l&&(m.push("project = @project"),f.project=l);let y=`
|
|
6085
6085
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
6086
6086
|
FROM intent_events
|
|
6087
6087
|
${m.length?"WHERE "+m.join(" AND "):""}
|
|
6088
6088
|
ORDER BY ts DESC LIMIT @limit
|
|
6089
|
-
`;return
|
|
6089
|
+
`;return ge(e,200,{rows:r.db.prepare(y).all(f)}),!0}if(n==="divergences"){let m=[],f={limit:p};s!==void 0&&(m.push("ts >= @since"),f.since=s),i&&(m.push("source = @source"),f.source=i);let y=`
|
|
6090
6090
|
SELECT ts, source, decided_by,
|
|
6091
6091
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
6092
6092
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
@@ -6094,7 +6094,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6094
6094
|
FROM intent_divergences
|
|
6095
6095
|
${m.length?"WHERE "+m.join(" AND "):""}
|
|
6096
6096
|
ORDER BY ts DESC LIMIT @limit
|
|
6097
|
-
`;return
|
|
6097
|
+
`;return ge(e,200,{rows:r.db.prepare(y).all(f)}),!0}if(n==="active"){let m=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],f={limit:p};i&&(m.push("e.source = @source"),f.source=i);let y=`
|
|
6098
6098
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
6099
6099
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
6100
6100
|
FROM intent_decisions d
|
|
@@ -6103,7 +6103,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6103
6103
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6104
6104
|
WHERE ${m.join(" AND ")}
|
|
6105
6105
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
6106
|
-
`;return
|
|
6106
|
+
`;return ge(e,200,{rows:r.db.prepare(y).all(f)}),!0}return ge(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ge(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function pn(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
6107
6107
|
<header class="ax-led__head">
|
|
6108
6108
|
<h1>Intent ledger</h1>
|
|
6109
6109
|
<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>
|
|
@@ -6308,7 +6308,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6308
6308
|
}
|
|
6309
6309
|
load();
|
|
6310
6310
|
})();
|
|
6311
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
6311
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function un(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
6312
6312
|
<header class="ax-cost__head">
|
|
6313
6313
|
<div>
|
|
6314
6314
|
<h1>Cost</h1>
|
|
@@ -6881,7 +6881,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6881
6881
|
load();
|
|
6882
6882
|
setInterval(load, 30000);
|
|
6883
6883
|
})();
|
|
6884
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
6884
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function mn(t={}){let e=`<div class="ax-pj__root">
|
|
6885
6885
|
<aside class="ax-pj__list">
|
|
6886
6886
|
<header>
|
|
6887
6887
|
<h2>Projects</h2>
|
|
@@ -6908,7 +6908,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6908
6908
|
</header>
|
|
6909
6909
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
6910
6910
|
</section>
|
|
6911
|
-
</div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6911
|
+
</div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ls,scripts:`<script>${Rs}</script>`})}var Ls=`
|
|
6912
6912
|
.ax-pj__root {
|
|
6913
6913
|
display: grid;
|
|
6914
6914
|
grid-template-columns: 360px 1fr;
|
|
@@ -7095,7 +7095,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7095
7095
|
}
|
|
7096
7096
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
7097
7097
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
7098
|
-
`,
|
|
7098
|
+
`,Rs=`
|
|
7099
7099
|
(function(){
|
|
7100
7100
|
const $ = (sel) => document.querySelector(sel);
|
|
7101
7101
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -7745,22 +7745,22 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7745
7745
|
load();
|
|
7746
7746
|
});
|
|
7747
7747
|
})();
|
|
7748
|
-
`;import{resolve as
|
|
7748
|
+
`;import{resolve as wt,join as Ks}from"path";import{existsSync as kt,readdirSync as Js,readFileSync as Vs}from"fs";import Ys from"better-sqlite3";var hn=String.raw`[\w.-]+(?:/[\w.-]+)+`,Ps=new RegExp(`^(?:chat:)?(${hn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Os=new RegExp(`^\\[(?:GitLab|GitHub) (${hn}) `);function fn(t){if(!t)return null;let e=t.match(Ps);return e?e[1]:null}function vt(t){if(!t)return null;let e=t.trimStart().match(Os);return e?e[1]:null}function Xe(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():fn(typeof n?.chatId=="string"?n.chatId:null)??fn(e)??vt(a)}function Ds(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Ke(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ns=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Hs=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Bs=t=>/^issue/i.test(t)?"issue":"mr";function zs(t){let e=t.subject.match(Ns)??t.inputPreview.trimStart().match(Hs);return e?{kind:Bs(e[1]),n:Number(e[2])}:null}function qs(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 gn(t){if(!Ds(t.projectId))return[];let e=zs(t);return e?[e]:qs(t.inputPreview)}var Fs=6e4,Us=5*6e4,Ws=40,xn=6,bn=new Map;function vn(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 gn(n)){let s=Ke(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Ws)return[...e.values()]}}return[...e.values()]}async function yn(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Ke(s.project,s.ref),l=bn.get(i);l&&n-l.at<(s.github?Us:Fs)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=xn)await Promise.all(o.slice(s,s+xn).map(async i=>{let l=Ke(i.project,i.ref),d=null;try{d=i.github?await Xs(i,e,a):await Gs(i,e,a)}catch{}bn.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function wn(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 Gs(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 wn(`${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 Xs(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 wn(`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}function _t(){let t=wt(process.cwd(),".agentx/intent/ledger.sqlite");if(!kt(t))return null;try{let e=new Ys(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-kn>6e4&&(kn=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var kn=0;function le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var ke={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"},opencode:{label:"OpenCode",color:"#57606a"}};function Qs(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in ke)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in ke)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in ke)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 ke)return s}return"workflow"}return t}function En(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 Zs(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 Tn(t,e,a){return Yt(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 ei(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:F(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&&!yt(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!yt(r||o||"")){let l=r||o||s,d=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:l,name:o||r||l,avatar:F(i),kind:d}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!yt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",m=_n(p);return{id:d,name:l||i||d,avatar:F(l||i||d),kind:m}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:F(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:F(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:F(i),kind:_n(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:F(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:F(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:F(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:F(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:F(o),kind:"whatsapp"}}}return null}function _n(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function yt(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 F(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 Cn(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}
|
|
7749
7749
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
7750
|
-
${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
|
|
7750
|
+
${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 ti(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 An(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
7751
7751
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
7752
7752
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
7753
|
-
`).all(r),s=new Map,i=new Map;if(o.length>0){let x=o.map(
|
|
7753
|
+
`).all(r),s=new Map,i=new Map;if(o.length>0){let x=o.map(M=>M.id),k=x.map((M,L)=>`@id${L}`).join(","),A=Object.fromEntries(x.map((M,L)=>[`id${L}`,M])),C=t.prepare(`
|
|
7754
7754
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
7755
|
-
FROM intent_decisions WHERE event_id IN (${
|
|
7756
|
-
`).all(
|
|
7755
|
+
FROM intent_decisions WHERE event_id IN (${k}) ORDER BY decided_at ASC
|
|
7756
|
+
`).all(A);for(let M of C)s.has(M.event_id)||s.set(M.event_id,[]),s.get(M.event_id).push(M);let _=t.prepare(`
|
|
7757
7757
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
7758
|
-
FROM intent_resolutions WHERE decision_event_id IN (${
|
|
7759
|
-
`).all(
|
|
7758
|
+
FROM intent_resolutions WHERE decision_event_id IN (${k})
|
|
7759
|
+
`).all(A);for(let M of _)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,d=new Map,p=new Map,m=new Map,f=[],y=e?.business?.projects??[],S=e?.business?.contactMap??[],I=it(e?.business??{});for(let x of o){let k=null;try{k=JSON.parse(x.raw_json)}catch{}let A=Tn(x.source,k,S),C=Cn(x.source,k),_=x.project??Xe(k,x.subject,C),M=null,L=null;A?(M=A.client,L=A.project||`${A.client}/_chat`):_&&(M=je(_,y),L=_);let R=Qs(x.source,x.intent||"",k),H=ke[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:H.label,color:H.color});let ee="__system",B,D=ei(x.source,x.intent||"",k);if(D){ee=D.id,B=D.kind;let N=A?.displayName||D.name;(!m.has(D.id)||A?.displayName)&&m.set(D.id,{id:D.id,name:N,avatar:F(N),kind:D.kind})}else m.has("__system")||m.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(x.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let G=`${x.id}|${N.decided_by}`,z=i.get(G),X=N.decided_at,Ht=z?.resolved_at??null,at=Ht===null,Ar=z?.duration_ms??(at?n-X:0),Mr=at?"active":z?.status==="error"||z?.status==="fail"?"error":"completed",W,Se;if(M)W=M,Se=L;else{let nt=I.get(N.agent_id);nt?(W=nt,Se=`${nt}/_${x.source}`):(W="unmapped",Se=`unmapped/_${x.source}`)}l.has(W)||l.set(W,{id:W,name:W,color:En(W),projects:[]}),d.has(W)||d.set(W,new Set),d.get(W).add(Se),f.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:W,projectId:Se,channelId:R,initiatorId:ee,initiatorKind:B,subject:ti(x.subject),intent:x.intent||"",startedAt:X,resolvedAt:Ht,duration:Ar,active:at,outcome:Mr,tokens:0,inputPreview:C,system:Zs(N.agent_id,e)})}}let b=[...l.values()].map(x=>({...x,projects:[...d.get(x.id)||[]].sort()})).sort((x,k)=>x.id.localeCompare(k.id)),E=[],c=new Set;if(e){let x=e.business??{},k=A=>{let C=x.orgChart?.[A]?.role,_=C?x.roles?.[C]?.title:void 0;return typeof _=="string"&&_.trim()?_.trim():void 0};for(let[A,C]of Object.entries(e.agents||{})){let _={id:A,name:C.name||A,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:k(A)};E.push(_),c.add(A)}}for(let x of f)c.has(x.agentId)||(E.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),c.add(x.agentId));E.sort((x,k)=>x.id.localeCompare(k.id));let u=[],h=new Set;for(let[x,k]of Object.entries(ke))u.push({id:x,label:k.label,color:k.color}),h.add(x);for(let x of p.values())h.has(x.id)||u.push(x);let g=[...m.values()];g.find(x=>x.id==="__system")||g.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let w=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:b,agents:E,channels:u,initiators:g,dispatches:f,forges:{gitlab:typeof w=="string"?w:void 0,github:"https://github.com"}}}function St(t){let e=_t();if(!e)return null;try{return An(e.db,ce,t)}finally{e.close()}}function Mn(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let m of p.clients){let f=e.get(m.id);if(!f)e.set(m.id,{...m,projects:[...m.projects]});else{let y=Array.from(new Set([...f.projects,...m.projects])).sort();e.set(m.id,{...f,projects:y})}}for(let m of p.agents)a.has(m.id)||a.set(m.id,m);for(let m of p.channels)n.has(m.id)||n.set(m.id,m);for(let m of p.initiators)r.has(m.id)||r.set(m.id,m);for(let m of p.dispatches){let f=ai(m);if(f.clientId!==m.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:En(f.clientId),projects:[]}),f.projectId!==m.projectId){let y=e.get(f.clientId);y.projects.includes(f.projectId)||e.set(f.clientId,{...y,projects:[...y.projects,f.projectId].sort()})}o.push({...f,nodeId:d,id:`${d}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,p)=>d.id.localeCompare(p.id)),agents:[...a.values()].sort((d,p)=>d.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,p)=>p.startedAt-d.startedAt)}}function ai(t){if(t.clientId!=="unmapped")return t;let e=vt(t.inputPreview);if(!e)return t;let a=ce?.business?.projects??[];return{...t,projectId:e,clientId:je(e,a)}}async function Je(t){let e=ce?.channels?.gitlab,a=await yn(vn(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 ce=null;function In(t){ce=t}async function $n(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=_t();if(!n)return le(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=jn(parseInt(r.searchParams.get("hours")||"6",10));le(e,200,await Je(An(n.db,ce,o)))}catch(r){le(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var ni=5e3;async function Et(t,e,a,n=St){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
|
|
7760
7760
|
|
|
7761
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
7761
|
+
`);let r=new URL(t.url||"/","http://_"),o=jn(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
|
|
7762
7762
|
|
|
7763
|
-
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),m=p&&await
|
|
7763
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),m=p&&await Je(p);if(s)break;m?(e.write(`event: snapshot
|
|
7764
7764
|
`),e.write(`data: ${JSON.stringify(m)}
|
|
7765
7765
|
|
|
7766
7766
|
`)):e.write(`event: error
|
|
@@ -7769,7 +7769,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
7769
7769
|
`)}catch(p){e.write(`event: error
|
|
7770
7770
|
data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
7771
7771
|
|
|
7772
|
-
`)}let
|
|
7772
|
+
`)}let d=Date.now();for(;!s&&Date.now()-d<ni;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function jn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function ri(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=wt(process.cwd(),".agentx/task-history",t,n);if(!kt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=wt(process.cwd(),".agentx/task-history",t,o);return kt(s)?Sn(s,e,a):null}return Sn(r,e,a)}function Sn(t,e,a){let n=null,r=1/0;for(let o of Js(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Vs(Ks(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function Ln(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 le(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=_t();if(!l)return le(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return le(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return le(e,404,{error:"decision not found"}),!0;let m=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(d.raw_json)}catch{}let y=Cn(d.source,f),S=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)||y,I=null,b=null;if(p.agent_id){let w=ri(p.agent_id,p.decided_at);if(w){typeof w.responseText=="string"&&(I=w.responseText);let x=w.transcript;Array.isArray(x)&&(b=x.length)}}let E=ce?.business?.projects??[],c=ce?.business?.contactMap??[],u=it(ce?.business??{}),h={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},g=Tn(d.source,f,c);if(g)h={client:g.client,project:g.project||`${g.client}/_chat`,via:`contactMap (channel=${g.channel??"*"}${g.username?` username=${g.username}`:""}${g.chatId?` chatId=${g.chatId}`:""})`};else if(d.project||Xe(f,d.subject,y)){let w=d.project||Xe(f,d.subject,y);h={client:je(w,E),project:w,via:d.project?`project namespace prefix (${w})`:`forge path in chat id / message (${w})`}}else if(p.agent_id){let w=u.get(p.agent_id);w&&(h={client:w,project:`${w}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${w})`})}le(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:m?.resolved_at??null,durationMs:m?.duration_ms??null,input:S,response:I,transcriptLen:b,resolutionStatus:m?.status??null,resultSummary:m?.result_summary??null,attribution:h})}catch(d){le(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as li,readFileSync as di}from"fs";import{resolve as Pn}from"path";rt();function Rn(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=oi.replace(/__AGENT_ID__/g,P(e));return $({title:`AgentX \xB7 ${P(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${P(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:si,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>${ii}</script>`})}var oi=`
|
|
7773
7773
|
<!-- Breadcrumb -->
|
|
7774
7774
|
<div class="ax-crumb">
|
|
7775
7775
|
<a href="/admin">Settings</a>
|
|
@@ -8358,7 +8358,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
|
8358
8358
|
</div>
|
|
8359
8359
|
</div>
|
|
8360
8360
|
</div>
|
|
8361
|
-
`,
|
|
8361
|
+
`,si=`
|
|
8362
8362
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
8363
8363
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
8364
8364
|
* primitives live in components.css.ts. */
|
|
@@ -8477,7 +8477,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
8477
8477
|
|
|
8478
8478
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
8479
8479
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
8480
|
-
`,
|
|
8480
|
+
`,ii=`
|
|
8481
8481
|
const $ = (id) => document.getElementById(id);
|
|
8482
8482
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
8483
8483
|
|
|
@@ -9331,15 +9331,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
9331
9331
|
/* ===== Boot ===== */
|
|
9332
9332
|
initOptsToggles();
|
|
9333
9333
|
loadAgent();
|
|
9334
|
-
`;function
|
|
9335
|
-
`);return
|
|
9336
|
-
`);return
|
|
9334
|
+
`;function On(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rn({agentId:a,peers:n,localToken:r}))}async function Dn(t,e,a){try{let n=t.method==="GET"?void 0:await $i(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){Ve(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,m={"GET ":()=>Ce(i),"PATCH ":()=>ci(i,n),"PATCH capability":()=>mi(i,n),"POST mcp":()=>pi(i,n),"DELETE mcp":()=>ui(i,n),"GET identity":()=>fi(i),"GET identity/file":()=>hi(i,String(o.path||"")),"PUT identity/file":()=>gi(i,n),"GET skills":()=>xi(i),"POST skills":()=>bi(i,n),"DELETE skills":()=>vi(i,n),"GET skills/tree":()=>yi(i,String(o.slug||"")),"GET skills/file":()=>wi(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>ki(i,n),"GET skills/deps":()=>_i(i,String(o.slug||"")),"POST skills/install":()=>Si(i,n,t),"POST skills/deps":()=>Ei(i,n,t),"GET channels":()=>Ti(i),"GET activity":()=>Ci(i,t),"GET handovers":()=>Ai(i),"POST handovers":()=>Mi(i,n),"DELETE handovers":()=>Ii(n)}[d];if(!m){Ve(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await m();Ve(e,200,f)}catch(n){Ve(e,400,{error:n?.message||"agent op failed"})}}function Nn(){let t=Pn(process.cwd(),"agentx.json");return li(t)?JSON.parse(di(t,"utf-8")):null}function U(t){let e=Nn();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 Ce(t){let{def:e,cfg:a}=U(t),n=e.workspace?be(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",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 ci(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}=T(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:Ce(t)}}function pi(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}=T(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:Ce(t)}}function ui(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=T(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:Ce(t)}}function mi(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}=T(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:Ce(t)}}function fi(t){let{def:e}=U(t);return be(e.workspace)}function hi(t,e){if(!e)throw new Error("path query param required");let{def:a}=U(t);return Pe(a.workspace,e)}function gi(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=U(t);return Oe(n.workspace,a,String(e?.content??""))}function xi(t){let{def:e}=U(t),a=be(e.workspace);return{skills:a.skills,workspace:a.workspace}}function bi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=U(t);return De(n.workspace,a,{title:e?.title,content:e?.content})}function vi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=U(t);return Ne(n.workspace,a)}function yi(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t),n=la(a.workspace,e),r=He(a.workspace,e);return{slug:e,tree:n,deps:r}}function wi(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=U(t);return da(n.workspace,e,a)}function ki(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=U(t);return ca(r.workspace,a,n,String(e?.content??""))}function _i(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t);return He(a.workspace,e)}async function Si(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=Hn(e?.worker),{def:o}=U(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(`
|
|
9335
|
+
`);return Bn(a,r,s,`install-${n}:${Date.now()}`)}async function Ei(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Hn(e?.worker),{def:o}=U(t),s=He(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=Pn(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(`
|
|
9336
|
+
`);return Bn(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Hn(t){if(t&&typeof t=="string")return t;let e=K();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Bn(t,e,a,n){let r=K(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),p;try{p=JSON.parse(d)}catch{p={content:d}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Ti(t){let e=Nn(),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 Ci(t,e){try{let n=(K().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 Tt(){return new Ut}function Ai(t){let e=Tt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Mi(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=Tt().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function Ii(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:Tt().remove(e,a,n)?"Released":"No active handover for that chat"}}function Ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $i(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 xe={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 zn=[{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 Ct(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(xe)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
9337
9337
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
9338
9338
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
9339
9339
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
9340
9340
|
<main id="grid" class="ax-live__body"></main>
|
|
9341
9341
|
</div>
|
|
9342
|
-
`;return $({title:`${
|
|
9342
|
+
`;return $({title:`${xe.brand} \xB7 ${xe.subtitle}`,activeTab:"live",subtitle:xe.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:ji,scripts:e+`<script>${Li}</script>`,headExtras:`<script>
|
|
9343
9343
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
9344
9344
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
9345
9345
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -9350,7 +9350,7 @@ loadAgent();
|
|
|
9350
9350
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
9351
9351
|
right.insertBefore(extras, right.firstChild);
|
|
9352
9352
|
});
|
|
9353
|
-
</script>`})}var
|
|
9353
|
+
</script>`})}var ji=`
|
|
9354
9354
|
/* --- Page frame --- */
|
|
9355
9355
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
9356
9356
|
|
|
@@ -9369,6 +9369,10 @@ loadAgent();
|
|
|
9369
9369
|
.ax-node__tag--wait { color: var(--ax-warn, var(--ax-text-2)); border-color: currentColor; }
|
|
9370
9370
|
.ax-node__name { font-weight: 600; font-size: 14px; }
|
|
9371
9371
|
.ax-node__url { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 11px; }
|
|
9372
|
+
.ax-node__sessions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 10px 16px 0; font-size: 12px; color: var(--ax-muted); }
|
|
9373
|
+
.ax-node__session { display: inline-flex; gap: 6px; align-items: center; padding: 2px 8px; border: 1px solid var(--ax-line, currentColor); border-radius: 999px; color: var(--ax-text-2, inherit); }
|
|
9374
|
+
.ax-node__session.is-bound { color: var(--ax-text, inherit); border-color: var(--ax-accent, currentColor); }
|
|
9375
|
+
.ax-node__session.is-waiting { border-style: dashed; }
|
|
9372
9376
|
.ax-node__tag {
|
|
9373
9377
|
font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px;
|
|
9374
9378
|
padding: 2px 7px; border-radius: 3px; border: 1px solid var(--ax-border-2);
|
|
@@ -9553,7 +9557,7 @@ loadAgent();
|
|
|
9553
9557
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
9554
9558
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
9555
9559
|
}
|
|
9556
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
9560
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,Li=`
|
|
9557
9561
|
'use strict';
|
|
9558
9562
|
|
|
9559
9563
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -9705,13 +9709,16 @@ function runningBodyHtml(rows) {
|
|
|
9705
9709
|
function renderNode(node) {
|
|
9706
9710
|
const sec = document.createElement('section');
|
|
9707
9711
|
sec.className = 'ax-node';
|
|
9708
|
-
|
|
9712
|
+
// #193 \u2014 a briefly slow node keeps its last good data, marked stale.
|
|
9713
|
+
const tag = node.stale
|
|
9714
|
+
? '<span class="ax-node__tag ax-node__tag--wait" role="status" title="' + escapeHtml(node.error || '') + '">not responding \xB7 data from ' + escapeHtml(fmtAgo(node.staleSince)) + '</span>'
|
|
9715
|
+
: node.reachable
|
|
9709
9716
|
? '<span class="ax-node__tag ax-node__tag--up">online \xB7 ' + (node.uptimeSec ? Math.round(node.uptimeSec / 60) + 'm' : '\u2014') + '</span>'
|
|
9710
9717
|
: '<span class="ax-node__tag ax-node__tag--down">offline \u2014 ' + escapeHtml(node.error || 'unreachable') + '</span>';
|
|
9711
9718
|
sec.innerHTML = '<header>' +
|
|
9712
9719
|
'<span class="ax-node__name">' + escapeHtml(node.name) + '</span>' +
|
|
9713
9720
|
'<span class="ax-node__url">' + escapeHtml(node.url) + '</span>' +
|
|
9714
|
-
tag + restartHtml(node) + '</header
|
|
9721
|
+
tag + (node.stale ? '' : restartHtml(node)) + '</header>' + sessionsHtml(node) + '<div class="ax-grid--agents"></div>';
|
|
9715
9722
|
const g = sec.querySelector('.ax-grid--agents');
|
|
9716
9723
|
if (!node.reachable || node.agents.length === 0) {
|
|
9717
9724
|
const empty = document.createElement('div');
|
|
@@ -9725,6 +9732,22 @@ function renderNode(node) {
|
|
|
9725
9732
|
return sec;
|
|
9726
9733
|
}
|
|
9727
9734
|
|
|
9735
|
+
// #193 \u2014 Claude Code sessions registered with this node's attach hooks. A
|
|
9736
|
+
// bound one says which agent it answers for; "waiting" means the binding is
|
|
9737
|
+
// saved but the session has not reported since a restart or an idle spell.
|
|
9738
|
+
function sessionsHtml(node) {
|
|
9739
|
+
const rows = node.attachSessions || [];
|
|
9740
|
+
if (!rows.length) return '';
|
|
9741
|
+
const chips = rows.map(r => {
|
|
9742
|
+
const who = r.agentIds.length ? 'as ' + r.agentIds.join(', ') : 'not attached';
|
|
9743
|
+
const when = r.waiting ? 'waiting for session' : 'seen ' + fmtAgo(new Date(r.lastSeenAt).toISOString());
|
|
9744
|
+
const cls = 'ax-node__session' + (r.agentIds.length ? ' is-bound' : '') + (r.waiting ? ' is-waiting' : '');
|
|
9745
|
+
return '<span class="' + cls + '" title="session ' + escapeHtml(r.session) + ' \xB7 ' + escapeHtml(r.mode) + (r.pending ? ' \xB7 ' + r.pending + ' queued' : '') + '">' +
|
|
9746
|
+
'<b>' + escapeHtml(r.project || r.session) + '</b> ' + escapeHtml(who) + ' \xB7 ' + escapeHtml(when) + '</span>';
|
|
9747
|
+
}).join('');
|
|
9748
|
+
return '<div class="ax-node__sessions" aria-label="Claude Code sessions"><span>Claude Code sessions</span>' + chips + '</div>';
|
|
9749
|
+
}
|
|
9750
|
+
|
|
9728
9751
|
// "Restart when idle": the node restarts itself once no task is running.
|
|
9729
9752
|
// Only nodes that report restart state (GET /health) offer it.
|
|
9730
9753
|
function restartHtml(node) {
|
|
@@ -9838,7 +9861,9 @@ function renderAgent(a, node) {
|
|
|
9838
9861
|
'</div>'
|
|
9839
9862
|
: (busy ? '' : '<div class="ax-agent__summary"><div class="ax-agent__summary-caption">' + escapeHtml(L.idle || 'idle') + '</div><div class="ax-agent__summary-text" style="font-style:italic;color:var(--ax-muted)">' + escapeHtml(L.neverRan || 'awaiting first task') + '</div></div>');
|
|
9840
9863
|
|
|
9841
|
-
const lastActiveText = a.
|
|
9864
|
+
const lastActiveText = (a.attached && !a.attached.waiting)
|
|
9865
|
+
? 'Claude Code \xB7 ' + a.attached.project + ' \xB7 active ' + fmtAgo(new Date(a.attached.lastSeenAt).toISOString())
|
|
9866
|
+
: a.lastActive ? 'last active ' + fmtAgo(a.lastActive) : (L.neverRan || 'not used yet');
|
|
9842
9867
|
const lastActiveAttr = a.lastActive ? ' data-last-active="' + escapeHtml(a.lastActive) + '"' : '';
|
|
9843
9868
|
const recentLink = nodeUrl
|
|
9844
9869
|
? '<button class="ax-linkbtn" data-agent-id="' + escapeHtml(a.id) + '" data-agent-name="' + escapeHtml(a.name || a.id) + '" data-node-url="' + escapeHtml(nodeUrl) + '" data-recent="1">history \u2192</button>'
|
|
@@ -9850,6 +9875,12 @@ function renderAgent(a, node) {
|
|
|
9850
9875
|
? '<span class="ax-badge ax-badge--mono ax-badge--live"><span class="ax-dot ax-dot--live ax-dot--pulse"></span> live</span>'
|
|
9851
9876
|
: (errored ? '<span class="ax-badge ax-badge--mono ax-badge--warn">errored</span>' : '<span class="ax-badge ax-badge--mono ax-badge--ghost">idle</span>');
|
|
9852
9877
|
const tierBadge = tierDisplay ? '<span class="ax-badge ax-badge--mono ax-badge--ghost" title="AI engine">' + escapeHtml(tierDisplay) + '</span>' : '';
|
|
9878
|
+
// #193 \u2014 the Claude Code session answering for this agent.
|
|
9879
|
+
const at = a.attached;
|
|
9880
|
+
const attachBadge = at
|
|
9881
|
+
? '<span class="ax-badge ax-badge--mono ' + (at.waiting ? 'ax-badge--ghost' : 'ax-badge--live') + '" title="Claude Code session ' + escapeHtml(at.session) + ' in ' + escapeHtml(at.project) + ' \xB7 ' + escapeHtml(at.mode) + '">' +
|
|
9882
|
+
(at.waiting ? 'waiting' : 'attached') + '</span>'
|
|
9883
|
+
: '';
|
|
9853
9884
|
|
|
9854
9885
|
const head =
|
|
9855
9886
|
'<div class="ax-agent__head">' +
|
|
@@ -9857,7 +9888,7 @@ function renderAgent(a, node) {
|
|
|
9857
9888
|
'<span class="ax-mention">' + escapeHtml(mention) + '</span>' +
|
|
9858
9889
|
'<span class="ax-agent__name">' + escapeHtml(a.name || a.id) + '</span>' +
|
|
9859
9890
|
'</div>' +
|
|
9860
|
-
'<div class="ax-agent__tier">' + tierBadge + liveBadge + '</div>' +
|
|
9891
|
+
'<div class="ax-agent__tier">' + attachBadge + tierBadge + liveBadge + '</div>' +
|
|
9861
9892
|
'</div>';
|
|
9862
9893
|
|
|
9863
9894
|
// An idle agent collapses to one line.
|
|
@@ -10097,7 +10128,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10097
10128
|
});
|
|
10098
10129
|
}
|
|
10099
10130
|
|
|
10100
|
-
`;var
|
|
10131
|
+
`;var qn=`
|
|
10101
10132
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
10102
10133
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
10103
10134
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -10271,7 +10302,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10271
10302
|
.mx-summary{max-width:56vw}
|
|
10272
10303
|
}
|
|
10273
10304
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
10274
|
-
`;var
|
|
10305
|
+
`;var Fn=`<script>
|
|
10275
10306
|
window.MX=(function(){
|
|
10276
10307
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
10277
10308
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -10380,7 +10411,7 @@ window.MX=(function(){
|
|
|
10380
10411
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
10381
10412
|
setHealth:setHealth,get:get};
|
|
10382
10413
|
})();
|
|
10383
|
-
</script>`;var
|
|
10414
|
+
</script>`;var Un=`<script>
|
|
10384
10415
|
window.MXD=(function(){
|
|
10385
10416
|
function el(id){return document.getElementById(id)}
|
|
10386
10417
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -10594,7 +10625,7 @@ window.MXD=(function(){
|
|
|
10594
10625
|
|
|
10595
10626
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
10596
10627
|
})();
|
|
10597
|
-
</script>`;var
|
|
10628
|
+
</script>`;var Wn=`<script>
|
|
10598
10629
|
(function(){
|
|
10599
10630
|
var LANES=[
|
|
10600
10631
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -10910,7 +10941,7 @@ window.MXD=(function(){
|
|
|
10910
10941
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
10911
10942
|
load();
|
|
10912
10943
|
})();
|
|
10913
|
-
</script>`;var
|
|
10944
|
+
</script>`;var Gn=`<script>
|
|
10914
10945
|
(function(){
|
|
10915
10946
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
10916
10947
|
var esc=MX.esc;
|
|
@@ -11088,7 +11119,7 @@ window.MXD=(function(){
|
|
|
11088
11119
|
}
|
|
11089
11120
|
load();setInterval(load,5000);
|
|
11090
11121
|
})();
|
|
11091
|
-
</script>`;var
|
|
11122
|
+
</script>`;var Xn=`
|
|
11092
11123
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
11093
11124
|
.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}
|
|
11094
11125
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -11129,7 +11160,7 @@ window.MXD=(function(){
|
|
|
11129
11160
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
11130
11161
|
.mx-rt-name{max-width:100%}
|
|
11131
11162
|
}
|
|
11132
|
-
`,
|
|
11163
|
+
`,Kn=`<script>
|
|
11133
11164
|
(function(){
|
|
11134
11165
|
var root=document.getElementById('mx-routines');
|
|
11135
11166
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -11256,12 +11287,12 @@ window.MXD=(function(){
|
|
|
11256
11287
|
syncBar();
|
|
11257
11288
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
11258
11289
|
})();
|
|
11259
|
-
</script>`;var Q={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>',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 Z(t,e,a,n,r=""){return q({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var
|
|
11290
|
+
</script>`;var Q={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>',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 Z(t,e,a,n,r=""){return q({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Ri=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Pi=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Oi=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Jn(t){let e=Be({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+ze([{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">
|
|
11260
11291
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
11261
|
-
${
|
|
11292
|
+
${Pi.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("")}
|
|
11262
11293
|
</div>
|
|
11263
11294
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
11264
|
-
${
|
|
11295
|
+
${Oi.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
11265
11296
|
</div>
|
|
11266
11297
|
</div>
|
|
11267
11298
|
<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">
|
|
@@ -11314,7 +11345,7 @@ window.MXD=(function(){
|
|
|
11314
11345
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
11315
11346
|
${Z(Q.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>')}
|
|
11316
11347
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
11317
|
-
${
|
|
11348
|
+
${Ri.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11318
11349
|
</div>
|
|
11319
11350
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
11320
11351
|
</section>
|
|
@@ -11347,7 +11378,7 @@ window.MXD=(function(){
|
|
|
11347
11378
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
11348
11379
|
</header>
|
|
11349
11380
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
11350
|
-
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
11381
|
+
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:qn+Xn,scripts:Fn+Di+Un+Wn+Kn+Gn})}var Di=`<script>
|
|
11351
11382
|
(function(){
|
|
11352
11383
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
11353
11384
|
var range=document.getElementById('mx-range');
|
|
@@ -11375,7 +11406,7 @@ window.MXD=(function(){
|
|
|
11375
11406
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
11376
11407
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
11377
11408
|
})();
|
|
11378
|
-
</script>`;async function
|
|
11409
|
+
</script>`;async function Vn(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Ni(s,e.days)}function Ni(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,p=0,m=0,f=0,y=0,S=0;for(let{node:b,data:E}of t)if(E){a.runs+=E.totals.runs,a.errors+=E.totals.errors,a.hours+=E.totals.hours,a.agents+=E.totals.agents,a.threads+=E.totals.threads;for(let c of E.days){let u=n.get(c.day)||{day:c.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])u[h][0]+=c[h]?.[0]||0,u[h][1]+=c[h]?.[1]||0;n.set(c.day,u)}for(let c of E.origins){let u=r.get(c.channel)||{channel:c.channel,runs:0,errors:0,hours:0};u.runs+=c.runs,u.errors+=c.errors,u.hours+=c.hours,r.set(c.channel,u)}for(let c of E.causes){let u=o.get(c.cause)||{cause:c.cause,count:0,agents:[],example:""};u.count+=c.count;for(let h of c.agents)u.agents.includes(h)||u.agents.push(h);u.example||(u.example=c.example),o.set(c.cause,u)}for(let c of E.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=E.rotations.total,p+=E.rotations.tokenSum||0,m+=E.rotations.tokenSamples||0,f=Math.max(f,E.rotations.maxTokens),y+=E.retention.traces,S+=E.retention.tracesWithSteps;for(let c of E.jobs)i.push({...c,node:b.name,nodeUrl:b.url});for(let c of E.threads)l.push({...c,node:b.name,nodeUrl:b.url})}let I=t.filter(b=>b.data).map(b=>b.data.since).filter(b=>Number.isFinite(b));return{generatedAt:Date.now(),windowDays:e,since:I.length?Math.min(...I):Date.now()-e*864e5,nodes:t.map(b=>({name:b.node.name,url:b.node.url,ok:!!b.data,error:b.error,runs:b.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((b,E)=>b.day.localeCompare(E.day)),origins:[...r.values()].map(b=>({...b,hours:Math.round(b.hours*100)/100})).sort((b,E)=>E.runs-b.runs),causes:[...o.values()].sort((b,E)=>E.count-b.count),jobs:i.sort((b,E)=>E.hours-b.hours),threads:l.sort((b,E)=>E.lastAt-E.firstAt-(b.lastAt-b.firstAt)||E.runs-b.runs),rotations:{total:d,byReason:[...s.entries()].map(([b,E])=>({reason:b,count:E})).sort((b,E)=>E.count-b.count),tokenSum:p,tokenSamples:m,maxTokens:f},retention:{traces:y,tracesWithSteps:S}}}async function Yn(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 Qn(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Hi(s,e.day)}function Hi(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function Zn(t={}){let e=`
|
|
11379
11410
|
<select id="boardPicker" title="Switch board"></select>
|
|
11380
11411
|
<div class="search">
|
|
11381
11412
|
<span class="icon">\u2315</span>
|
|
@@ -11476,7 +11507,7 @@ window.MXD=(function(){
|
|
|
11476
11507
|
</footer>
|
|
11477
11508
|
</div>
|
|
11478
11509
|
</div>
|
|
11479
|
-
<script src="/sortable.min.js"></script>`;return $({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:
|
|
11510
|
+
<script src="/sortable.min.js"></script>`;return $({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Bi,scripts:`<script>${zi}</script>`,headExtras:`<script>
|
|
11480
11511
|
// The boards page has its own connection dot + wants body height:100%
|
|
11481
11512
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
11482
11513
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -11492,7 +11523,7 @@ window.MXD=(function(){
|
|
|
11492
11523
|
right.insertBefore(dot, right.firstChild);
|
|
11493
11524
|
}
|
|
11494
11525
|
});
|
|
11495
|
-
</script>`})}var
|
|
11526
|
+
</script>`})}var Bi=`
|
|
11496
11527
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
11497
11528
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
11498
11529
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -11745,7 +11776,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
11745
11776
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
11746
11777
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
11747
11778
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
11748
|
-
`,
|
|
11779
|
+
`,zi=`
|
|
11749
11780
|
'use strict';
|
|
11750
11781
|
const state = {
|
|
11751
11782
|
boards: [], current: null, items: {},
|
|
@@ -12798,9 +12829,9 @@ function appendEvents(events) {
|
|
|
12798
12829
|
}
|
|
12799
12830
|
|
|
12800
12831
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
12801
|
-
`;function
|
|
12832
|
+
`;function er(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
12802
12833
|
<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>
|
|
12803
|
-
${
|
|
12834
|
+
${zn.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${P(n.alias)}</span>`:"";return`<article class="term"><h3>${P(n.term)}${r}</h3><p>${P(n.definition)}</p></article>`}).join("")}`;return $({title:`${xe.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:qi})}var qi=`
|
|
12804
12835
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
12805
12836
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
12806
12837
|
.lead {
|
|
@@ -12830,7 +12861,7 @@ article.term .alias {
|
|
|
12830
12861
|
}
|
|
12831
12862
|
article.term p {
|
|
12832
12863
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
12833
|
-
}`;function
|
|
12864
|
+
}`;function tr(t={}){let e=`<div class="ax-wf__root">
|
|
12834
12865
|
<aside class="ax-wf__list">
|
|
12835
12866
|
<header>
|
|
12836
12867
|
<h2>Workflows</h2>
|
|
@@ -12907,7 +12938,7 @@ article.term p {
|
|
|
12907
12938
|
</aside>
|
|
12908
12939
|
</div>
|
|
12909
12940
|
|
|
12910
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return $({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
12941
|
+
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return $({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Fi,scripts:`<script>${ve({workflowHealth:Vt})}${Ui}</script>`})}var Fi=`
|
|
12911
12942
|
.ax-wf__root {
|
|
12912
12943
|
display: grid;
|
|
12913
12944
|
grid-template-columns: 340px 1fr;
|
|
@@ -13291,7 +13322,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13291
13322
|
font-size: 12px; z-index: 50;
|
|
13292
13323
|
}
|
|
13293
13324
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
13294
|
-
`,
|
|
13325
|
+
`,Ui=`
|
|
13295
13326
|
(() => {
|
|
13296
13327
|
const $ = (sel) => document.querySelector(sel)
|
|
13297
13328
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -14080,7 +14111,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14080
14111
|
setInterval(refresh, 15000)
|
|
14081
14112
|
})
|
|
14082
14113
|
})();
|
|
14083
|
-
`;function
|
|
14114
|
+
`;function ar(t={}){let e=`<div class="ax-proc__root">
|
|
14084
14115
|
<header class="ax-proc__header">
|
|
14085
14116
|
<h1>Procedures</h1>
|
|
14086
14117
|
<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>
|
|
@@ -14124,7 +14155,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14124
14155
|
<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>
|
|
14125
14156
|
<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>
|
|
14126
14157
|
</section>
|
|
14127
|
-
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
14158
|
+
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Wi,scripts:`<script>${Gi}</script>`})}var Wi=`
|
|
14128
14159
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
14129
14160
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14130
14161
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -14150,7 +14181,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14150
14181
|
.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); }
|
|
14151
14182
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
14152
14183
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
14153
|
-
`,
|
|
14184
|
+
`,Gi=`
|
|
14154
14185
|
(function(){
|
|
14155
14186
|
function $(sel){ return document.querySelector(sel) }
|
|
14156
14187
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -14250,7 +14281,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14250
14281
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
14251
14282
|
else bootAll()
|
|
14252
14283
|
})();
|
|
14253
|
-
`;function
|
|
14284
|
+
`;function nr(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
14254
14285
|
data-task-id="${P(t.taskId)}"
|
|
14255
14286
|
data-agent-id="${P(t.agentId)}"
|
|
14256
14287
|
data-node-url="${P(t.nodeUrl)}"
|
|
@@ -14293,7 +14324,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14293
14324
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
14294
14325
|
</div>
|
|
14295
14326
|
</footer>
|
|
14296
|
-
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14327
|
+
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Xi,scripts:`<script>${Ki}</script>`})}var Xi=`
|
|
14297
14328
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
14298
14329
|
the sticky topbar. Breathe. */
|
|
14299
14330
|
.ax-task-page {
|
|
@@ -14435,7 +14466,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14435
14466
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
14436
14467
|
}
|
|
14437
14468
|
|
|
14438
|
-
`,
|
|
14469
|
+
`,Ki=`
|
|
14439
14470
|
(function () {
|
|
14440
14471
|
var root = document.querySelector('.ax-task-page');
|
|
14441
14472
|
if (!root) return;
|
|
@@ -14820,7 +14851,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14820
14851
|
});
|
|
14821
14852
|
|
|
14822
14853
|
})();
|
|
14823
|
-
`;function
|
|
14854
|
+
`;function rr(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
14824
14855
|
data-agent-id="${P(t.agentId)}"
|
|
14825
14856
|
data-agent-name="${P(e)}"
|
|
14826
14857
|
data-node-url="${P(t.nodeUrl)}">
|
|
@@ -14849,7 +14880,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14849
14880
|
<div class="ax-history__list" id="hist-list">
|
|
14850
14881
|
<div class="ax-history__empty">loading\u2026</div>
|
|
14851
14882
|
</div>
|
|
14852
|
-
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14883
|
+
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ji,scripts:`<script>${Vi}</script>`})}var Ji=`
|
|
14853
14884
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
14854
14885
|
flush against the sticky topbar. */
|
|
14855
14886
|
.ax-history {
|
|
@@ -14901,7 +14932,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14901
14932
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
14902
14933
|
}
|
|
14903
14934
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
14904
|
-
|
|
14935
|
+
`,Vi=`
|
|
14905
14936
|
(function () {
|
|
14906
14937
|
var root = document.querySelector('.ax-history');
|
|
14907
14938
|
if (!root) return;
|
|
@@ -15001,11 +15032,542 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15001
15032
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
15002
15033
|
});
|
|
15003
15034
|
})();
|
|
15004
|
-
`;function
|
|
15035
|
+
`;function sr(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"])?j(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 _e(t,e,l=>or(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Qi(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return j(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return j(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?_e(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return j(e,200,{ok:!0,emission:d})}):j(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"])?j(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?_e(t,e,l=>{try{let d=a.layouts.save(s,l);return j(e,200,{layout:d})}catch(d){return j(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?_e(t,e,l=>{let d=ot.safeParse(l);if(!d.success)return j(e,200,{ok:!1,issues:d.error.issues.map(m=>({path:m.path.join("."),message:m.message}))});let p=st(d.data).map(m=>({path:"",message:m}));return j(e,200,{ok:p.length===0,issues:p,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?j(e,200,{workflow:l}):j(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return _e(t,e,p=>or(e,a,p,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),j(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return j(e,404,{error:"unknown workflows endpoint",path:n})}var Yi=["mesh"];function or(t,e,a,n){let r=ot.safeParse(a);if(!r.success)return j(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=st(o);if(s.length>0)return j(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return j(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return j(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,d=e.store.get(n.id);if(d)for(let p of Yi)!(p in l)&&p in d&&(o[p]=d[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),p=l?.yamlPath,m=!!p||/yaml round-trip failed/.test(d);return j(t,m?409:500,{error:m?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:m?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),j(t,200,{workflow:i})}function Qi(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",m=a.runs.list({workflowId:d,limit:l});if(!p)return j(e,200,{runs:m});let f=m.map(y=>({id:y.id,workflowId:y.workflowId,workflowVersion:y.workflowVersion,homeNode:y.homeNode,status:y.status,pending:y.pending,entityRef:y.entityRef,history:(y.history||[]).slice(-5),parentRunId:y.parentRunId,parentNodeId:y.parentNodeId,rootRunId:y.rootRunId,depth:y.depth,createdAt:y.createdAt,updatedAt:y.updatedAt}));return j(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return j(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return _e(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?j(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?j(e,200,{ok:!0,runId:l,status:p}):j(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return Zi(t,e,a,l);let d=a.runs.get(l);return d?j(e,200,{run:d}):j(e,404,{error:"run not found"})}return j(e,404,{error:"unknown runs endpoint"})}function Zi(t,e,a,n){let r=a.runs.get(n);if(!r)return j(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)}
|
|
15005
15036
|
|
|
15006
15037
|
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=m=>{if(!o)try{e.write(`data: ${JSON.stringify(m)}
|
|
15007
15038
|
|
|
15008
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),
|
|
15039
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let m=a.runs.get(n);m&&m.updatedAt!==d&&(d=m.updatedAt,i(m))},2e3);return!0}function _e(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){j(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{j(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{j(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>j(e,400,{error:"body read failed",message:r.message})),!0}function j(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{deflateSync as el}from"zlib";var tl=[41,121,255],al=[255,255,255],ir=new Map;function Mt(t){let e=ir.get(t);return e||(e=rl(t,nl(t)),ir.set(t,e)),e}function nl(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,d=i*i+l*l<=r*r?al:tl;a.set(d,o*e+1+s*3)}return a}function rl(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]),At("IHDR",a),At("IDAT",el(e)),At("IEND",Buffer.alloc(0))])}function At(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(sl(n)),Buffer.concat([a,n,r])}var ol=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 sl(t){let e=4294967295;for(let a of t)e=ol[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function Ye(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 il(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:Ye(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:Ye(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:Ye(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function ll(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:Ye(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var dl=/^\/api\/app\/tasks\/(cancel|followup)$/;async function lr(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 y=cl(s.searchParams.get("timezone")),S=await o.snapshot({date:pl(y),timezone:y});return a==="/api/app/activity"?ne(e,200,{ts:S.ts,tasks:ll(S.nodes)}):ne(e,200,{ts:S.ts,nodes:S.nodes.map(il)})}if(n==="GET"&&a==="/api/app/approvals")return ne(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(dl);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let d;try{d=await It(t)}catch(y){return ne(e,400,{error:y.message})}let p=Ae(d.node);if(!p)return ne(e,400,{error:"node is required"});let m=`operator (phone: ${r})`,f;if(i){let y=Ae(d.taskId);if(!y)return ne(e,400,{error:"taskId is required"});let S=`/api/tasks/${encodeURIComponent(y)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,S,{reason:`cancelled by ${m}`});else{let I=Ae(d.message);if(!I)return ne(e,400,{error:"message is required"});f=await o.nodePost(p,S,{message:I,sender:m})}}else if(a==="/api/app/nodes/restart")f=await o.nodePost(p,d.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")f=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let y=Ae(d.cronId);if(!y||typeof d.enabled!="boolean")return ne(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(y)}/enabled`,{enabled:d.enabled})}else{let y=Ae(d.key),S=d.action;if(!y||S!=="yes"&&S!=="no"&&S!=="later")return ne(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,y,S,m)}return ne(e,f.status,f.body)}function Ae(t){return typeof t=="string"?t.trim():""}function cl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function pl(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function It(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 ne(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var ul=2048,dr=/^[A-Za-z0-9_-]{8,256}$/;async function cr(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 re(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(y=>y.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return re(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return re(e,404,{error:"not found"});if(!s||l)return re(e,503,{error:l});let d;try{d=await It(t)}catch(y){return re(e,400,{error:y.message})}let p=ml(d.endpoint,o.allowedHosts);if(!p){let y="";try{y=new URL(String(d.endpoint)).hostname}catch{}return re(e,400,{error:`not a known push service${y?`: ${y}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return re(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let m=d.keys?.p256dh,f=d.keys?.auth;return typeof m!="string"||!dr.test(m)||typeof f!="string"||!dr.test(f)?re(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?re(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:m,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),re(e,200,{ok:!0}))}function ml(t,e){if(typeof t!="string"||t.length>ul)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 re(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var pr=`
|
|
15040
|
+
(function () {
|
|
15041
|
+
var fleetPanel = document.getElementById('panel-fleet');
|
|
15042
|
+
var activityPanel = document.getElementById('panel-activity');
|
|
15043
|
+
if (!fleetPanel || !activityPanel) return;
|
|
15044
|
+
var tz = 'UTC';
|
|
15045
|
+
try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'; } catch (e) {}
|
|
15046
|
+
|
|
15047
|
+
function esc(s) {
|
|
15048
|
+
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
|
15049
|
+
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
|
15050
|
+
});
|
|
15051
|
+
}
|
|
15052
|
+
function ago(iso) {
|
|
15053
|
+
if (!iso) return '';
|
|
15054
|
+
var s = Math.max(0, (Date.now() - Date.parse(iso)) / 1000);
|
|
15055
|
+
if (s < 60) return 'just now';
|
|
15056
|
+
if (s < 3600) return Math.round(s / 60) + ' min ago';
|
|
15057
|
+
if (s < 86400) return Math.round(s / 3600) + ' h ago';
|
|
15058
|
+
return Math.round(s / 86400) + ' d ago';
|
|
15059
|
+
}
|
|
15060
|
+
function plural(n, word) { return n + ' ' + word + (n === 1 ? '' : 's'); }
|
|
15061
|
+
function uptime(sec) {
|
|
15062
|
+
if (sec == null) return '';
|
|
15063
|
+
if (sec < 3600) return 'up ' + Math.round(sec / 60) + ' min';
|
|
15064
|
+
if (sec < 86400) return 'up ' + Math.round(sec / 3600) + ' h';
|
|
15065
|
+
return 'up ' + Math.round(sec / 86400) + ' d';
|
|
15066
|
+
}
|
|
15067
|
+
function api(method, path, body) {
|
|
15068
|
+
return fetch(path, {
|
|
15069
|
+
method: method,
|
|
15070
|
+
credentials: 'same-origin',
|
|
15071
|
+
headers: body ? { 'Content-Type': 'application/json' } : {},
|
|
15072
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
15073
|
+
}).then(function (r) {
|
|
15074
|
+
if (r.status === 401) { location.reload(); throw new Error('not paired'); }
|
|
15075
|
+
return r.json().catch(function () { return {}; }).then(function (b) {
|
|
15076
|
+
if (!r.ok) throw new Error(b.error || ('HTTP ' + r.status));
|
|
15077
|
+
return b;
|
|
15078
|
+
});
|
|
15079
|
+
});
|
|
15080
|
+
}
|
|
15081
|
+
|
|
15082
|
+
// One shared bottom sheet for every confirmation and the follow-up box.
|
|
15083
|
+
var sheet = document.createElement('dialog');
|
|
15084
|
+
sheet.className = 'fx-sheet';
|
|
15085
|
+
sheet.innerHTML = '<form method="dialog"><h3 id="fx-title"></h3><p id="fx-text"></p>' +
|
|
15086
|
+
'<label id="fx-field" hidden><span>Message</span><textarea id="fx-input" rows="3"></textarea></label>' +
|
|
15087
|
+
'<p id="fx-error" class="fx-error" role="alert"></p>' +
|
|
15088
|
+
'<div class="fx-actions"><button value="cancel" class="fx-btn">Cancel</button>' +
|
|
15089
|
+
'<button value="ok" id="fx-ok" class="fx-btn fx-primary">OK</button></div></form>';
|
|
15090
|
+
document.body.appendChild(sheet);
|
|
15091
|
+
var pending = null;
|
|
15092
|
+
function ask(opts) {
|
|
15093
|
+
document.getElementById('fx-title').textContent = opts.title;
|
|
15094
|
+
document.getElementById('fx-text').textContent = opts.text || '';
|
|
15095
|
+
document.getElementById('fx-ok').textContent = opts.ok || 'OK';
|
|
15096
|
+
document.getElementById('fx-ok').className = 'fx-btn ' + (opts.danger ? 'fx-danger' : 'fx-primary');
|
|
15097
|
+
document.getElementById('fx-error').textContent = '';
|
|
15098
|
+
var field = document.getElementById('fx-field');
|
|
15099
|
+
var input = document.getElementById('fx-input');
|
|
15100
|
+
field.hidden = !opts.input;
|
|
15101
|
+
input.value = '';
|
|
15102
|
+
pending = opts;
|
|
15103
|
+
if (sheet.showModal) { sheet.showModal(); if (opts.input) input.focus(); }
|
|
15104
|
+
else if (window.confirm(opts.title)) run(opts, opts.input ? window.prompt('Message') || '' : '');
|
|
15105
|
+
}
|
|
15106
|
+
sheet.addEventListener('close', function () {
|
|
15107
|
+
var opts = pending;
|
|
15108
|
+
pending = null;
|
|
15109
|
+
if (!opts || sheet.returnValue !== 'ok') return;
|
|
15110
|
+
run(opts, document.getElementById('fx-input').value.trim());
|
|
15111
|
+
});
|
|
15112
|
+
function run(opts, text) {
|
|
15113
|
+
if (opts.input && !text) { flash(opts.panel, 'Nothing sent: the message was empty.', true); return; }
|
|
15114
|
+
api('POST', opts.path, opts.body(text)).then(function (b) {
|
|
15115
|
+
flash(opts.panel, opts.done(b), false);
|
|
15116
|
+
refresh();
|
|
15117
|
+
}).catch(function (e) { flash(opts.panel, opts.title + ' failed: ' + e.message, true); });
|
|
15118
|
+
}
|
|
15119
|
+
// The refresh that follows an action re-renders the panel, so the last
|
|
15120
|
+
// result is kept on the panel and shown again for a few seconds.
|
|
15121
|
+
function flash(panel, msg, bad) {
|
|
15122
|
+
panel._msg = { text: msg, bad: bad, at: Date.now() };
|
|
15123
|
+
var el = panel.querySelector('.fx-status');
|
|
15124
|
+
if (!el) return;
|
|
15125
|
+
el.textContent = msg;
|
|
15126
|
+
el.className = 'fx-status' + (bad ? ' fx-bad' : '');
|
|
15127
|
+
}
|
|
15128
|
+
function statusLine(panel, ts) {
|
|
15129
|
+
var m = panel._msg;
|
|
15130
|
+
if (m && Date.now() - m.at < 10000) return '<p class="fx-status' + (m.bad ? ' fx-bad' : '') + '" role="status" aria-live="polite">' + esc(m.text) + '</p>';
|
|
15131
|
+
return '<p class="fx-status" role="status" aria-live="polite">Updated ' + esc(new Date(ts).toLocaleTimeString()) + '</p>';
|
|
15132
|
+
}
|
|
15133
|
+
|
|
15134
|
+
function statusPill(n) {
|
|
15135
|
+
if (!n.reachable) return '<span class="fx-pill fx-off">Offline</span>';
|
|
15136
|
+
if (n.restart) return '<span class="fx-pill fx-warn">Restart ' + esc(n.restart.state) + '</span>';
|
|
15137
|
+
return '<span class="fx-pill fx-on">Online</span>';
|
|
15138
|
+
}
|
|
15139
|
+
function renderFleet(data) {
|
|
15140
|
+
// Redraws every 15 seconds; keep the sections the user opened open.
|
|
15141
|
+
var openKeys = {};
|
|
15142
|
+
fleetPanel.querySelectorAll('details[open]').forEach(function (d) { openKeys[d.getAttribute('data-key')] = true; });
|
|
15143
|
+
var html = '<div class="fx-head"><h2>Fleet</h2><button type="button" class="fx-btn" data-act="refresh">Refresh</button></div>' +
|
|
15144
|
+
statusLine(fleetPanel, data.ts);
|
|
15145
|
+
if (!data.nodes.length) html += '<p class="soon">No machines found.</p>';
|
|
15146
|
+
data.nodes.forEach(function (n, i) {
|
|
15147
|
+
var running = n.agents.reduce(function (sum, a) { return sum + (a.active || 0); }, 0);
|
|
15148
|
+
html += '<article class="fx-card"><div class="fx-row"><h3>' + esc(n.name) + '</h3>' + statusPill(n) + '</div>';
|
|
15149
|
+
if (!n.reachable) {
|
|
15150
|
+
html += '<p class="fx-muted">Not reachable' + (n.error ? ': ' + esc(n.error) : '') + '. The rest of the fleet still works.</p></article>';
|
|
15151
|
+
return;
|
|
15152
|
+
}
|
|
15153
|
+
html += '<p class="fx-muted">' + esc(uptime(n.uptimeSec)) + ' \xB7 ' + plural(n.agents.length, 'agent') + ' \xB7 ' + running + ' running \xB7 schedules today: ' +
|
|
15154
|
+
n.crons.today.success + ' ok, ' + n.crons.today.failed + ' failed</p>';
|
|
15155
|
+
html += '<div class="fx-row fx-gap"><button type="button" class="fx-btn" data-act="reload" data-i="' + i + '">Reload config</button>' +
|
|
15156
|
+
(n.restart ? '<button type="button" class="fx-btn" data-act="unrestart" data-i="' + i + '">Cancel restart</button>'
|
|
15157
|
+
: '<button type="button" class="fx-btn fx-danger-o" data-act="restart" data-i="' + i + '">Restart when idle</button>') + '</div>';
|
|
15158
|
+
html += '<details data-key="' + esc(n.url) + '|agents"' + (openKeys[n.url + '|agents'] ? ' open' : '') + '><summary>Agents (' + n.agents.length + ')</summary><ul class="fx-list">';
|
|
15159
|
+
n.agents.forEach(function (a) {
|
|
15160
|
+
html += '<li><div class="fx-row"><strong>' + esc(a.name) + '</strong><span class="fx-muted">' +
|
|
15161
|
+
(a.active ? a.active + ' running' : (a.lastActive ? ago(a.lastActive) : 'idle')) + (a.errors ? ' \xB7 ' + a.errors + ' errors' : '') + '</span></div>' +
|
|
15162
|
+
(a.last ? '<p class="fx-muted' + (a.last.ok ? '' : ' fx-bad') + '">' + esc(a.last.text) + '</p>' : '') + '</li>';
|
|
15163
|
+
});
|
|
15164
|
+
html += '</ul></details><details data-key="' + esc(n.url) + '|crons"' + (openKeys[n.url + '|crons'] ? ' open' : '') + '><summary>Schedules (' + n.crons.items.length + ')</summary><ul class="fx-list">';
|
|
15165
|
+
n.crons.items.forEach(function (c, j) {
|
|
15166
|
+
var last = c.last ? '<span class="fx-pill ' + (c.last.status === 'success' ? 'fx-on' : 'fx-off') + '">' + esc(c.last.status) + '</span>' : '';
|
|
15167
|
+
html += '<li><div class="fx-row"><strong>' + esc(c.id) + '</strong>' +
|
|
15168
|
+
'<button type="button" class="fx-switch" role="switch" aria-checked="' + c.enabled + '" aria-label="' + (c.enabled ? 'Turn off ' : 'Turn on ') + esc(c.id) +
|
|
15169
|
+
'" data-act="cron" data-i="' + i + '" data-j="' + j + '"><span></span></button></div>' +
|
|
15170
|
+
'<p class="fx-muted">' + esc(c.schedule) + ' \xB7 ' + esc(c.agent) + (c.consecutiveErrors ? ' \xB7 failed ' + c.consecutiveErrors + ' times in a row' : '') + ' ' + last + '</p>' +
|
|
15171
|
+
(c.last && c.last.text ? '<p class="fx-muted">' + esc(c.last.text) + '</p>' : '') + '</li>';
|
|
15172
|
+
});
|
|
15173
|
+
html += '</ul></details></article>';
|
|
15174
|
+
});
|
|
15175
|
+
fleetPanel.innerHTML = html;
|
|
15176
|
+
fleetPanel._data = data;
|
|
15177
|
+
}
|
|
15178
|
+
|
|
15179
|
+
function renderActivity(act, appr) {
|
|
15180
|
+
var html = '<div class="fx-head"><h2>Activity</h2><button type="button" class="fx-btn" data-act="refresh">Refresh</button></div>' +
|
|
15181
|
+
statusLine(activityPanel, act.ts);
|
|
15182
|
+
var items = [];
|
|
15183
|
+
appr.nodes.forEach(function (n) { n.items.forEach(function (it) { items.push({ node: n, it: it }); }); });
|
|
15184
|
+
html += '<h3 class="fx-sub">Needs you (' + items.length + ')</h3>';
|
|
15185
|
+
if (!items.length) html += '<p class="fx-muted">Nothing is waiting for a decision.</p>';
|
|
15186
|
+
items.forEach(function (x, k) {
|
|
15187
|
+
html += '<article class="fx-card"><h4>' + esc(x.it.title) + '</h4><p>' + esc(x.it.ask) + '</p>' +
|
|
15188
|
+
(x.it.recommend ? '<p class="fx-muted">Suggested: ' + esc(x.it.recommend) + '</p>' : '') +
|
|
15189
|
+
'<p class="fx-muted">' + esc(x.it.raisedBy || '') + ' \xB7 ' + esc(x.node.nodeName) + '</p>' +
|
|
15190
|
+
'<div class="fx-row fx-gap"><button type="button" class="fx-btn fx-primary" data-act="decide" data-k="' + k + '" data-v="yes">Yes</button>' +
|
|
15191
|
+
'<button type="button" class="fx-btn" data-act="decide" data-k="' + k + '" data-v="no">No</button>' +
|
|
15192
|
+
'<button type="button" class="fx-btn" data-act="decide" data-k="' + k + '" data-v="later">Later</button></div></article>';
|
|
15193
|
+
});
|
|
15194
|
+
appr.nodes.forEach(function (n) { if (n.error) html += '<p class="fx-muted fx-bad">Approvals on ' + esc(n.nodeName) + ' could not be read: ' + esc(n.error) + '</p>'; });
|
|
15195
|
+
html += '<h3 class="fx-sub">Running now (' + act.tasks.length + ')</h3>';
|
|
15196
|
+
if (!act.tasks.length) html += '<p class="fx-muted">No agent is working right now.</p>';
|
|
15197
|
+
act.tasks.forEach(function (t, k) {
|
|
15198
|
+
html += '<article class="fx-card"><div class="fx-row"><h4>' + esc(t.agentName) + '</h4><span class="fx-muted">' + esc(ago(t.startedAt)) + '</span></div>' +
|
|
15199
|
+
'<p>' + esc(t.preview) + '</p><p class="fx-muted">' + esc(t.nodeName) + ' \xB7 ' + esc(t.channel) + '</p>' +
|
|
15200
|
+
'<div class="fx-row fx-gap"><button type="button" class="fx-btn" data-act="followup" data-k="' + k + '">Follow up</button>' +
|
|
15201
|
+
'<button type="button" class="fx-btn fx-danger-o" data-act="cancel" data-k="' + k + '">Stop</button></div></article>';
|
|
15202
|
+
});
|
|
15203
|
+
activityPanel.innerHTML = html;
|
|
15204
|
+
activityPanel._act = act;
|
|
15205
|
+
activityPanel._items = items;
|
|
15206
|
+
}
|
|
15207
|
+
|
|
15208
|
+
fleetPanel.addEventListener('click', function (ev) {
|
|
15209
|
+
var b = ev.target.closest('[data-act]');
|
|
15210
|
+
if (!b) return;
|
|
15211
|
+
var act = b.getAttribute('data-act');
|
|
15212
|
+
if (act === 'refresh') return refresh();
|
|
15213
|
+
var n = fleetPanel._data.nodes[+b.getAttribute('data-i')];
|
|
15214
|
+
if (act === 'reload') ask({ panel: fleetPanel, title: 'Reload config on ' + n.name + '?', text: 'Re-reads agentx.json. Running work continues.', ok: 'Reload',
|
|
15215
|
+
path: '/api/app/nodes/reload', body: function () { return { node: n.url }; }, done: function () { return n.name + ' reloaded its config.'; } });
|
|
15216
|
+
if (act === 'restart') ask({ panel: fleetPanel, title: 'Restart ' + n.name + '?', danger: true, ok: 'Restart when idle',
|
|
15217
|
+
text: 'It restarts as soon as no agent is working' + (n.inflight ? ' (' + n.inflight + ' tasks running now)' : '') + '. Agents on it are unavailable for a moment.',
|
|
15218
|
+
path: '/api/app/nodes/restart', body: function () { return { node: n.url }; }, done: function () { return n.name + ' will restart when idle.'; } });
|
|
15219
|
+
if (act === 'unrestart') ask({ panel: fleetPanel, title: 'Cancel the restart of ' + n.name + '?', ok: 'Cancel restart',
|
|
15220
|
+
path: '/api/app/nodes/restart', body: function () { return { node: n.url, cancel: true }; }, done: function () { return 'Restart cancelled.'; } });
|
|
15221
|
+
if (act === 'cron') {
|
|
15222
|
+
var c = n.crons.items[+b.getAttribute('data-j')];
|
|
15223
|
+
var on = !c.enabled;
|
|
15224
|
+
ask({ panel: fleetPanel, title: (on ? 'Turn on ' : 'Turn off ') + c.id + '?', ok: on ? 'Turn on' : 'Turn off', danger: !on,
|
|
15225
|
+
text: on ? 'It runs again on its schedule (' + c.schedule + ').' : 'It stops running until you turn it on again.',
|
|
15226
|
+
path: '/api/app/crons/toggle', body: function () { return { node: n.url, cronId: c.id, enabled: on }; },
|
|
15227
|
+
done: function () { return c.id + (on ? ' is on.' : ' is off.'); } });
|
|
15228
|
+
}
|
|
15229
|
+
});
|
|
15230
|
+
|
|
15231
|
+
activityPanel.addEventListener('click', function (ev) {
|
|
15232
|
+
var b = ev.target.closest('[data-act]');
|
|
15233
|
+
if (!b) return;
|
|
15234
|
+
var act = b.getAttribute('data-act');
|
|
15235
|
+
if (act === 'refresh') return refresh();
|
|
15236
|
+
var k = +b.getAttribute('data-k');
|
|
15237
|
+
if (act === 'decide') {
|
|
15238
|
+
var x = activityPanel._items[k];
|
|
15239
|
+
var v = b.getAttribute('data-v');
|
|
15240
|
+
var word = { yes: 'Yes', no: 'No', later: 'Later' }[v];
|
|
15241
|
+
ask({ panel: activityPanel, title: word + ': ' + x.it.title + '?', ok: word, danger: v === 'no',
|
|
15242
|
+
text: v === 'yes' ? (x.it.yes || '') : v === 'no' ? (x.it.no || '') : 'Ask again later.',
|
|
15243
|
+
path: '/api/app/approvals/decide', body: function () { return { node: x.node.node, key: x.it.key, action: v }; },
|
|
15244
|
+
done: function () { return v === 'later' ? 'Put off: ' + x.it.title + '.' : 'Answered ' + word + ': ' + x.it.title + '.'; } });
|
|
15245
|
+
return;
|
|
15246
|
+
}
|
|
15247
|
+
var t = activityPanel._act.tasks[k];
|
|
15248
|
+
if (act === 'cancel') ask({ panel: activityPanel, title: 'Stop ' + t.agentName + '?', danger: true, ok: 'Stop',
|
|
15249
|
+
text: 'The current task is stopped. The agent keeps the conversation.',
|
|
15250
|
+
path: '/api/app/tasks/cancel', body: function () { return { node: t.node, taskId: t.taskId }; }, done: function () { return 'Stopped.'; } });
|
|
15251
|
+
if (act === 'followup') ask({ panel: activityPanel, title: 'Follow up with ' + t.agentName, input: true, ok: 'Send',
|
|
15252
|
+
text: 'Sent after the current step finishes.',
|
|
15253
|
+
path: '/api/app/tasks/followup', body: function (text) { return { node: t.node, taskId: t.taskId, message: text }; }, done: function () { return 'Follow-up queued.'; } });
|
|
15254
|
+
});
|
|
15255
|
+
|
|
15256
|
+
var loading = false;
|
|
15257
|
+
function visible(panel) { return !panel.hidden && document.visibilityState === 'visible'; }
|
|
15258
|
+
function refresh() {
|
|
15259
|
+
// Never redraw under an open sheet: the rows it refers to would move.
|
|
15260
|
+
if (loading || sheet.open) return;
|
|
15261
|
+
var q = '?timezone=' + encodeURIComponent(tz);
|
|
15262
|
+
var jobs = [];
|
|
15263
|
+
loading = true;
|
|
15264
|
+
if (visible(fleetPanel)) {
|
|
15265
|
+
jobs.push(api('GET', '/api/app/fleet' + q).then(renderFleet).catch(function (e) { flash(fleetPanel, 'Could not load the fleet: ' + e.message, true); }));
|
|
15266
|
+
}
|
|
15267
|
+
if (visible(activityPanel)) {
|
|
15268
|
+
jobs.push(Promise.all([api('GET', '/api/app/activity' + q), api('GET', '/api/app/approvals')])
|
|
15269
|
+
.then(function (r) { renderActivity(r[0], r[1]); })
|
|
15270
|
+
.catch(function (e) { flash(activityPanel, 'Could not load activity: ' + e.message, true); }));
|
|
15271
|
+
}
|
|
15272
|
+
Promise.all(jobs).then(function () { loading = false; }, function () { loading = false; });
|
|
15273
|
+
}
|
|
15274
|
+
[fleetPanel, activityPanel].forEach(function (p) {
|
|
15275
|
+
if (!p.querySelector('.fx-status')) p.insertAdjacentHTML('beforeend', '<p class="fx-status" role="status" aria-live="polite"></p>');
|
|
15276
|
+
});
|
|
15277
|
+
document.querySelectorAll('[role=tab]').forEach(function (t) { t.addEventListener('click', function () { setTimeout(refresh, 0); }); });
|
|
15278
|
+
document.addEventListener('visibilitychange', refresh);
|
|
15279
|
+
window.addEventListener('online', refresh);
|
|
15280
|
+
setInterval(refresh, 15000);
|
|
15281
|
+
refresh();
|
|
15282
|
+
})();
|
|
15283
|
+
`;var ur=`
|
|
15284
|
+
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
15285
|
+
.fx-head h2 { margin: 4px 0 0; }
|
|
15286
|
+
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
15287
|
+
.fx-status { margin: 4px 0 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); min-height: 1em; }
|
|
15288
|
+
.fx-bad { color: var(--ax-red-ink, #b3261e); }
|
|
15289
|
+
.fx-card {
|
|
15290
|
+
background: var(--ax-surface); border: var(--ax-border-w) solid var(--ax-border);
|
|
15291
|
+
border-radius: var(--ax-radius); padding: 12px 14px; margin: 0 0 12px;
|
|
15292
|
+
}
|
|
15293
|
+
.fx-card h3, .fx-card h4 { margin: 0; font-size: 16px; }
|
|
15294
|
+
.fx-card p { margin: 6px 0 0; line-height: 1.45; overflow-wrap: anywhere; }
|
|
15295
|
+
.fx-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
15296
|
+
.fx-gap { justify-content: flex-start; flex-wrap: wrap; margin-top: 10px; }
|
|
15297
|
+
.fx-muted { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
15298
|
+
.fx-pill { font-size: var(--ax-fs-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--ax-radius-pill); white-space: nowrap; }
|
|
15299
|
+
.fx-on { background: var(--ax-green-e); color: var(--ax-text); }
|
|
15300
|
+
.fx-off { background: var(--ax-red-t); color: var(--ax-red-ink); }
|
|
15301
|
+
.fx-warn { background: var(--ax-amber-t); color: var(--ax-amber-ink); }
|
|
15302
|
+
.fx-btn {
|
|
15303
|
+
min-height: 44px; padding: 0 14px; font: inherit; font-size: var(--ax-fs-sm); font-weight: 600;
|
|
15304
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-pill);
|
|
15305
|
+
background: var(--ax-surface-2); color: var(--ax-text); cursor: pointer;
|
|
15306
|
+
}
|
|
15307
|
+
/* Same tinted fill as the dashboard's .ax-btn--primary: legible in both themes. */
|
|
15308
|
+
.fx-primary { background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); border-color: color-mix(in oklch, var(--ax-accent) 50%, var(--ax-border)); color: var(--ax-accent); }
|
|
15309
|
+
.fx-danger { background: color-mix(in oklch, var(--ax-red) 15%, var(--ax-surface)); border-color: color-mix(in oklch, var(--ax-red) 50%, var(--ax-border)); color: var(--ax-red-ink); }
|
|
15310
|
+
.fx-danger-o { color: var(--ax-red-ink); border-color: var(--ax-red-e, var(--ax-border)); }
|
|
15311
|
+
details { margin-top: 10px; }
|
|
15312
|
+
summary { min-height: 44px; display: flex; align-items: center; gap: 8px; cursor: pointer; font-weight: 600; list-style: none; }
|
|
15313
|
+
summary::-webkit-details-marker { display: none; }
|
|
15314
|
+
summary::before { content: "\u203A"; display: inline-block; width: 12px; font-size: 20px; line-height: 1; color: var(--ax-text-2); transition: transform .15s; }
|
|
15315
|
+
details[open] > summary::before { transform: rotate(90deg); }
|
|
15316
|
+
.fx-list { list-style: none; margin: 0; padding: 0; }
|
|
15317
|
+
.fx-list li { padding: 10px 0; border-top: var(--ax-border-w) solid var(--ax-border); }
|
|
15318
|
+
.fx-switch {
|
|
15319
|
+
position: relative; width: 52px; min-width: 52px; height: 32px; border-radius: 16px; cursor: pointer;
|
|
15320
|
+
border: var(--ax-border-w) solid var(--ax-border); background: var(--ax-surface-3); padding: 0;
|
|
15321
|
+
}
|
|
15322
|
+
.fx-switch span { position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: left .15s; }
|
|
15323
|
+
.fx-switch[aria-checked=true] { background: var(--ax-accent); border-color: var(--ax-accent); }
|
|
15324
|
+
.fx-switch[aria-checked=true] span { left: 23px; }
|
|
15325
|
+
.fx-sheet {
|
|
15326
|
+
width: 100%; max-width: 520px; margin: auto auto 0; border: 0; padding: 0;
|
|
15327
|
+
border-radius: 16px 16px 0 0; background: var(--ax-surface); color: var(--ax-text);
|
|
15328
|
+
}
|
|
15329
|
+
.fx-sheet::backdrop { background: rgba(0,0,0,.45); }
|
|
15330
|
+
.fx-sheet form { padding: 20px calc(20px + env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-left)); }
|
|
15331
|
+
.fx-sheet h3 { margin: 0 0 8px; font-size: 18px; }
|
|
15332
|
+
.fx-sheet p { margin: 0 0 12px; color: var(--ax-text-2); line-height: 1.45; }
|
|
15333
|
+
.fx-sheet label span { display: block; font-weight: 600; margin-bottom: 6px; }
|
|
15334
|
+
.fx-sheet textarea {
|
|
15335
|
+
width: 100%; box-sizing: border-box; font: inherit; font-size: 16px; padding: 10px;
|
|
15336
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm); background: var(--ax-bg); color: var(--ax-text);
|
|
15337
|
+
}
|
|
15338
|
+
.fx-error:empty { display: none; }
|
|
15339
|
+
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
15340
|
+
`;var mr=`
|
|
15341
|
+
(function () {
|
|
15342
|
+
var panel = document.getElementById('panel-alerts');
|
|
15343
|
+
if (!panel) return;
|
|
15344
|
+
panel.innerHTML = '<h2>Alerts</h2>' +
|
|
15345
|
+
'<div class="fx-card"><div class="fx-row"><h3>Notifications on this phone</h3><span id="al-pill" class="fx-pill"></span></div>' +
|
|
15346
|
+
'<p id="al-text" class="fx-muted">Checking\u2026</p>' +
|
|
15347
|
+
'<div class="fx-row fx-gap"><button type="button" id="al-btn" class="fx-btn fx-primary" hidden></button></div>' +
|
|
15348
|
+
'<p id="al-error" class="fx-error fx-bad" role="alert"></p></div>' +
|
|
15349
|
+
'<h3 class="fx-sub">Recent</h3><ul id="al-list" class="fx-list"></ul>';
|
|
15350
|
+
var pill = document.getElementById('al-pill');
|
|
15351
|
+
var text = document.getElementById('al-text');
|
|
15352
|
+
var btn = document.getElementById('al-btn');
|
|
15353
|
+
var err = document.getElementById('al-error');
|
|
15354
|
+
var list = document.getElementById('al-list');
|
|
15355
|
+
var server = null;
|
|
15356
|
+
var busy = false;
|
|
15357
|
+
|
|
15358
|
+
function esc(s) {
|
|
15359
|
+
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
|
15360
|
+
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
|
15361
|
+
});
|
|
15362
|
+
}
|
|
15363
|
+
function ago(ms) {
|
|
15364
|
+
var s = Math.max(0, (Date.now() - ms) / 1000);
|
|
15365
|
+
if (s < 60) return 'just now';
|
|
15366
|
+
if (s < 3600) return Math.round(s / 60) + ' min ago';
|
|
15367
|
+
if (s < 86400) return Math.round(s / 3600) + ' h ago';
|
|
15368
|
+
return Math.round(s / 86400) + ' d ago';
|
|
15369
|
+
}
|
|
15370
|
+
function api(method, path, body) {
|
|
15371
|
+
return fetch(path, {
|
|
15372
|
+
method: method,
|
|
15373
|
+
credentials: 'same-origin',
|
|
15374
|
+
headers: body ? { 'Content-Type': 'application/json' } : {},
|
|
15375
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
15376
|
+
}).then(function (r) {
|
|
15377
|
+
if (r.status === 401) { location.reload(); throw new Error('not paired'); }
|
|
15378
|
+
return r.json().catch(function () { return {}; }).then(function (b) {
|
|
15379
|
+
if (!r.ok) throw new Error(b.error || ('HTTP ' + r.status));
|
|
15380
|
+
return b;
|
|
15381
|
+
});
|
|
15382
|
+
});
|
|
15383
|
+
}
|
|
15384
|
+
// The VAPID key arrives base64url-encoded; the Push API wants bytes.
|
|
15385
|
+
function keyBytes(b64) {
|
|
15386
|
+
var s = b64.replace(/-/g, '+').replace(/_/g, '/');
|
|
15387
|
+
while (s.length % 4) s += '=';
|
|
15388
|
+
var raw = atob(s);
|
|
15389
|
+
var out = new Uint8Array(raw.length);
|
|
15390
|
+
for (var i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);
|
|
15391
|
+
return out;
|
|
15392
|
+
}
|
|
15393
|
+
function supported() {
|
|
15394
|
+
return 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window;
|
|
15395
|
+
}
|
|
15396
|
+
// The key this phone subscribed with. When the computer's keys are
|
|
15397
|
+
// replaced, the old subscription can never be delivered to, so it is
|
|
15398
|
+
// dropped and the card offers Turn on again.
|
|
15399
|
+
function savedKey() { try { return localStorage.getItem('ax-push-key'); } catch (e) { return null; } }
|
|
15400
|
+
function saveKey(k) { try { if (k) localStorage.setItem('ax-push-key', k); else localStorage.removeItem('ax-push-key'); } catch (e) {} }
|
|
15401
|
+
function register(sub) {
|
|
15402
|
+
var body = sub.toJSON();
|
|
15403
|
+
body.publicKey = server.publicKey;
|
|
15404
|
+
return api('POST', '/api/app/push/subscribe', body).then(function () { saveKey(server.publicKey); });
|
|
15405
|
+
}
|
|
15406
|
+
function currentSub() {
|
|
15407
|
+
return navigator.serviceWorker.ready.then(function (reg) { return reg.pushManager.getSubscription(); });
|
|
15408
|
+
}
|
|
15409
|
+
function show(state, message, action) {
|
|
15410
|
+
pill.textContent = state === 'on' ? 'On' : state === 'off' ? 'Off' : 'Unavailable';
|
|
15411
|
+
pill.className = 'fx-pill ' + (state === 'on' ? 'fx-on' : state === 'off' ? 'fx-warn' : 'fx-off');
|
|
15412
|
+
text.textContent = message;
|
|
15413
|
+
btn.hidden = !action;
|
|
15414
|
+
if (action) { btn.textContent = action; btn.className = 'fx-btn ' + (action === 'Turn off' ? 'fx-danger-o' : 'fx-primary'); }
|
|
15415
|
+
}
|
|
15416
|
+
|
|
15417
|
+
function refresh() {
|
|
15418
|
+
err.textContent = '';
|
|
15419
|
+
if (!supported()) {
|
|
15420
|
+
show('na', 'This browser can\u2019t receive notifications here. On an iPhone, add the app to the Home Screen first (Share, then Add to Home Screen), then open it from there.');
|
|
15421
|
+
return Promise.resolve();
|
|
15422
|
+
}
|
|
15423
|
+
return api('GET', '/api/app/push').then(function (s) {
|
|
15424
|
+
server = s;
|
|
15425
|
+
if (!s.available) { show('na', s.reason || 'Notifications are not set up on this computer.'); return; }
|
|
15426
|
+
if (Notification.permission === 'denied') {
|
|
15427
|
+
show('na', 'Notifications are blocked for this app. Allow them in the phone\u2019s settings for this app, then come back.');
|
|
15428
|
+
return;
|
|
15429
|
+
}
|
|
15430
|
+
return currentSub().then(function (sub) {
|
|
15431
|
+
var offer = function () { show('off', 'Turn on to get a notification when an agent needs you.', 'Turn on'); };
|
|
15432
|
+
if (!sub) { offer(); return; }
|
|
15433
|
+
if (savedKey() !== s.publicKey) {
|
|
15434
|
+
// Made with keys this computer no longer has: it can't be used.
|
|
15435
|
+
saveKey(null);
|
|
15436
|
+
return sub.unsubscribe().then(offer, offer);
|
|
15437
|
+
}
|
|
15438
|
+
// The computer may have lost it (the phone was re-paired): send it again.
|
|
15439
|
+
var sync = s.subscriptions > 0 ? Promise.resolve() : register(sub);
|
|
15440
|
+
return sync.then(function () { show('on', 'This phone gets a notification when an agent needs you.', 'Turn off'); });
|
|
15441
|
+
});
|
|
15442
|
+
}).catch(function (e) { show('na', 'Could not check notifications: ' + e.message); });
|
|
15443
|
+
}
|
|
15444
|
+
|
|
15445
|
+
function turnOn() {
|
|
15446
|
+
return Notification.requestPermission().then(function (p) {
|
|
15447
|
+
if (p !== 'granted') throw new Error('Notifications were not allowed.');
|
|
15448
|
+
return navigator.serviceWorker.ready;
|
|
15449
|
+
}).then(function (reg) {
|
|
15450
|
+
// A subscription made with older keys can't be reused; replace it.
|
|
15451
|
+
return reg.pushManager.getSubscription().then(function (old) {
|
|
15452
|
+
return old ? old.unsubscribe() : null;
|
|
15453
|
+
}).then(function () {
|
|
15454
|
+
return reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: keyBytes(server.publicKey) });
|
|
15455
|
+
});
|
|
15456
|
+
}).then(register);
|
|
15457
|
+
}
|
|
15458
|
+
function turnOff() {
|
|
15459
|
+
return currentSub().then(function (sub) {
|
|
15460
|
+
if (!sub) return null;
|
|
15461
|
+
var endpoint = sub.endpoint;
|
|
15462
|
+
saveKey(null);
|
|
15463
|
+
return sub.unsubscribe().then(function () { return api('POST', '/api/app/push/unsubscribe', { endpoint: endpoint }); });
|
|
15464
|
+
});
|
|
15465
|
+
}
|
|
15466
|
+
btn.addEventListener('click', function () {
|
|
15467
|
+
if (busy) return;
|
|
15468
|
+
busy = true;
|
|
15469
|
+
btn.disabled = true;
|
|
15470
|
+
err.textContent = '';
|
|
15471
|
+
(btn.textContent === 'Turn off' ? turnOff() : turnOn())
|
|
15472
|
+
.catch(function (e) { err.textContent = e.message; })
|
|
15473
|
+
.then(refresh)
|
|
15474
|
+
.then(function () { busy = false; btn.disabled = false; });
|
|
15475
|
+
});
|
|
15476
|
+
|
|
15477
|
+
function loadRecent() {
|
|
15478
|
+
return api('GET', '/api/app/alerts').then(function (b) {
|
|
15479
|
+
var items = b.items || [];
|
|
15480
|
+
if (!items.length) { list.innerHTML = '<li class="fx-muted">No notifications yet.</li>'; return; }
|
|
15481
|
+
list.innerHTML = items.map(function (it) {
|
|
15482
|
+
// Only web links: a button URL comes from an agent's message.
|
|
15483
|
+
var link = /^https?:/i.test(it.url || '')
|
|
15484
|
+
? ' <a href="' + esc(it.url) + '" target="_blank" rel="noopener noreferrer">Open</a>' : '';
|
|
15485
|
+
return '<li><div class="fx-row"><strong>' + esc(it.title) + '</strong><span class="fx-muted">' + esc(ago(it.at)) + '</span></div>' +
|
|
15486
|
+
'<p>' + esc(it.body) + link + '</p></li>';
|
|
15487
|
+
}).join('');
|
|
15488
|
+
}).catch(function (e) { list.innerHTML = '<li class="fx-bad">Could not load notifications: ' + esc(e.message) + '</li>'; });
|
|
15489
|
+
}
|
|
15490
|
+
|
|
15491
|
+
if ('serviceWorker' in navigator) {
|
|
15492
|
+
navigator.serviceWorker.addEventListener('message', function (ev) {
|
|
15493
|
+
var d = ev.data || {};
|
|
15494
|
+
if (d.type === 'agentx-push') loadRecent();
|
|
15495
|
+
if (d.type === 'agentx-open' && d.url) location.href = d.url;
|
|
15496
|
+
});
|
|
15497
|
+
}
|
|
15498
|
+
document.addEventListener('visibilitychange', function () { if (!document.hidden) loadRecent(); });
|
|
15499
|
+
refresh();
|
|
15500
|
+
loadRecent();
|
|
15501
|
+
})();
|
|
15502
|
+
`;var $t=`
|
|
15503
|
+
var CACHE = 'agentx-app-v2';
|
|
15504
|
+
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
15505
|
+
self.addEventListener('install', function (e) {
|
|
15506
|
+
e.waitUntil(caches.open(CACHE).then(function (c) { return c.addAll(STATIC); }).then(function () { return self.skipWaiting(); }));
|
|
15507
|
+
});
|
|
15508
|
+
self.addEventListener('activate', function (e) {
|
|
15509
|
+
e.waitUntil(caches.keys().then(function (keys) {
|
|
15510
|
+
return Promise.all(keys.filter(function (k) { return k !== CACHE; }).map(function (k) { return caches.delete(k); }));
|
|
15511
|
+
}).then(function () { return self.clients.claim(); }));
|
|
15512
|
+
});
|
|
15513
|
+
self.addEventListener('fetch', function (e) {
|
|
15514
|
+
var req = e.request;
|
|
15515
|
+
var url = new URL(req.url);
|
|
15516
|
+
if (req.method !== 'GET' || url.origin !== self.location.origin) return;
|
|
15517
|
+
if (url.pathname.indexOf('/api/') === 0) return;
|
|
15518
|
+
if (req.mode === 'navigate' && url.pathname === '/app') {
|
|
15519
|
+
e.respondWith(fetch(req).then(function (res) {
|
|
15520
|
+
var copy = res.clone();
|
|
15521
|
+
caches.open(CACHE).then(function (c) { return res.ok ? c.put('/app', copy) : res.status === 401 ? c.delete('/app') : null; });
|
|
15522
|
+
return res;
|
|
15523
|
+
}).catch(function () {
|
|
15524
|
+
return caches.match('/app').then(function (hit) { return hit || Response.error(); });
|
|
15525
|
+
}));
|
|
15526
|
+
return;
|
|
15527
|
+
}
|
|
15528
|
+
if (STATIC.indexOf(url.pathname) >= 0) {
|
|
15529
|
+
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
15530
|
+
}
|
|
15531
|
+
});
|
|
15532
|
+
function safeUrl(u) {
|
|
15533
|
+
try {
|
|
15534
|
+
var abs = new URL(u || '/app#alerts', self.location.origin);
|
|
15535
|
+
return abs.protocol === 'https:' || abs.protocol === 'http:' ? abs.href : null;
|
|
15536
|
+
} catch (x) { return null; }
|
|
15537
|
+
}
|
|
15538
|
+
self.addEventListener('push', function (e) {
|
|
15539
|
+
var d = {};
|
|
15540
|
+
try { d = e.data ? e.data.json() : {}; } catch (x) { d = { body: e.data ? e.data.text() : '' }; }
|
|
15541
|
+
var actions = Array.isArray(d.actions) ? d.actions : [];
|
|
15542
|
+
var urls = {};
|
|
15543
|
+
actions.forEach(function (a) { urls[a.action] = a.url; });
|
|
15544
|
+
e.waitUntil(self.registration.showNotification(d.title || 'AgentX', {
|
|
15545
|
+
body: d.body || '',
|
|
15546
|
+
icon: '/app/icon-192.png',
|
|
15547
|
+
badge: '/app/icon-192.png',
|
|
15548
|
+
data: { url: d.url, urls: urls },
|
|
15549
|
+
actions: actions.map(function (a) { return { action: a.action, title: a.title }; }),
|
|
15550
|
+
}).then(function () {
|
|
15551
|
+
return self.clients.matchAll({ type: 'window' });
|
|
15552
|
+
}).then(function (cs) {
|
|
15553
|
+
cs.forEach(function (c) { c.postMessage({ type: 'agentx-push' }); });
|
|
15554
|
+
}));
|
|
15555
|
+
});
|
|
15556
|
+
self.addEventListener('notificationclick', function (e) {
|
|
15557
|
+
e.notification.close();
|
|
15558
|
+
var data = e.notification.data || {};
|
|
15559
|
+
var target = safeUrl((e.action && data.urls && data.urls[e.action]) || data.url) || safeUrl('/app#alerts');
|
|
15560
|
+
var inApp = new URL(target).origin === self.location.origin;
|
|
15561
|
+
e.waitUntil(self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (cs) {
|
|
15562
|
+
var app = inApp ? cs.filter(function (c) { return new URL(c.url).pathname === '/app'; })[0] : null;
|
|
15563
|
+
if (app) {
|
|
15564
|
+
app.postMessage({ type: 'agentx-open', url: target });
|
|
15565
|
+
return app.focus();
|
|
15566
|
+
}
|
|
15567
|
+
return self.clients.openWindow(target);
|
|
15568
|
+
}));
|
|
15569
|
+
});
|
|
15570
|
+
`;var fl="<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 jt(t){return`<meta charset="utf-8">
|
|
15009
15571
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
15010
15572
|
<meta name="theme-color" content="#2979FF">
|
|
15011
15573
|
<meta name="referrer" content="no-referrer">
|
|
@@ -15016,13 +15578,13 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15016
15578
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
15017
15579
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
15018
15580
|
<title>${t}</title>
|
|
15019
|
-
${
|
|
15020
|
-
<style>${
|
|
15581
|
+
${fl}
|
|
15582
|
+
<style>${fa}${xl}</style>`}var fr=[{id:"chat",label:"Chat",soon:"Talking to your agents from this phone arrives in the next update."},{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 hr(){let t=fr.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=fr.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
15021
15583
|
<h2>${a.label}</h2>
|
|
15022
15584
|
<p class="soon">${a.soon}</p>
|
|
15023
15585
|
</section>`).join("");return`<!doctype html>
|
|
15024
15586
|
<html lang="en">
|
|
15025
|
-
<head>${
|
|
15587
|
+
<head>${jt("AgentX")}<style>${bl}${ur}</style></head>
|
|
15026
15588
|
<body>
|
|
15027
15589
|
<header class="bar">
|
|
15028
15590
|
<div>
|
|
@@ -15034,21 +15596,23 @@ ${qi}
|
|
|
15034
15596
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
15035
15597
|
<main>${e}</main>
|
|
15036
15598
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
15037
|
-
<script>${
|
|
15599
|
+
<script>${hl}</script>
|
|
15600
|
+
<script>${pr}</script>
|
|
15601
|
+
<script>${mr}</script>
|
|
15038
15602
|
</body>
|
|
15039
|
-
</html>`}function
|
|
15603
|
+
</html>`}function gr(){return`<!doctype html>
|
|
15040
15604
|
<html lang="en">
|
|
15041
|
-
<head>${
|
|
15605
|
+
<head>${jt("Pair \xB7 AgentX")}</head>
|
|
15042
15606
|
<body>
|
|
15043
15607
|
<main class="card">
|
|
15044
15608
|
<h1>Pairing this phone\u2026</h1>
|
|
15045
15609
|
<p id="msg" role="status">One moment.</p>
|
|
15046
15610
|
</main>
|
|
15047
|
-
<script>${
|
|
15611
|
+
<script>${gl}</script>
|
|
15048
15612
|
</body>
|
|
15049
|
-
</html>`}function
|
|
15613
|
+
</html>`}function xr(){return`<!doctype html>
|
|
15050
15614
|
<html lang="en">
|
|
15051
|
-
<head>${
|
|
15615
|
+
<head>${jt("Not paired \xB7 AgentX")}</head>
|
|
15052
15616
|
<body>
|
|
15053
15617
|
<main class="card">
|
|
15054
15618
|
<h1>This phone isn't paired</h1>
|
|
@@ -15056,37 +15620,7 @@ ${qi}
|
|
|
15056
15620
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
15057
15621
|
</main>
|
|
15058
15622
|
</body>
|
|
15059
|
-
</html>`}function
|
|
15060
|
-
var CACHE = 'agentx-app-v1';
|
|
15061
|
-
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
15062
|
-
self.addEventListener('install', function (e) {
|
|
15063
|
-
e.waitUntil(caches.open(CACHE).then(function (c) { return c.addAll(STATIC); }).then(function () { return self.skipWaiting(); }));
|
|
15064
|
-
});
|
|
15065
|
-
self.addEventListener('activate', function (e) {
|
|
15066
|
-
e.waitUntil(caches.keys().then(function (keys) {
|
|
15067
|
-
return Promise.all(keys.filter(function (k) { return k !== CACHE; }).map(function (k) { return caches.delete(k); }));
|
|
15068
|
-
}).then(function () { return self.clients.claim(); }));
|
|
15069
|
-
});
|
|
15070
|
-
self.addEventListener('fetch', function (e) {
|
|
15071
|
-
var req = e.request;
|
|
15072
|
-
var url = new URL(req.url);
|
|
15073
|
-
if (req.method !== 'GET' || url.origin !== self.location.origin) return;
|
|
15074
|
-
if (url.pathname.indexOf('/api/') === 0) return;
|
|
15075
|
-
if (req.mode === 'navigate' && url.pathname === '/app') {
|
|
15076
|
-
e.respondWith(fetch(req).then(function (res) {
|
|
15077
|
-
var copy = res.clone();
|
|
15078
|
-
caches.open(CACHE).then(function (c) { return res.ok ? c.put('/app', copy) : res.status === 401 ? c.delete('/app') : null; });
|
|
15079
|
-
return res;
|
|
15080
|
-
}).catch(function () {
|
|
15081
|
-
return caches.match('/app').then(function (hit) { return hit || Response.error(); });
|
|
15082
|
-
}));
|
|
15083
|
-
return;
|
|
15084
|
-
}
|
|
15085
|
-
if (STATIC.indexOf(url.pathname) >= 0) {
|
|
15086
|
-
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
15087
|
-
}
|
|
15088
|
-
});
|
|
15089
|
-
`,Fi=`
|
|
15623
|
+
</html>`}function br(){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 hl=`
|
|
15090
15624
|
(function () {
|
|
15091
15625
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
15092
15626
|
function select(tab, focus) {
|
|
@@ -15110,8 +15644,12 @@ self.addEventListener('fetch', function (e) {
|
|
|
15110
15644
|
if (next) { ev.preventDefault(); select(next, true); }
|
|
15111
15645
|
});
|
|
15112
15646
|
});
|
|
15113
|
-
|
|
15114
|
-
|
|
15647
|
+
function fromHash() {
|
|
15648
|
+
var t = tabs.filter(function (t) { return '#' + t.dataset.tab === location.hash; })[0];
|
|
15649
|
+
if (t) select(t, false);
|
|
15650
|
+
}
|
|
15651
|
+
fromHash();
|
|
15652
|
+
window.addEventListener('hashchange', fromHash);
|
|
15115
15653
|
|
|
15116
15654
|
var root = document.documentElement;
|
|
15117
15655
|
var themeBtn = document.getElementById('theme');
|
|
@@ -15148,7 +15686,7 @@ self.addEventListener('fetch', function (e) {
|
|
|
15148
15686
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
15149
15687
|
}
|
|
15150
15688
|
})();
|
|
15151
|
-
`,
|
|
15689
|
+
`,gl=`
|
|
15152
15690
|
(function () {
|
|
15153
15691
|
var msg = document.getElementById('msg');
|
|
15154
15692
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -15165,7 +15703,7 @@ self.addEventListener('fetch', function (e) {
|
|
|
15165
15703
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
15166
15704
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
15167
15705
|
})();
|
|
15168
|
-
`,
|
|
15706
|
+
`,xl=`
|
|
15169
15707
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
15170
15708
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
15171
15709
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -15177,7 +15715,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
15177
15715
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
15178
15716
|
.muted { color: var(--ax-text-2); }
|
|
15179
15717
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
15180
|
-
`,
|
|
15718
|
+
`,bl=`
|
|
15181
15719
|
body { display: flex; flex-direction: column; }
|
|
15182
15720
|
.bar {
|
|
15183
15721
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -15214,21 +15752,21 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
15214
15752
|
}
|
|
15215
15753
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
15216
15754
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
15217
|
-
`;var
|
|
15218
|
-
Live dashboard: http://${
|
|
15755
|
+
`;var yr="agentx_app",vl=400*86400;async function wr(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new J;if(n==="GET"){if(a==="/app/manifest.webmanifest")return pe(e,200,"application/manifest+json",br());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),pe(e,200,"text/javascript; charset=utf-8",$t);if(a==="/app/icon-192.png")return pe(e,200,"image/png",Mt(192),"public, max-age=86400");if(a==="/app/icon-512.png")return pe(e,200,"image/png",Mt(512),"public, max-age=86400");if(a==="/app/pair")return pe(e,200,"text/html; charset=utf-8",gr())}if(n==="POST"&&a==="/api/app/session"){let i=vr(Lt(t),o);return i?(e.setHeader("Set-Cookie",`${yr}=${Lt(t)}; Path=/; Max-Age=${vl}; HttpOnly; Secure; SameSite=Strict`),Me(e,200,{device:i.name})):Me(e,401,{error:"invalid or revoked device token"})}let s=vr(yl(t),o);return s?n==="GET"&&a==="/app"?pe(e,200,"text/html; charset=utf-8",hr()):n==="GET"&&a==="/api/app/me"?Me(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await lr(t,e,a,n,s.name,r.fleet)||r.push&&await cr(t,e,a,n,s,r.push)?!0:Me(e,404,{error:"not found"}):a==="/app"?pe(e,401,"text/html; charset=utf-8",xr()):Me(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function vr(t,e){if(!t)return null;let a=e.verify(t);return a&&me(a,"app")?a:null}function yl(t){return Lt(t)??wl(t,yr)}function Lt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function wl(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 pe(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 pe(t,e,"application/json",JSON.stringify(a))}function Ou(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let y of a)try{s.set(y.id,Ll(y,t))}catch(S){console.error(` Board "${y.id}" failed to initialize: ${S.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Ie(process.cwd(),t.workflows.dir):void 0,d=new Wt(l?{baseDir:l}:void 0),p=new Gt(l?{baseDir:l,nodeId:i}:{nodeId:i}),m=new Xt(l?{baseDir:l}:void 0);In(t),oa({business:t.business?.enabled===!0}),kl(async(y,S)=>{try{await Ml(y,S,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:m})}catch(I){v(S,500,{error:I.message||"internal error"})}}).listen(n,r,()=>{let y=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
15756
|
+
Live dashboard: http://${y}:${n}
|
|
15219
15757
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
15220
|
-
Kanban dashboard: http://${
|
|
15221
|
-
`),console.log(` Boards: ${a.map(S=>S.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var al=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 nl(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(Gt(t.headers)==="foreign"&&Xt(o)){v(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await rr(t,e,r,o,{nodeName:a.config.node?.name}))return;if(o==="GET"&&al.has(r)&&ma("page",r),o==="GET"&&r==="/"){let d=ia();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(vt({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zn({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(vt({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ce(a.config);if(!d){v(e,503,{error:"no node available"});return}let u=await new Promise(f=>{let b="";t.on("data",x=>b+=x),t.on("end",()=>f(b)),t.on("error",()=>f(""))}),g=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:u||"{}"});e.writeHead(g.status,{"Content-Type":"application/json"}),e.end(await g.text())}catch(d){v(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 ce(a.config),u=o==="POST"?void 0:n.searchParams.get("node"),g=o==="POST"?await ie(t):void 0,f=g?.node??u,b=f?d.find(M=>M.url===f):d[0];if(!b){v(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(b.url+r+x,{method:o,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}},...o==="POST"?{body:JSON.stringify({...g,node:void 0})}:{}});v(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){v(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 ie(t),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${g}/api/workflows/editor/chat`,{method:"POST",headers:u,body:JSON.stringify(d??{})}),b=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,b)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ce(a.config);if(!d){v(e,200,{configured:!1,workflows:[]});return}let u=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});v(e,u.status,await u.json().catch(()=>({configured:!1,workflows:[]})))}catch{v(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_a({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ka({peers:O(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(va({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,u=setTimeout(()=>d.abort(),8e3);try{let g=Ht(await ce(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(g.map(async A=>{try{let k=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:d.signal});if(!k.ok)throw new Error(`HTTP ${k.status}`);return{name:A.name,url:A.url,ok:!0,data:await k.json()}}catch(k){return{name:A.name,url:A.url,ok:!1,error:k.message}}}));v(e,200,{nodes:M});return}let f=g.find(M=>M.url===n.searchParams.get("node"));if(!f){v(e,400,{error:"Select a known node"});return}let b=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(b)||o==="POST"&&["register","ended","action","retry","clear"].includes(b))){v(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Dt(t)):void 0,y=await fetch(f.url+"/monitor/"+b+(b==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):b==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:d.signal,headers:{"Content-Type":"application/json",...f.token?{Authorization:`Bearer ${f.token}`}:{}}});v(e,y.status,await y.json())}catch(g){v(e,502,{error:g.message})}finally{clearTimeout(u)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Dn({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qn({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fn({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Un({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sa({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",u=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(Wn({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:u,peers:O(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(Gn({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){la(t,e);return}if(o==="POST"&&r==="/api/setup"){await da(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await ca(t,e);return}if(o==="GET"&&r==="/admin"){Aa(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Ba(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Pa(t,e,O(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}Xa(t,e,O(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 kl(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await ft(t,e,r,g=>lr(g,a.config));return}let u=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(u){let g=decodeURIComponent(u[1]),f=g.indexOf("::");if(f>0){let b=g.slice(0,f),x=g.slice(f+2),y=a.config.node?.id||a.config.node?.name||"local";if(b===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===b);if(M){let A=At(M.url.replace(/\/+$/,""),a.config);if(A){await or(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}v(e,404,{error:`unknown node "${b}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let u=At(d,a.config);if(!u){v(e,404,{error:`unknown peer: ${d}`});return}let g=(n.search||"").replace(/[?&]peer=[^&]*/g,b=>b.startsWith("?")?"?":"");await or(t,e,u,r+(g==="?"?"":g));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ka(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await _l(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-VITHTLEC.js"),g=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",f=await d({running:g});v(e,200,f)}catch(d){v(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(Qa({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Ya(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Za({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(en({peers:O(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 dl(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 bn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ft(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await wn(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){En(t,e,c[1],O(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",u=d.startsWith("Bearer ")?d.slice(7):"";if(u!==a.token){let g=new V,f=u?g.verify(u):null;if(!f||!ue(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ma(t,e);return}if(r.startsWith("/api/admin/approvals")){await za(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await Oa(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Sn(t,e,r);return}if(r.startsWith("/api/admin/")){await Ia(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(Ea);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){v(e,400,{error:"invalid asset name"});return}let u=yl("web/"+d);try{let g=await wl(u),f=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",b=n.searchParams.has("v");e.writeHead(200,{"Content-Type":f,"Cache-Control":b?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(g)}catch{v(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Tt(a.config);v(e,200,d)}catch(d){v(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),u=n.searchParams.get("timezone")||"UTC",g=await Tt(a.config,{date:d,timezone:u});v(e,200,g)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(u,g,f,b)=>{let x=parseInt(n.searchParams.get(u)||"",10);return Number.isFinite(x)?Math.max(f,Math.min(b,x)):g};try{let u=await ce(a.config);v(e,200,await Hn(u,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(u){v(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){v(e,400,{error:"day=YYYY-MM-DD query param required"});return}let u=(g,f,b,x)=>{let y=parseInt(n.searchParams.get(g)||"",10);return Number.isFinite(y)?Math.max(b,Math.min(x,y)):f};try{let g=await ce(a.config);v(e,200,await Bn(g,{day:d,tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",40,1,200)}))}catch(g){v(e,502,{error:g.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){v(e,400,{error:"node query param required"});return}let u=n.searchParams,g;if(r==="/api/mesh/thread"){let[f,b,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!f||!b||!x){v(e,400,{error:"agent, channel, chat required"});return}g=`/analytics/thread?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(b)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[f,b]=[u.get("kind"),u.get("key")];if(!f||!b){v(e,400,{error:"kind and key required"});return}g=`/analytics/job?kind=${encodeURIComponent(f)}&key=${encodeURIComponent(b)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[f,b,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!f||!b||!x){v(e,400,{error:"agent, channel, chat required"});return}g=`/analytics/conversation?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(b)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(u.get("tzOffset")||"0")}`}else{let f=u.get("task");if(!f){v(e,400,{error:"task required"});return}g=`/analytics/run/${encodeURIComponent(f)}`}try{await Nn(e,await ce(a.config),d,g)}catch(f){v(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/live/stream"){pl(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),g=d.searchParams.get("agent"),f=d.searchParams.get("task");if(!u||!g||!f){v(e,400,{error:"node, agent, task query params required"});return}await ul(t,e,a,u,g,f);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),g=d.searchParams.get("agent"),f=d.searchParams.get("task"),b=d.searchParams.get("limit")||"50";if(!u||!g){v(e,400,{error:"node and agent query params required"});return}await gl(e,a,u,g,f,b);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),g=d.searchParams.get("task"),f=d.searchParams.get("kind");if(!u||!g||f!=="cancel"&&f!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await fl(t,e,a,u,g,f);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){v(e,400,{error:"node query param required"});return}await Ct(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 u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!u.ok)throw new Error(`HTTP ${u.status}`);let g=await u.json();v(e,200,g)}catch(d){v(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 u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!u.ok){v(e,u.status,{error:`HTTP ${u.status}`});return}v(e,200,await u.json())}catch(d){v(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ie(t);try{let u=await vl(a.config,d);v(e,200,u)}catch(u){v(e,502,{error:u.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!ml(t,e,[`agent:${d}`]))return;await hl(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",u=d.startsWith("Bearer ")?d.slice(7):"";if(u!==a.token){let g=new V,f=u?g.verify(u):null;if(!f||!ue(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){v(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){v(e,400,{error:"node query param required"});return}await Ct(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let u=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let g=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({name:y.name,url:y.url,token:y.token}))],f={flag:!1},b=[];t.on("close",()=>{f.flag=!0;for(let y of b)try{y.abort()}catch{}});let x=setInterval(()=>{if(!f.flag)try{e.write(`: ping
|
|
15758
|
+
Kanban dashboard: http://${y}:${n}
|
|
15759
|
+
`),console.log(` Boards: ${a.map(S=>S.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Al=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 Ml(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(na(t.headers)==="foreign"&&ra(o)){v(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await wr(t,e,r,o,{nodeName:a.config.node?.name,fleet:Jl(a.config),push:Kl(a.config)}))return;if(o==="GET"&&Al.has(r)&&Ea("page",r),o==="GET"&&r==="/"){let c=va();if(!c.configExists||c.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ct({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zn({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ct({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await ue(a.config);if(!c){v(e,503,{error:"no node available"});return}let u=await new Promise(g=>{let w="";t.on("data",x=>w+=x),t.on("end",()=>g(w)),t.on("error",()=>g(""))}),h=await fetch(c.url+r,{method:"POST",headers:{"Content-Type":"application/json",...c.token?{Authorization:`Bearer ${c.token}`}:{}},body:u||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(c){v(e,502,{error:"could not reach the node",message:String(c?.message||c)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let c=await ue(a.config),u=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await de(t):void 0,g=h?.node??u,w=g?c.find(A=>A.url===g):c[0];if(!w){v(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",k=await fetch(w.url+r+x,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});v(e,k.status,await k.json().catch(()=>({error:`HTTP ${k.status}`})))}catch(c){v(e,502,{error:"could not reach the node",message:c?.message||String(c)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let c=await de(t),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:u,body:JSON.stringify(c??{})}),w=await g.json().catch(()=>({error:`HTTP ${g.status}`}));v(e,g.status,w)}catch(c){v(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await ue(a.config);if(!c){v(e,200,{configured:!1,workflows:[]});return}let u=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});v(e,u.status,await u.json().catch(()=>({configured:!1,workflows:[]})))}catch{v(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pa({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ra({peers:O(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(Ia({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,u=setTimeout(()=>c.abort(),8e3);try{let h=Jt(await ue(a.config,c.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let A=await Promise.all(h.map(async C=>{try{let _=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:c.signal});if(!_.ok)throw new Error(`HTTP ${_.status}`);return{name:C.name,url:C.url,ok:!0,data:await _.json()}}catch(_){return{name:C.name,url:C.url,ok:!1,error:_.message}}}));v(e,200,{nodes:A});return}let g=h.find(A=>A.url===n.searchParams.get("node"));if(!g){v(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))){v(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Kt(t)):void 0,k=await fetch(g.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:c.signal,headers:{"Content-Type":"application/json",...g.token?{Authorization:`Bearer ${g.token}`}:{}}});v(e,k.status,await k.json())}catch(h){v(e,502,{error:h.message})}finally{clearTimeout(u)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Jn({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(er({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(tr({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ar({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ba({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let c=n.searchParams.get("agent")||"",u=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!c){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(nr({taskId:decodeURIComponent(i[1]),agentId:c,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:u,peers:O(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(rr({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){ya(t,e);return}if(o==="POST"&&r==="/api/setup"){await wa(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await ka(t,e);return}if(o==="GET"&&r==="/admin"){Ba(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Qa(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Xa(t,e,O(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}on(t,e,O(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let c=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(c==="fleet"){if(r==="/api/admin/activity-graph"){await td(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Et(t,e,r,h=>Cr(h,a.config));return}let u=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(u){let h=decodeURIComponent(u[1]),g=h.indexOf("::");if(g>0){let w=h.slice(0,g),x=h.slice(g+2),k=a.config.node?.id||a.config.node?.name||"local";if(w===k)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let A=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(A){let C=$e(A.url.replace(/\/+$/,""),a.config);if(C){await _r(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}v(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let u=$e(c,a.config);if(!u){v(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await _r(t,e,u,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await sn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await ad(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-QICAXIQB.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",g=await c({running:h});v(e,200,g)}catch(c){v(e,500,{error:c?.message||String(c)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await cn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(un({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mn({peers:O(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 Pl(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 $n(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Et(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ln(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){On(t,e,d[1],O(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let c=t.headers.authorization||"",u=c.startsWith("Bearer ")?c.slice(7):"";if(u!==a.token){let h=new J,g=u?h.verify(u):null;if(!g||!me(g,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await za(t,e);return}if(r.startsWith("/api/admin/approvals")){await Za(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await Ka(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Dn(t,e,r);return}if(r.startsWith("/api/admin/")){await qa(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(Oa);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){v(e,400,{error:"invalid asset name"});return}let u=Zl("web/"+c);try{let h=await ed(u),g=c.endsWith(".map")?"application/json; charset=utf-8":c.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":g,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{v(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await et(a.config);v(e,200,c)}catch(c){v(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let c=n.searchParams.get("date")||new Date().toISOString().slice(0,10),u=n.searchParams.get("timezone")||"UTC",h=await et(a.config,{date:c,timezone:u});v(e,200,h)}catch(c){v(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(u,h,g,w)=>{let x=parseInt(n.searchParams.get(u)||"",10);return Number.isFinite(x)?Math.max(g,Math.min(w,x)):h};try{let u=await ue(a.config);v(e,200,await Vn(u,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(u){v(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let c=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(c)){v(e,400,{error:"day=YYYY-MM-DD query param required"});return}let u=(h,g,w,x)=>{let k=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(k)?Math.max(w,Math.min(x,k)):g};try{let h=await ue(a.config);v(e,200,await Qn(h,{day:c,tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",40,1,200)}))}catch(h){v(e,502,{error:h.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let c=n.searchParams.get("node");if(!c){v(e,400,{error:"node query param required"});return}let u=n.searchParams,h;if(r==="/api/mesh/thread"){let[g,w,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!g||!w||!x){v(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(g)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[g,w]=[u.get("kind"),u.get("key")];if(!g||!w){v(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(g)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[g,w,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!g||!w||!x){v(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(g)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(u.get("tzOffset")||"0")}`}else{let g=u.get("task");if(!g){v(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(g)}`}try{await Yn(e,await ue(a.config),c,h)}catch(g){v(e,502,{error:g.message})}return}if(o==="GET"&&r==="/api/live/stream"){ql(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let c=new URL(t.url||"/","http://localhost"),u=c.searchParams.get("node"),h=c.searchParams.get("agent"),g=c.searchParams.get("task");if(!u||!h||!g){v(e,400,{error:"node, agent, task query params required"});return}await Fl(t,e,a,u,h,g);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),u=c.searchParams.get("node"),h=c.searchParams.get("agent"),g=c.searchParams.get("task"),w=c.searchParams.get("limit")||"50";if(!u||!h){v(e,400,{error:"node and agent query params required"});return}await Gl(e,a,u,h,g,w);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),u=c.searchParams.get("node"),h=c.searchParams.get("task"),g=c.searchParams.get("kind");if(!u||!h||g!=="cancel"&&g!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Xl(t,e,a,u,h,g);return}if(o==="POST"&&r==="/api/voice/stop"){let c=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!c){v(e,400,{error:"node query param required"});return}await Nt(t,e,a,c,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:c});if(!u.ok)throw new Error(`HTTP ${u.status}`);let h=await u.json();v(e,200,h)}catch(c){v(e,502,{error:c.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:c});if(!u.ok){v(e,u.status,{error:`HTTP ${u.status}`});return}v(e,200,await u.json())}catch(c){v(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await de(t);try{let u=await Yl(a.config,c);v(e,200,u)}catch(u){v(e,502,{error:u.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let c=p[1];if(!Ul(t,e,[`agent:${c}`]))return;await Wl(t,e,a.config,c);return}if(r.startsWith("/api/")&&a.token){let c=t.headers.authorization||"",u=c.startsWith("Bearer ")?c.slice(7):"";if(u!==a.token){let h=new J,g=u?h.verify(u):null;if(!g||!me(g,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){v(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let c=n.searchParams.get("node");if(!c){v(e,400,{error:"node query param required"});return}await Nt(t,e,a,c,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let u=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(k=>({name:k.name,url:k.url,token:k.token}))],g={flag:!1},w=[];t.on("close",()=>{g.flag=!0;for(let k of w)try{k.abort()}catch{}});let x=setInterval(()=>{if(!g.flag)try{e.write(`: ping
|
|
15222
15760
|
|
|
15223
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let
|
|
15761
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let k of h)(async()=>{let A={Accept:"text/event-stream"};k.token&&(A.Authorization=`Bearer ${k.token}`);let C=new AbortController;w.push(C);try{let _=await fetch(`${k.url.replace(/\/+$/,"")}/events${u?`?${u}`:""}`,{headers:A,signal:C.signal});if(!_.ok||!_.body)return;let M=_.body.getReader(),L=new TextDecoder,R="";for(;!g.flag;){let{done:H,value:ee}=await M.read();if(H)break;R+=L.decode(ee,{stream:!0});let B;for(;(B=R.indexOf(`
|
|
15224
15762
|
|
|
15225
|
-
`))>=0;){let D=R.slice(0,B);if(R=R.slice(B+2),
|
|
15763
|
+
`))>=0;){let D=R.slice(0,B);if(R=R.slice(B+2),g.flag)break;try{e.write(D+`
|
|
15226
15764
|
|
|
15227
|
-
`)}catch{
|
|
15228
|
-
`;
|
|
15229
|
-
data: ${JSON.stringify(
|
|
15765
|
+
`)}catch{g.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let c=new URL(t.url||"/","http://localhost"),u=Math.max(1,Math.min(500,Number(c.searchParams.get("limit")||50))),h=c.searchParams.get("workflowId")||void 0,g=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:u,workflowId:h}),x=`?limit=${u}${h?`&workflowId=${encodeURIComponent(h)}`:""}${g?"&summary=1":""}`,k=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],A=await Promise.all(k.map(async L=>{let R={};L.token&&(R.Authorization=`Bearer ${L.token}`);try{let H=new AbortController,ee=setTimeout(()=>H.abort(),5e3);try{let B=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:R,signal:H.signal});if(!B.ok)return[];let D=await B.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(ee)}}catch{return[]}})),C=new Map;for(let L of w)C.set(L.id,L);for(let L of A)for(let R of L)C.set(R.id,R);let _=Array.from(C.values()).sort((L,R)=>L.updatedAt<R.updatedAt?1:-1).slice(0,u),M=g?_.map(L=>jl(L)):_;v(e,200,{runs:M})}catch(c){v(e,502,{error:"runs fetch failed",message:c.message||String(c)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let c=decodeURIComponent(f[1]),u=a.workflowRuns.get(c);if(u){v(e,200,{run:u});return}let h=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(g=>({url:g.url,token:g.token}))];for(let g of h)try{let w={};g.token&&(w.Authorization=`Bearer ${g.token}`);let x=await fetch(`${g.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(c)}`,{headers:w});if(x.ok){v(e,200,await x.json());return}}catch{}v(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let u=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${u}/api/actions/builtin`,{headers:c}),g=await h.json().catch(()=>({error:`HTTP ${h.status}`}));v(e,h.status,g)}catch(c){v(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let y=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(y){try{let c=await de(t).catch(()=>({})),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${h}/workflows/${encodeURIComponent(y[1])}/run`,{method:"POST",headers:u,body:JSON.stringify(c??{})}),w=await g.json().catch(()=>({error:`HTTP ${g.status}`}));v(e,g.status,w)}catch(c){v(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&sr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(u,h,g)=>{if(a.token)return!0;let w=lt(u);if(!w)return!0;let x=new J().verify(w);if(!x)return v(h,401,{error:"invalid or revoked token"}),!1;for(let k of g)if(!me(x,k))return v(h,403,{error:`token missing scope: ${k}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){v(e,200,a.boards.map(c=>({id:c.id,name:c.name,source:c.source,primaryToolLabel:c.primaryToolLabel,labels:c.labels,columns:c.columns,timeRangeDays:c.timeRangeDays})));return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(S&&o==="GET"){let c=a.sources.get(S[1]);if(!c){v(e,404,{error:"unknown board"});return}try{let u=typeof c.listMembers=="function"?await c.listMembers():[];v(e,200,u)}catch(u){v(e,502,{error:u.message})}return}let I=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(I&&o==="GET"){let c=a.sources.get(I[1]);if(!c){v(e,404,{error:"unknown board"});return}try{let u=typeof c.listMilestones=="function"?await c.listMilestones():[];v(e,200,u)}catch(u){v(e,502,{error:u.message})}return}let b=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(b&&o==="PATCH"){let[,c,u]=b,h=decodeURIComponent(u),g=a.boards.find(C=>C.id===c);if(!g){v(e,404,{error:`unknown board: ${c}`});return}let w=a.sources.get(c);if(!w){v(e,503,{error:`board "${c}" source unavailable`});return}let x=await de(t),k=g.columns.find(C=>C.id===x.to),A=g.columns.find(C=>C.id===x.from);if(!k){v(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await $l(w,h,A,k),Rt({actor:Pt(t),action:"move",boardId:c,itemId:h,payload:{from:x.from,to:x.to}}),v(e,200,{ok:!0})}catch(C){v(e,502,{error:C.message||"transition failed"})}return}if(E){let[,c,u]=E,h=u?decodeURIComponent(u):void 0,g=a.boards.find(x=>x.id===c);if(!g){v(e,404,{error:`unknown board: ${c}`});return}let w=a.sources.get(c);if(!w){v(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!h){let{columns:x,totals:k}=await Il(g,w,n.searchParams);v(e,200,{columns:x,totals:k});return}if(o==="GET"&&h){try{let x=typeof w.getItem=="function"?await w.getItem(h):null;if(!x){v(e,404,{error:"not found"});return}v(e,200,x)}catch(x){v(e,502,{error:x.message})}return}if(o==="PATCH"&&h){let x=await de(t);try{let k=typeof w.updateItem=="function"?await w.updateItem(h,x):null;if(!k){v(e,501,{error:"update unsupported"});return}Rt({actor:Pt(t),action:"update",boardId:c,itemId:h,payload:x}),v(e,200,k)}catch(k){v(e,502,{error:k.message})}return}if(o==="POST"&&!h){let x=await de(t);if(!x.title){v(e,400,{error:"title required"});return}if(!w.capabilities.create||!w.create){v(e,400,{error:`source ${w.type} does not support create`});return}try{let k=await w.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});Rt({actor:Pt(t),action:"create",boardId:c,itemId:k.id,payload:{title:x.title}}),v(e,201,k)}catch(k){v(e,502,{error:k.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let c=r.replace(/^\/+|\/+$/g,""),h={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[c];if(h){e.writeHead(302,{Location:h}),e.end();return}}v(e,404,{error:"not found",path:r})}async function Il(t,e,a){if(!e.capabilities.listAll||!e.listAll){let c={};for(let u of t.columns)c[u.id]=[];return{columns:c,totals:Object.fromEntries(t.columns.map(u=>[u.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(c=>c.kind!=="closed"),m=t.columns.some(c=>c.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],y=m?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],S={};for(let c of t.columns)S[c.id]=[];let I=t.columns.find(c=>c.kind==="closed");for(let c of y)I&&S[I.id].push({...c,stage:I.id});let b=t.columns.filter(c=>c.kind!=="closed");for(let c of f){let u=Bt(c,b);if(!u)continue;let h=S[u];h&&h.push({...c,stage:u})}if(i)for(let c of Object.keys(S))S[c]=S[c].filter(u=>u.assignee===i);for(let c of Object.keys(S))S[c].sort((u,h)=>{let g=(u.priority??99)-(h.priority??99);return g!==0?g:(h.updatedAt||"").localeCompare(u.updatedAt||"")});let E=Object.fromEntries(Object.entries(S).map(([c,u])=>[c,u.length]));return{columns:S,totals:E}}async function $l(t,e,a,n){let r=zt(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 jl(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 Ll(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 ia(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Rt(t){try{let e=Ie(process.cwd(),".agentx");Sr(e)||Sl(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
15766
|
+
`;_l(Ie(e,"board-audit.jsonl"),a)}catch{}}function Pt(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function Rl(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,l,d,p,m,f,y,S]=await Promise.all([fetch(t+"/health",{headers:r,signal:a}).catch(()=>null),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),fetch(t+"/mesh",{headers:r,signal:a}).catch(()=>null),fetch(t+"/crons",{headers:r,signal:a}).catch(()=>null),fetch(t+"/crons/runs"+s,{headers:r,signal:a}).catch(()=>null),fetch(t+"/talk",{headers:r,signal:a}).catch(()=>null),fetch(t+"/routines",{headers:r,signal:a}).catch(()=>null),fetch(t+"/attach/sessions",{headers:r,signal:a}).catch(()=>null)]);if(!l||!l.ok)return o.error=l?`HTTP ${l.status}`:"unreachable",o;let I=await l.json();if(o.agents=I.map(b=>({id:b.id,name:b.name,tier:b.tier,model:b.model,skillCount:Number.isFinite(b.skillCount)?b.skillCount:void 0,active:b.active||0,total:b.total||0,errors:b.errors||0,lastActive:b.lastActive,lastSummary:b.lastSummary,hourlyTasks:Array.isArray(b.hourlyTasks)?b.hourlyTasks:void 0,runningTasks:Array.isArray(b.runningTasks)?b.runningTasks:[]})),i&&i.ok){let b=await i.json();o.uptimeSec=b.uptime,typeof b.inflight?.total=="number"&&(o.inflight=b.inflight.total),b.restart&&typeof b.restart.state=="string"&&(o.restart=b.restart),o.name=b.node?.name||b.node?.id||t,o.id=b.node?.id||t,b.usage&&(o.usage=b.usage)}if(p&&p.ok){let b=await p.json();o.crons=b.map(E=>({id:E.id,enabled:E.enabled===!0,schedule:String(E.schedule||""),timezone:E.timezone,agent:String(E.agent||""),kind:typeof E.command=="string"&&E.command.trim()?"command":"agent",model:E.model,nextRun:E.nextRun,retryPending:E.retryPending===!0,consecutiveErrors:Number(E.consecutiveErrors)||0}))}if(m&&m.ok){let b=await m.json();o.cronRuns=Array.isArray(b.runs)?b.runs:[]}if(y&&y.ok){let b=await y.json().catch(()=>null);b&&Array.isArray(b.routines)&&(o.routines=b.routines.slice(0,Qt.routines))}if(f&&f.ok){let b=await f.json().catch(()=>null);b?.active&&b.kind==="lesson"&&(o.lesson={agentId:b.agentId??null,mode:String(b.mode||"teach"),goal:String(b.goal||""),step:Number(b.step)||0,saying:String(b.saying||""),startedAt:String(b.startedAt||"")})}if(S&&S.ok){let b=await S.json().catch(()=>null);b&&Array.isArray(b.sessions)&&zl(o,b.sessions,b.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await Ol(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Qe=null;function Pl(t){if(Qe)return Qe;let e=Ie(process.cwd(),".agentx/wiki");return Qe=Aa({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Qe}var Ot=new WeakMap;async function Ol(t){if(Ot.has(t))return Ot.get(t);try{let e=t.ok?await t.json():null;return Ot.set(t,e),e}catch{return null}}async function tt(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 ue(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=fe(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:fe(a,l)})}let s=await tt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:fe(a,i.url)});return[...o.values()]}var Dl=3e3,Nl=6e3,Hl=5*6e4,Dt=new Map,Ze=new Map;function et(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Ze.get(a);if(n)return n;let r=(async()=>{let o=await ue(t,AbortSignal.timeout(Dl)),s=await Promise.all(o.map(async i=>{let l=await Rl(i.url,i.token,AbortSignal.timeout(Nl),e);return e?l:Bl(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Ze.delete(a));return Ze.set(a,r),r}function Bl(t,e,a=Date.now()){if(e.reachable&&!e.error)return Dt.set(t,{node:e,at:a}),e;let n=Dt.get(t);return!n||a-n.at>Hl?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Du(){Dt.clear(),Ze.clear()}function zl(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 ql(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,d)=>{n||e.write(`event: ${l}
|
|
15767
|
+
data: ${JSON.stringify(d)}
|
|
15230
15768
|
|
|
15231
|
-
`)},o=async()=>{try{let
|
|
15769
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await et(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 Fl(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let S of a.config.dashboard.daemons)i.add(S.url.replace(/\/+$/,""));try{let S=await tt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let I of S)i.add(I.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){v(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=fe(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,m;try{m=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(S){v(e,502,{error:S.message||"upstream connect failed"});return}if(!m.ok||!m.body){v(e,m.status||502,{error:`upstream HTTP ${m.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=m.body.getReader();(async()=>{try{for(;;){let{value:S,done:I}=await f.read();if(I)break;S&&e.write(S)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Ul(t,e,a){let n=lt(t);if(!n)return v(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new J().verify(n);if(!r)return v(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!me(r,o))return v(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Wl(t,e,a,n){let r=a.agents?.[n];if(!r){v(e,404,{error:"unknown agent"});return}if(r.access!=="public"){v(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await de(t)}catch{v(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){v(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(d){v(e,502,{error:d.message||"upstream call failed"})}}async function Gl(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let m of e.config.dashboard.daemons)i.add(m.url.replace(/\/+$/,""));try{let m=await tt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of m)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){v(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=fe(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let m=await fetch(`${s}${p}`,{headers:d}),f=await m.text();t.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(m){v(t,502,{error:m.message||"upstream fetch failed"})}}async function Xl(t,e,a,n,r,o){await Nt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Nt(t,e,a,n,r){let o={};try{o=await de(t)??{}}catch{}let s=await Er(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Er(t,e,a,n){let r=(d,p)=>({status:d,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await tt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of d)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=fe(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function Kl(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=ta(e.keysFile);return{store:()=>{let r=qt();return r?new ma(r):null},publicKey:()=>aa(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Jl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>et(t,n),async nodePost(n,r,o){let s=await Er(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=Le({root:process.cwd()}).items.map(kr)}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=$e(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let d=await l.json();s.items=(d.items??[]).map(kr)}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 d=ye(),p=await Re({root:process.cwd()},r,o,{laterHours:d.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=$e(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let d=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:d.status,body:a(await d.text())}}catch(d){return{status:502,body:{error:d.message||"peer dashboard unreachable"}}}}}}function kr(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 Vl=`
|
|
15232
15770
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
15233
15771
|
|
|
15234
15772
|
Title pattern:
|
|
@@ -15260,16 +15798,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
15260
15798
|
Shape:
|
|
15261
15799
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
15262
15800
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
15263
|
-
`;async function
|
|
15801
|
+
`;async function Yl(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):
|
|
15264
15802
|
- ${r.knownLabels.slice(0,60).join(`
|
|
15265
15803
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
15266
|
-
`),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:
|
|
15804
|
+
`),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:Vl}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let p=(d.content||"").toString(),m=Ql(p);if(!m||typeof m.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(m.labels)?m.labels.filter(y=>typeof y=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:m.title.trim(),description:(m.description||"").toString(),labels:f,assigneeUsername:typeof m.assigneeUsername=="string"?m.assigneeUsername:void 0,kind:typeof m.kind=="string"?m.kind:void 0,raw:p}}function Ql(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 Zl(t){let e=Cl(Tl(import.meta.url));return Ie(e,t)}async function ed(t){return El(t)}function v(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function de(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 Tr(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function O(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:Tr(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 td(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;v(e,200,await Je(await Cr(r,a.config)))}async function Cr(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=St(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=$e(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let m=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return m.ok?{nodeId:i.name||i.url,snap:await m.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Mn(n)}async function ad(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 m=process.env.HOME||"",f=[m&&`${m}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),y=f.find(S=>Sr(S));if(!y){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",y]}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}
|
|
15267
15805
|
|
|
15268
|
-
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=m=>{i+=m.toString("utf8");let
|
|
15269
|
-
`))>=0;){let
|
|
15270
|
-
data: ${
|
|
15806
|
+
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=m=>{i+=m.toString("utf8");let f;for(;(f=i.indexOf(`
|
|
15807
|
+
`))>=0;){let y=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
|
|
15808
|
+
data: ${y.replace(/\n/g," ")}
|
|
15271
15809
|
|
|
15272
|
-
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let
|
|
15810
|
+
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
|
|
15273
15811
|
|
|
15274
|
-
`)}catch{}},15e3),p=()=>{clearInterval(
|
|
15275
|
-
//# sourceMappingURL=board-dashboard-
|
|
15812
|
+
`)}catch{}},15e3),p=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function _r(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((m,f)=>{let y=[];t.on("data",S=>y.push(S)),t.on("end",()=>m(Buffer.concat(y))),t.on("error",f)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let m=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await m.arrayBuffer());e.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(m){v(e,502,{error:`proxy to peer failed: ${m?.message||m}`,target:r})}}function $e(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Tr(n),token:n.dashboardToken||n.token}:null}export{zl as applyAttachSessions,Du as resetLiveCaches,ue as resolveNodeTargets,Ou as startBoardDashboard,Bl as withLastGood};
|
|
15813
|
+
//# sourceMappingURL=board-dashboard-3XJVYDB3.js.map
|