agentix-cli 0.54.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/mac-voice/Sources/AgentXVoice/AgentClient.swift +29 -0
- package/apps/mac-voice/Sources/AgentXVoice/Config.swift +7 -0
- package/apps/mac-voice/Sources/AgentXVoice/Orb.swift +311 -0
- package/apps/mac-voice/Sources/AgentXVoice/OrbMath.swift +57 -0
- package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +14 -1
- package/apps/mac-voice/Sources/AgentXVoice/ResultCard.swift +33 -1
- package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +74 -3
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +197 -14
- package/apps/mac-voice/build.sh +1 -1
- package/dist/{App-VRTLAPRF.js → App-4EM7IPB3.js} +2 -2
- package/dist/{ChatApp-YENWPZT4.js → ChatApp-FYTEEGSU.js} +2 -2
- package/dist/{agent-HVUGHYBF.js → agent-RZ46ZB4W.js} +2 -2
- package/dist/{board-dashboard-3XJVYDB3.js → board-dashboard-NRRYCDZW.js} +826 -180
- package/dist/board-dashboard-NRRYCDZW.js.map +1 -0
- package/dist/{chunk-M67AN4J7.js → chunk-4HEVSWO3.js} +2 -2
- package/dist/{chunk-KLDGJSR5.js → chunk-6AK6WKE5.js} +2 -2
- package/dist/{chunk-ENRJ2QEH.js → chunk-723K4SAW.js} +2 -2
- package/dist/{chunk-UYMK3XNB.js → chunk-76AHNHWC.js} +2 -2
- package/dist/{chunk-XWU7O3S5.js → chunk-C3VRBEJ7.js} +2 -2
- package/dist/{chunk-HQMISQ7L.js → chunk-CELYD5QW.js} +2 -2
- package/dist/{chunk-33QV5O6P.js → chunk-D3LSPFHK.js} +2 -2
- package/dist/chunk-EJ5ISSWW.js +151 -0
- package/dist/chunk-EJ5ISSWW.js.map +1 -0
- package/dist/{chunk-4HNHHKJF.js → chunk-EZN2YXRY.js} +2 -2
- package/dist/{chunk-BKDUCPZ3.js → chunk-GSOL2LW6.js} +2 -2
- package/dist/{chunk-TLFJVLVQ.js → chunk-IL2XLW4H.js} +152 -151
- package/dist/chunk-IL2XLW4H.js.map +1 -0
- package/dist/{chunk-WLRHL2P7.js → chunk-LKJSPO3S.js} +2 -2
- package/dist/{chunk-37EABIOJ.js → chunk-M4AG2YNX.js} +2 -2
- package/dist/{chunk-ZOJUHPD5.js → chunk-O3XG2NVR.js} +18 -18
- package/dist/{chunk-ZOJUHPD5.js.map → chunk-O3XG2NVR.js.map} +1 -1
- package/dist/{chunk-QYHABRLM.js → chunk-SA23V7WX.js} +2 -2
- package/dist/chunk-U4H35SJS.js +15 -0
- package/dist/chunk-U4H35SJS.js.map +1 -0
- package/dist/{chunk-3RCFUIYR.js → chunk-UIVHSYCN.js} +9 -9
- package/dist/chunk-UIVHSYCN.js.map +1 -0
- package/dist/{chunk-3W2KMI5O.js → chunk-W4YMMWJL.js} +2 -2
- package/dist/{chunk-6JHA3ZE6.js → chunk-WKMTT2UY.js} +211 -197
- package/dist/chunk-WKMTT2UY.js.map +1 -0
- package/dist/chunk-WOMQ2VGA.js +5 -0
- package/dist/{chunk-QX4R5WY7.js.map → chunk-WOMQ2VGA.js.map} +1 -1
- package/dist/chunk-X5C5W3E4.js +3 -0
- package/dist/chunk-X5C5W3E4.js.map +1 -0
- package/dist/{chunk-2TJYZF4E.js → chunk-XEOAKD5C.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-IA7ZPE56.js +2 -0
- package/dist/config-HPN2F7LH.js +2 -0
- package/dist/config-mutator-7GPTMTVB.js +2 -0
- package/dist/doctor-IBWQVQV4.js +2 -0
- package/dist/index.d.ts +185 -19
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/program-G6DIFJUF.js +2 -0
- package/dist/{promote-H6ZHJXTY.js → promote-T4UJROEH.js} +2 -2
- package/dist/query-VUJC4Y5O.js +2 -0
- package/dist/registry-DX2RI7I7.js +2 -0
- package/dist/{request-planner-ABD4WIGM.js → request-planner-B7DE7VJR.js} +2 -2
- package/dist/{review-candidates-B6574GOJ.js → review-candidates-4YJHIBAF.js} +2 -2
- package/dist/routing-MZG3UODH.js +2 -0
- package/dist/schedule-tool-A4OFQ4YZ.js +2 -0
- package/dist/scheduler-RHJW2V4M.js +2 -0
- package/dist/seat-2PEI7JRX.js +2 -0
- package/dist/{select-Y7SBUCGJ.js → select-4KIUR27O.js} +2 -2
- package/dist/{set-enabled-ARKMDLXN.js → set-enabled-SE7HQKPF.js} +2 -2
- package/dist/subscriptions-RYVPHVIV.js +2 -0
- package/dist/{tool-5EVYUN2G.js → tool-5VMD7IE4.js} +2 -2
- package/dist/wiki-2QFLAH4U.js +2 -0
- package/dist/wiki-2QFLAH4U.js.map +1 -0
- package/package.json +1 -1
- package/dist/board-dashboard-3XJVYDB3.js.map +0 -1
- package/dist/chunk-3RCFUIYR.js.map +0 -1
- package/dist/chunk-4FFWNPFX.js +0 -15
- package/dist/chunk-4FFWNPFX.js.map +0 -1
- package/dist/chunk-6JHA3ZE6.js.map +0 -1
- package/dist/chunk-BMSPRUEJ.js +0 -150
- package/dist/chunk-BMSPRUEJ.js.map +0 -1
- package/dist/chunk-QX4R5WY7.js +0 -5
- package/dist/chunk-TLFJVLVQ.js.map +0 -1
- package/dist/client-N4XQEAVL.js +0 -2
- package/dist/config-KHKIY6LI.js +0 -2
- package/dist/config-mutator-ZZKFQ7HJ.js +0 -2
- package/dist/doctor-QICAXIQB.js +0 -2
- package/dist/program-ZWNGK3RB.js +0 -2
- package/dist/query-FTE4FLYK.js +0 -2
- package/dist/registry-HDOFVNRK.js +0 -2
- package/dist/routing-BGKZOHOA.js +0 -2
- package/dist/schedule-tool-UDHXTKWV.js +0 -2
- package/dist/scheduler-NQM3HVUY.js +0 -2
- package/dist/seat-VGST5AQB.js +0 -2
- package/dist/wiki-GREI2TSP.js +0 -2
- /package/dist/{App-VRTLAPRF.js.map → App-4EM7IPB3.js.map} +0 -0
- /package/dist/{ChatApp-YENWPZT4.js.map → ChatApp-FYTEEGSU.js.map} +0 -0
- /package/dist/{agent-HVUGHYBF.js.map → agent-RZ46ZB4W.js.map} +0 -0
- /package/dist/{chunk-M67AN4J7.js.map → chunk-4HEVSWO3.js.map} +0 -0
- /package/dist/{chunk-KLDGJSR5.js.map → chunk-6AK6WKE5.js.map} +0 -0
- /package/dist/{chunk-ENRJ2QEH.js.map → chunk-723K4SAW.js.map} +0 -0
- /package/dist/{chunk-UYMK3XNB.js.map → chunk-76AHNHWC.js.map} +0 -0
- /package/dist/{chunk-XWU7O3S5.js.map → chunk-C3VRBEJ7.js.map} +0 -0
- /package/dist/{chunk-HQMISQ7L.js.map → chunk-CELYD5QW.js.map} +0 -0
- /package/dist/{chunk-33QV5O6P.js.map → chunk-D3LSPFHK.js.map} +0 -0
- /package/dist/{chunk-4HNHHKJF.js.map → chunk-EZN2YXRY.js.map} +0 -0
- /package/dist/{chunk-BKDUCPZ3.js.map → chunk-GSOL2LW6.js.map} +0 -0
- /package/dist/{chunk-WLRHL2P7.js.map → chunk-LKJSPO3S.js.map} +0 -0
- /package/dist/{chunk-37EABIOJ.js.map → chunk-M4AG2YNX.js.map} +0 -0
- /package/dist/{chunk-QYHABRLM.js.map → chunk-SA23V7WX.js.map} +0 -0
- /package/dist/{chunk-3W2KMI5O.js.map → chunk-W4YMMWJL.js.map} +0 -0
- /package/dist/{chunk-2TJYZF4E.js.map → chunk-XEOAKD5C.js.map} +0 -0
- /package/dist/{client-N4XQEAVL.js.map → client-IA7ZPE56.js.map} +0 -0
- /package/dist/{config-KHKIY6LI.js.map → config-HPN2F7LH.js.map} +0 -0
- /package/dist/{config-mutator-ZZKFQ7HJ.js.map → config-mutator-7GPTMTVB.js.map} +0 -0
- /package/dist/{doctor-QICAXIQB.js.map → doctor-IBWQVQV4.js.map} +0 -0
- /package/dist/{program-ZWNGK3RB.js.map → program-G6DIFJUF.js.map} +0 -0
- /package/dist/{promote-H6ZHJXTY.js.map → promote-T4UJROEH.js.map} +0 -0
- /package/dist/{query-FTE4FLYK.js.map → query-VUJC4Y5O.js.map} +0 -0
- /package/dist/{registry-HDOFVNRK.js.map → registry-DX2RI7I7.js.map} +0 -0
- /package/dist/{request-planner-ABD4WIGM.js.map → request-planner-B7DE7VJR.js.map} +0 -0
- /package/dist/{review-candidates-B6574GOJ.js.map → review-candidates-4YJHIBAF.js.map} +0 -0
- /package/dist/{routing-BGKZOHOA.js.map → routing-MZG3UODH.js.map} +0 -0
- /package/dist/{schedule-tool-UDHXTKWV.js.map → schedule-tool-A4OFQ4YZ.js.map} +0 -0
- /package/dist/{scheduler-NQM3HVUY.js.map → scheduler-RHJW2V4M.js.map} +0 -0
- /package/dist/{seat-VGST5AQB.js.map → seat-2PEI7JRX.js.map} +0 -0
- /package/dist/{select-Y7SBUCGJ.js.map → select-4KIUR27O.js.map} +0 -0
- /package/dist/{set-enabled-ARKMDLXN.js.map → set-enabled-SE7HQKPF.js.map} +0 -0
- /package/dist/{wiki-GREI2TSP.js.map → subscriptions-RYVPHVIV.js.map} +0 -0
- /package/dist/{tool-5EVYUN2G.js.map → tool-5VMD7IE4.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as ka}from"./chunk-WWMFNLKD.js";import{a as Aa}from"./chunk-GUJB53QU.js";import{a as C,b as Ma,c as Ia,d as $a,e as La,f as we,g as ja,h as Ra,i as Na,j as Oa,k as Da}from"./chunk-76AHNHWC.js";import{a as Pa}from"./chunk-Z3IP66SL.js";import{a as _a,b as ue,c as Ea,d as $,e as P,j as Ge,k as Xe,l as Z,m as U,n as Ke,o as Sa,p as Ta,q as Ca}from"./chunk-KAFO5QZR.js";import{A as Be,G as se,H as ua,I as ma,N as ga,P as ye,Q as ze,R as qe,S as Ue,T as Fe,U as xa,V as va,W as ba,X as We,Z as ya,a as ra,aa as wa,c as De,d as ht,e as oa,i as sa,k as ia,m as Q,n as ge,o as gt,z as He}from"./chunk-UIVHSYCN.js";import{g as aa,h as na}from"./chunk-723K4SAW.js";import{o as la,r as da}from"./chunk-S7CVSKOX.js";import{a as fa,b as ha}from"./chunk-LQRBGQIR.js";import"./chunk-SA23V7WX.js";import"./chunk-W4YMMWJL.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ca,c as pa}from"./chunk-2D3RYIDU.js";import{a as Qt,c as mt,d as ft,h as Zt,i as ea,j as ta}from"./chunk-CELYD5QW.js";import"./chunk-WP6KLXTP.js";import{a as ut}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-O3XG2NVR.js";import"./chunk-EZN2YXRY.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-LKJSPO3S.js";import{b as Yt}from"./chunk-C3VRBEJ7.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-M4AG2YNX.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as Jt,b as Vt,c as Zr,n as Y,q as pt}from"./chunk-U4H35SJS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function xt(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 Ha(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:xt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ee={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"/>'},xe=(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>",Je=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+xe(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ba(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 ma}from"./chunk-WWMFNLKD.js";import{a as ba}from"./chunk-GUJB53QU.js
|
|
|
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">${xe(ee.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${xe(ee.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{a as ma}from"./chunk-WWMFNLKD.js";import{a as ba}from"./chunk-GUJB53QU.js
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${Je(ee.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
|
+
${Je(ee.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
|
+
${Je(ee.pulse,"In motion","run-count")}
|
|
35
35
|
<div id="running" class="bf-col"></div>
|
|
36
36
|
</aside>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
${
|
|
39
|
+
${Je(ee.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${
|
|
41
|
+
<div class="bf-search">${xe(ee.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 @@ ${Fe(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">${xe(ee.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">${xe(ee.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>${xe(ee.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 @@ ${Fe(Y.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css
|
|
88
|
+
</div>`,css:eo,scripts:`<script>${ue({decayOf:xt,rankByDecay:Ha})}const ICON = ${JSON.stringify(ee)};${to}</script>`})}var eo=`
|
|
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
|
+
}`,to=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 vt(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 u=r[p].from-r[p-1].to;u<d&&(d=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,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 bt(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 za(t,e=[],a){let{bands:n,gaps:r}=vt(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(T=>l.startedAt>=T.from&&l.startedAt<=T.to);if(d===-1)continue;let p=n[d],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,y=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:d,track:0,left:f,width:y,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>bt(l.runs.filter(u=>u.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 ao}from"crypto";import{readFileSync as no,statSync as ro}from"fs";import{resolve as oo,dirname as so}from"path";import{fileURLToPath as io}from"url";var qa=new Map;function Ve(t){let e=qa.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=so(io(import.meta.url)),r=oo(n,"web",t),o=ro(r),s=o.size<8e6?ao("sha1").update(no(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return qa.set(t,a),a}var ae={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"/>'},Ye=(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>",lo=[["agent","Agent",ae.bot],["client","Client",ae.user],["project","Project",ae.folder],["channel","Channel",ae.route],["node","Node",ae.mesh]],Ua={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 Fa(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">${Ua[e]}</p>
|
|
786
786
|
</div>
|
|
787
787
|
<div class="ac-tools">
|
|
788
788
|
<div class="ac-seg" id="view" role="radiogroup" aria-label="View">
|
|
789
|
-
${[["timeline","Timeline",
|
|
789
|
+
${[["timeline","Timeline",ae.timeline],["map","Map",ae.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Ye(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":""}>${Ye(ae.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
|
+
${lo.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ye(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">${Ye(ae.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="${Ve("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:co,scripts:`<script>${ue({computeBands:vt,packTracks:bt,buildTimeline:za})}const ICON = ${JSON.stringify(ae)};const SUB = ${JSON.stringify(Ua)};${po}</script>`})}var co=`
|
|
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
|
+
`,po=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 Wa(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:uo,scripts:`<script src="${Ve("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var uo=`
|
|
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 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
|
-
${
|
|
1048
|
-
${
|
|
1049
|
-
${
|
|
1046
|
+
`;import{createServer as rd}from"http";import{appendFileSync as od,existsSync as Gr,mkdirSync as sd}from"fs";import{readFile as id}from"fs/promises";import{fileURLToPath as ld}from"url";import{dirname as dd,resolve as Pe}from"path";Zr();var Ga='/*! 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 Qe,readFileSync as Ka,writeFileSync as Ja,rmSync as cc,mkdirSync as vo,copyFileSync as bo,readdirSync as yo}from"fs";import{resolve as ke}from"path";pt();var ne={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 Xa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Ge({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.`})+Xe([{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+fo()+Sa,css:go,scripts:`${e}<script>${Ta}
|
|
1047
|
+
${Ca}
|
|
1048
|
+
${mo}
|
|
1049
|
+
${xo}</script>`})}var mo=`
|
|
1050
1050
|
(function(){
|
|
1051
1051
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1052
1052
|
async function refresh() {
|
|
@@ -1107,8 +1107,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
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 fo(){let t=ha().business?`<button data-tab="business">Business</button>
|
|
1111
|
+
`:"";return ho.replace("__BUSINESS_TABS__",t)}var ho=`
|
|
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>
|
|
@@ -1251,8 +1251,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1251
1251
|
<div id="global-msg" class="msg"></div>
|
|
1252
1252
|
|
|
1253
1253
|
<section id="tab-agents" class="tab active">
|
|
1254
|
-
${
|
|
1255
|
-
${
|
|
1254
|
+
${U({icon:ne.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
|
+
${Z({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>
|
|
@@ -1274,8 +1274,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1274
1274
|
</section>
|
|
1275
1275
|
|
|
1276
1276
|
<section id="tab-channels" class="tab">
|
|
1277
|
-
${
|
|
1278
|
-
${
|
|
1277
|
+
${U({icon:ne.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
|
+
${Z({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 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1360
1360
|
</div>
|
|
1361
1361
|
</details>
|
|
1362
1362
|
|
|
1363
|
-
<div id="ch-chatapps-label">${
|
|
1363
|
+
<div id="ch-chatapps-label">${Ke({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">${Ke({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
|
|
@@ -1381,8 +1381,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1381
1381
|
</section>
|
|
1382
1382
|
|
|
1383
1383
|
<section id="tab-crons" class="tab">
|
|
1384
|
-
${
|
|
1385
|
-
${
|
|
1384
|
+
${U({icon:ne.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
|
+
${Z({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">
|
|
@@ -1479,8 +1479,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1479
1479
|
</section>
|
|
1480
1480
|
|
|
1481
1481
|
<section id="tab-webhooks" class="tab">
|
|
1482
|
-
${
|
|
1483
|
-
${
|
|
1482
|
+
${U({icon:ne.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
|
+
${Z({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>
|
|
@@ -1499,10 +1499,10 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1499
1499
|
</section>
|
|
1500
1500
|
|
|
1501
1501
|
<section id="tab-mesh" class="tab">
|
|
1502
|
-
${
|
|
1502
|
+
${U({icon:ne.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
|
+
${Z({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
|
+
${Ke({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>
|
|
@@ -1529,8 +1529,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1529
1529
|
</section>
|
|
1530
1530
|
|
|
1531
1531
|
<section id="tab-business" class="tab">
|
|
1532
|
-
${
|
|
1533
|
-
${
|
|
1532
|
+
${U({icon:ne.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
|
+
${Z({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>
|
|
@@ -1617,8 +1617,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1617
1617
|
</section>
|
|
1618
1618
|
|
|
1619
1619
|
<section id="tab-boards-cfg" class="tab">
|
|
1620
|
-
${
|
|
1621
|
-
${
|
|
1620
|
+
${U({icon:ne.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
|
+
${Z({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>
|
|
@@ -1642,8 +1642,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1642
1642
|
</section>
|
|
1643
1643
|
|
|
1644
1644
|
<section id="tab-actions" class="tab">
|
|
1645
|
-
${
|
|
1646
|
-
${
|
|
1645
|
+
${U({icon:ne.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
|
+
${Z({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>
|
|
@@ -1698,8 +1698,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1698
1698
|
</section>
|
|
1699
1699
|
|
|
1700
1700
|
<section id="tab-tokens" class="tab">
|
|
1701
|
-
${
|
|
1702
|
-
${
|
|
1701
|
+
${U({icon:ne.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
|
+
${Z({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>
|
|
@@ -1718,8 +1718,8 @@ ${Xr}</script>`})}var Fr=`
|
|
|
1718
1718
|
</section>
|
|
1719
1719
|
|
|
1720
1720
|
<section id="tab-advanced" class="tab">
|
|
1721
|
-
${
|
|
1722
|
-
${
|
|
1721
|
+
${U({icon:ne.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
|
+
${Z({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 @@ ${Xr}</script>`})}var Fr=`
|
|
|
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
|
+
`,go=`
|
|
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
|
+
`,xo=`
|
|
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 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}
|
|
4763
|
+
`;function Va(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({peers:a,localToken:n}))}async function Ya(t,e){let a=kt();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 Ro(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await wo(t),r={"GET /api/admin/state":()=>_o(),"POST /api/admin/agents":()=>Mo(n),"PATCH /api/admin/agents":()=>Io(n),"DELETE /api/admin/agents":()=>$o(n),"POST /api/admin/agents/access":()=>Eo(n),"POST /api/admin/channels/telegram":()=>Lo(n),"DELETE /api/admin/channels/telegram":()=>as(n),"POST /api/admin/channels/telegram/toggle":()=>ns(n),"POST /api/admin/crons":()=>rs(n),"DELETE /api/admin/crons":()=>os(n),"POST /api/admin/config/raw":()=>ss(n),"GET /api/admin/tokens":()=>So(),"POST /api/admin/tokens":()=>To(n),"DELETE /api/admin/tokens":()=>Co(n),"POST /api/admin/agents/test":()=>Ao(n),"POST /api/admin/agents/integrations":()=>Bo(n),"DELETE /api/admin/agents/integrations":()=>zo(n),"PATCH /api/admin/agents/integrations":()=>qo(n),"PATCH /api/admin/channels/telegram":()=>jo(n),"POST /api/admin/channels/slack":()=>Jo(n),"POST /api/admin/channels/slack/toggle":()=>Vo(n),"POST /api/admin/channels/discord":()=>Yo(n),"POST /api/admin/channels/discord/toggle":()=>Qo(n),"POST /api/admin/channels/gitlab":()=>Zo(n),"POST /api/admin/channels/gitlab/toggle":()=>es(n),"GET /api/admin/channels/whatsapp/state":()=>Me("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Me("/webrtc/history"),"POST /api/admin/actions":()=>bs(n),"DELETE /api/admin/actions":()=>ys(n),"POST /api/admin/actions/run":()=>ws(n),"GET /api/admin/channels/whatsapp/chats":()=>Me("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Me("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ie("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ts(n),"POST /api/admin/webhooks":()=>Uo(n),"PATCH /api/admin/webhooks":()=>Fo(n),"DELETE /api/admin/webhooks":()=>Ko(n),"POST /api/admin/mesh/peers":()=>Wo(n),"DELETE /api/admin/mesh/peers":()=>Go(n),"POST /api/admin/mesh/toggle":()=>Xo(n),"GET /api/admin/files":()=>Po(t),"GET /api/admin/files/read":()=>No(t),"PUT /api/admin/files":()=>Oo(n),"POST /api/admin/files/skill":()=>Do(n),"DELETE /api/admin/files/skill":()=>Ho(n),"POST /api/admin/business/orgchart":()=>is(n),"DELETE /api/admin/business/orgchart":()=>ls(n),"POST /api/admin/business/project":()=>ds(n),"DELETE /api/admin/business/project":()=>us(n),"POST /api/admin/business/client":()=>cs(n),"DELETE /api/admin/business/client":()=>ps(n),"POST /api/admin/business/contact":()=>ms(n),"DELETE /api/admin/business/contact":()=>fs(n),"POST /api/admin/boards":()=>hs(n),"DELETE /api/admin/boards":()=>gs(n),"POST /api/admin/boards/columns":()=>xs(n),"DELETE /api/admin/boards/columns":()=>vs(n),"POST /api/admin/notifications":()=>_s(n),"POST /api/admin/screen":()=>Es(n),"POST /api/admin/webhooks/triggers":()=>Ss(n),"POST /api/admin/mesh/health":()=>ks(n),"GET /api/admin/projects":()=>Me("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ie("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ie("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ie("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ie("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ie("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ie("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ie("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ie("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){yt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();yt(e,200,i)}catch(n){yt(e,400,{error:n.message||"admin op failed"})}}function yt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function wo(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 ko(t){let e=ke(process.cwd(),t);if(!Qe(e))return[];let a=[];for(let n of yo(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ka(ke(e,n.name),"utf-8")))}catch{}return a}function kt(){let t=ke(process.cwd(),"agentx.json");return Qe(t)?JSON.parse(Ka(t,"utf-8")):null}function _o(){let t=kt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([c,m])=>({id:c,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(h=>{let x=h.credentials||{},k={};for(let[v,_]of Object.entries(x))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?k[v]=process.env[_]?"set":"unset":typeof _=="string"&&(k[v]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:x,credStatus:k,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([c,m])=>({id:c,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([c,m])=>({id:c,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.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}},u=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:{}},w=t.notifications||{},T={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:la(w.local),ntfy:Na(t.channels?.ntfy)},g=[];try{g=ko(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,h)=>m.id.localeCompare(h.id))}catch{}let S=(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:u,nodeName:t.node?.name,business:y,boards:S,notifications:T,screen:ya(t.screen),actions:g}}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}=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 So(){return new Q().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 To(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 Q().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Co(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Q().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ao(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=Y();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 Mo(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=en(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ke(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),d=ke(i,"CLAUDE.md");if(!Qe(d))try{vo(i,{recursive:!0}),Ja(d,`# ${a}
|
|
4764
4764
|
|
|
4765
4765
|
${s||"You are "+a+"."}
|
|
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>
|
|
4766
|
+
`)}catch{}return{summary:l}}function Io(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=en(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 $o(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 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}=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 jo(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 Me(t){let{url:e,headers:a}=_t(),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 ie(t,e){let{url:a,headers:n}=_t(),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 Ro(t,e){try{let{url:a,headers:n}=_t(),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 _t(){let t="http://127.0.0.1:18800",e={};try{let a=Y();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ie(t){let a=kt()?.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 wt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Po(t){let e=wt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ye(Ie(e));return{agentId:e,...a}}function No(t){let e=wt(t,"agent").trim(),a=wt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return ze(Ie(e),a)}function Oo(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=qe(Ie(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Do(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=Ue(Ie(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Ho(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=Fe(Ie(e),a);return{summary:`removed skill "${a}"`,...n}}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)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function zo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function qo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(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 Za=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Uo(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(!Za.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(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let 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 Fo(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"&&Za.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 Wo(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 Go(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 Xo(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 Ko(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 Jo(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 Vo(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 Yo(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 Qo(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 Zo(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 es(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 ts(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-RHJW2V4M.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 as(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 ns(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 rs(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 os(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 ss(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ke(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Qe(n))try{bo(n,r)}catch{}Ja(n,JSON.stringify(a,null,2)+`
|
|
4767
|
+
`,"utf-8");try{let s=Y().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 en(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function is(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function ls(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 ds(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 cs(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 ps(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 us(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 ms(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 fs(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 hs(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let u=l.boards[d];return l.boards[d]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function gs(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 xs(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(u=>u.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(u=>u.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 vs(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 bs(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 ys(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 ws(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 ks(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 _s(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=da(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=Oa(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 Es(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=wa(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ss(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}}pt();import{resolve as As}from"path";function tn(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:Ts,scripts:`${e}<script>${Cs}</script>`})}var Ts=`
|
|
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; }`,Cs=`
|
|
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 nn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(tn({peers:a,localToken:n}))}async function rn(t,e,a){try{let n=t.method==="GET"?void 0:await Os(t),r=Ms(),o={"GET /api/admin/graph/state":()=>Is(r),"POST /api/admin/graph/classifications/approve":()=>$s(r,n),"POST /api/admin/graph/classifications/reject":()=>Ls(r,n),"POST /api/admin/graph/nodes":()=>js(r,n),"PATCH /api/admin/graph/nodes":()=>Rs(r,n),"DELETE /api/admin/graph/nodes":()=>Ps(r,n),"PUT /api/admin/graph/schema":()=>Ns(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Et(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Et(e,200,l)}catch(n){Et(e,400,{error:n?.message||"graph op failed"})}}function Ms(){let t=Y(),e=As(process.cwd(),t.graph.baseDir);return new Yt({baseDir:e})}function Is(t){let e=Y(),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 $s(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=on(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=St(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Ls(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=on(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function on(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 js(t,e){let a=an(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?an(String(e.parentId)):null,o=St({[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 Rs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=St({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ps(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Ns(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 St(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 an(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Et(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Os(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 sn(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:Ds,scripts:`${e}<script>${Hs}</script>`})}var Ds=`
|
|
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
|
+
`,Hs=`
|
|
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 Bs=["yes","no","later"];function le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function ln(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 dn(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(sn({peers:e,localToken:a}))}async function cn(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 le(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=He(s,{includeSnoozed:n.searchParams.get("all")==="1"});return le(e,200,{...i,settings:we(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await ln(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!Bs.includes(d))return le(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=we(s.configPath),u=await Be(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(le(e,200,{ok:!0,message:u.message}),!0):(le(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await ln(t),l={},d=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} 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 u=i.destination.trim();if(!u)l.destination=null;else{let f=ja(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Ra(l,{configPath:s.configPath,reload:s.reload});return p.success?(le(e,200,{ok:!0,settings:we(s.configPath)}),!0):(le(e,400,{error:p.error}),!0)}}catch(i){return le(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return le(e,404,{error:"Not found"}),!0}import{resolve as Us}from"path";import{existsSync as Fs}from"fs";import Ws from"better-sqlite3";function pn(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:zs,scripts:`<script>${qs}</script>`})}var zs=`
|
|
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
|
+
`,qs=`
|
|
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 fn={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 hn(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Tt(t){let e=fn[hn(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 Gs(){let t=Us(process.cwd(),".agentx/db.sqlite");if(!Fs(t))return null;try{let e=new Ws(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function gn(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:a}))}function Xs(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 de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function xn(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Gs();if(!r)return de(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Xs(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(d).all(l);return
|
|
6007
|
+
`,p=r.db.prepare(d).all(l);return de(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(d).all(l);return
|
|
6012
|
+
`,p=r.db.prepare(d).all(l);return de(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
|
-
`,
|
|
6018
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6017
|
+
`,u=r.db.prepare(d).all(l).map(f=>({...f,plain:vn(f.error)}));return de(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return de(e,200,Ks(r.db)),!0;if(n==="activity")return de(e,200,Js(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=un(i.searchParams.get("range"));return de(e,200,mn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=un(i.searchParams.get("range")),d=mn(r.db,l),p=Vs(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 de(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return de(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function vn(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 Ks(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),u=_=>p.length?p[Math.min(p.length-1,Math.floor(p.length*_))].duration_ms:0,f=u(.5),y=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Tt(M),0),g=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Tt(M),0),S=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,
|
|
@@ -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),
|
|
6036
|
+
`).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),x=m.filter(_=>!h.has(_)),v=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(_=>({..._,plain:vn(_.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:T,spendDelta:T-g,idleAgentCount:x.length},perAgent:S,perChannel:c,idleAgents:x,recentErrors:v}}function Js(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 un(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 mn(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,37 +6073,37 @@ 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,d=0,p=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,u=0,f=0,y=0,w=0,T=0,g=0,S={},c={};for(let E of n){let I=Tt(E),j=hn(E.model),R=fn[j],B=(E.tier2_input_tokens||0)/1e6*R.input*.5+(E.tier2_output_tokens||0)/1e6*R.output*.5+(E.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,te=(E.input_tokens||0)+(E.tier2_input_tokens||0),z=(E.output_tokens||0)+(E.tier2_output_tokens||0),D=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),H=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=I,E.day>=s&&(p+=I,w+=E.tasks||0),E.day>=i&&E.day<s&&(g+=I,T+=E.tasks||0),E.day===r&&(l+=I),E.day===o&&(d+=I),E.day===r&&(f+=B),E.day>=s&&(y+=B);let J=S[E.day]||(S[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});J.tasks+=E.tasks||0,J.input+=te,J.output+=z,J.cacheRead+=D,J.cacheCreate+=H,J.cost+=I,J.tier2+=B;let q=J.agents[E.agent_id]||(J.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});q.tasks+=E.tasks||0,q.cost+=I,q.tier2+=B,q.input+=te,q.output+=z,q.cacheRead+=D,q.cacheCreate+=H,E.model&&(q.model=E.model);let V=c[E.agent_id]||(c[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});V.tasks+=E.tasks||0,V.cost+=I,V.tier2+=B,V.input+=te,V.output+=z,V.cacheRead+=D,V.cacheCreate+=H,E.model&&(V.model=E.model)}let m=Object.values(S).sort((E,I)=>E.date<I.date?-1:1),h=0,x=0,k=0,v=0,_=0,M=0;for(let E of m)h+=E.tasks,x+=E.input,k+=E.output,v+=E.cacheRead,_+=E.cacheCreate,M+=E.cost;let A=Object.entries(c).map(([E,I])=>({agent_id:E,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((E,I)=>I.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:y,tier2PctToday:l>0?f/l:0,spendRange:M,avgDailyRange:m.length?M/m.length:0,tasksRange:h,tokensRange:x+k+v+_,cacheHitRange:v+x>0?v/(v+x):0,costPerTaskRange:h>0?M/h:0,spendDeltaWoW:g>0?(p-g)/g:0,tasksDeltaWoW:T>0?(w-T)/T:0},days:m,perAgent:A}}function Vs(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 Ys}from"path";import{existsSync as Qs}from"fs";import Zs from"better-sqlite3";function ei(){let t=Ys(process.cwd(),".agentx/intent/ledger.sqlite");if(!Qs(t))return null;try{let e=new Zs(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-bn>6e4&&(bn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var bn=0;function ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ti(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 yn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ei();if(!r)return ve(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ti(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 u=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 ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),w=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,T=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),g=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,S=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} 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 ve(e,200,{since:s??null,eventsBySource:y,totalDecisions:w,decisionsByOutcome:T,totalDivergences:g,divergencesBySource:S,inFlight:c}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.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
|
+
${u.length?"WHERE "+u.join(" AND "):""}
|
|
6088
6088
|
ORDER BY ts DESC LIMIT @limit
|
|
6089
|
-
`;return
|
|
6089
|
+
`;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}if(n==="divergences"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.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,
|
|
6093
6093
|
event_id
|
|
6094
6094
|
FROM intent_divergences
|
|
6095
|
-
${
|
|
6095
|
+
${u.length?"WHERE "+u.join(" AND "):""}
|
|
6096
6096
|
ORDER BY ts DESC LIMIT @limit
|
|
6097
|
-
`;return
|
|
6097
|
+
`;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],f={limit:p};i&&(u.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
|
|
6101
6101
|
JOIN intent_events e ON e.id = d.event_id
|
|
6102
6102
|
LEFT JOIN intent_resolutions r
|
|
6103
6103
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6104
|
-
WHERE ${
|
|
6104
|
+
WHERE ${u.join(" AND ")}
|
|
6105
6105
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
6106
|
-
`;return
|
|
6106
|
+
`;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}return ve(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function wn(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 kn(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 _n(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:ai,scripts:`<script>${ni}</script>`})}var ai=`
|
|
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
|
+
`,ni=`
|
|
7099
7099
|
(function(){
|
|
7100
7100
|
const $ = (sel) => document.querySelector(sel);
|
|
7101
7101
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -7745,23 +7745,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7745
7745
|
load();
|
|
7746
7746
|
});
|
|
7747
7747
|
})();
|
|
7748
|
-
`;import{resolve as
|
|
7748
|
+
`;import{resolve as Mt,join as xi}from"path";import{existsSync as It,readdirSync as vi,readFileSync as bi}from"fs";import yi from"better-sqlite3";var Sn=String.raw`[\w.-]+(?:/[\w.-]+)+`,ri=new RegExp(`^(?:chat:)?(${Sn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),oi=new RegExp(`^\\[(?:GitLab|GitHub) (${Sn}) `);function En(t){if(!t)return null;let e=t.match(ri);return e?e[1]:null}function Ct(t){if(!t)return null;let e=t.trimStart().match(oi);return e?e[1]:null}function Ze(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():En(typeof n?.chatId=="string"?n.chatId:null)??En(e)??Ct(a)}function si(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function et(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var ii=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,li=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,di=t=>/^issue/i.test(t)?"issue":"mr";function ci(t){let e=t.subject.match(ii)??t.inputPreview.trimStart().match(li);return e?{kind:di(e[1]),n:Number(e[2])}:null}function pi(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 Tn(t){if(!si(t.projectId))return[];let e=ci(t);return e?[e]:pi(t.inputPreview)}var ui=6e4,mi=5*6e4,fi=40,Cn=6,An=new Map;function Mn(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 Tn(n)){let s=et(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=fi)return[...e.values()]}}return[...e.values()]}async function In(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=et(s.project,s.ref),l=An.get(i);l&&n-l.at<(s.github?mi:ui)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Cn)await Promise.all(o.slice(s,s+Cn).map(async i=>{let l=et(i.project,i.ref),d=null;try{d=i.github?await gi(i,e,a):await hi(i,e,a)}catch{}An.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function $n(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 hi(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 $n(`${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 gi(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 $n(`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=Mt(process.cwd(),".agentx/intent/ledger.sqlite");if(!It(t))return null;try{let e=new yi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ln>6e4&&(Ln=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Ln=0;function ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var _e={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 wi(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in _e)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in _e)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in _e)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 _e)return s}return"workflow"}return t}function Pn(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 ki(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 Nn(t,e,a){return oa(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 _i(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&&!At(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!At(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&&!At(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=jn(p);return{id:d,name:l||i||d,avatar:F(l||i||d),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,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:jn(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 jn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function At(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 On(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 Ei(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 Dn(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
|
|
7753
|
+
`).all(r),s=new Map,i=new Map;if(o.length>0){let v=o.map(I=>I.id),_=v.map((I,j)=>`@id${j}`).join(","),M=Object.fromEntries(v.map((I,j)=>[`id${j}`,I])),A=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 (${_}) ORDER BY decided_at ASC
|
|
7756
|
+
`).all(M);for(let I of A)s.has(I.event_id)||s.set(I.event_id,[]),s.get(I.event_id).push(I);let E=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 (${_})
|
|
7759
|
+
`).all(M);for(let I of E)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,d=new Map,p=new Map,u=new Map,f=[],y=e?.business?.projects??[],w=e?.business?.contactMap??[],T=ht(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Nn(v.source,_,w),A=On(v.source,_),E=v.project??Ze(_,v.subject,A),I=null,j=null;M?(I=M.client,j=M.project||`${M.client}/_chat`):E&&(I=De(E,y),j=E);let R=wi(v.source,v.intent||"",_),B=_e[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:B.label,color:B.color});let te="__system",z,D=_i(v.source,v.intent||"",_);if(D){te=D.id,z=D.kind;let H=M?.displayName||D.name;(!u.has(D.id)||M?.displayName)&&u.set(D.id,{id:D.id,name:H,avatar:F(H),kind:D.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(v.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let J=`${v.id}|${H.decided_by}`,q=i.get(J),V=H.decided_at,Kt=q?.resolved_at??null,dt=Kt===null,Yr=q?.duration_ms??(dt?n-V:0),Qr=dt?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",G,Ae;if(I)G=I,Ae=j;else{let ct=T.get(H.agent_id);ct?(G=ct,Ae=`${ct}/_${v.source}`):(G="unmapped",Ae=`unmapped/_${v.source}`)}l.has(G)||l.set(G,{id:G,name:G,color:Pn(G),projects:[]}),d.has(G)||d.set(G,new Set),d.get(G).add(Ae),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:G,projectId:Ae,channelId:R,initiatorId:te,initiatorKind:z,subject:Ei(v.subject),intent:v.intent||"",startedAt:V,resolvedAt:Kt,duration:Yr,active:dt,outcome:Qr,tokens:0,inputPreview:A,system:ki(H.agent_id,e)})}}let g=[...l.values()].map(v=>({...v,projects:[...d.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),S=[],c=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,E=A?v.roles?.[A]?.title:void 0;return typeof E=="string"&&E.trim()?E.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let E={id:M,name:A.name||M,tier:A.tier==="claude-code"?"lead":"worker",model:A.model||"",role:A.systemPrompt?A.systemPrompt.split(/[.\n]/)[0].slice(0,60):A.tier||"",title:_(M)};S.push(E),c.add(M)}}for(let v of f)c.has(v.agentId)||(S.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),c.add(v.agentId));S.sort((v,_)=>v.id.localeCompare(_.id));let m=[],h=new Set;for(let[v,_]of Object.entries(_e))m.push({id:v,label:_.label,color:_.color}),h.add(v);for(let v of p.values())h.has(v.id)||m.push(v);let x=[...u.values()];x.find(v=>v.id==="__system")||x.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:S,channels:m,initiators:x,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function Lt(t){let e=$t();if(!e)return null;try{return Dn(e.db,me,t)}finally{e.close()}}function Hn(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 u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let y=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:y})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=Si(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Pn(f.clientId),projects:[]}),f.projectId!==u.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 Si(t){if(t.clientId!=="unmapped")return t;let e=Ct(t.inputPreview);if(!e)return t;let a=me?.business?.projects??[];return{...t,projectId:e,clientId:De(e,a)}}async function tt(t){let e=me?.channels?.gitlab,a=await In(Mn(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 me=null;function Bn(t){me=t}async function zn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=$t();if(!n)return ce(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=qn(parseInt(r.searchParams.get("hours")||"6",10));ce(e,200,await tt(Dn(n.db,me,o)))}catch(r){ce(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Ti=5e3;async function jt(t,e,a,n=Lt){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=qn(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),
|
|
7764
|
-
`),e.write(`data: ${JSON.stringify(
|
|
7763
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await tt(p);if(s)break;u?(e.write(`event: snapshot
|
|
7764
|
+
`),e.write(`data: ${JSON.stringify(u)}
|
|
7765
7765
|
|
|
7766
7766
|
`)):e.write(`event: error
|
|
7767
7767
|
data: ${JSON.stringify({error:"ledger not available"})}
|
|
@@ -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 d=Date.now();for(;!s&&Date.now()-d<
|
|
7772
|
+
`)}let d=Date.now();for(;!s&&Date.now()-d<Ti;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function qn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ci(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Mt(process.cwd(),".agentx/task-history",t,n);if(!It(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Mt(process.cwd(),".agentx/task-history",t,o);return It(s)?Rn(s,e,a):null}return Rn(r,e,a)}function Rn(t,e,a){let n=null,r=1/0;for(let o of vi(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(bi(xi(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 Un(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 ce(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=$t();if(!l)return ce(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 ce(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 ce(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(d.raw_json)}catch{}let y=On(d.source,f),w=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,T=null,g=null;if(p.agent_id){let k=Ci(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(T=k.responseText);let v=k.transcript;Array.isArray(v)&&(g=v.length)}}let S=me?.business?.projects??[],c=me?.business?.contactMap??[],m=ht(me?.business??{}),h={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=Nn(d.source,f,c);if(x)h={client:x.client,project:x.project||`${x.client}/_chat`,via:`contactMap (channel=${x.channel??"*"}${x.username?` username=${x.username}`:""}${x.chatId?` chatId=${x.chatId}`:""})`};else if(d.project||Ze(f,d.subject,y)){let k=d.project||Ze(f,d.subject,y);h={client:De(k,S),project:k,via:d.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=m.get(p.agent_id);k&&(h={client:k,project:`${k}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}ce(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:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:w,response:T,transcriptLen:g,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:h})}catch(d){ce(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as $i,readFileSync as Li}from"fs";import{resolve as Wn}from"path";pt();function Fn(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=Ai.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:Mi,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 Ai=`
|
|
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
|
+
`,Mi=`
|
|
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 Gn(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fn({agentId:a,peers:n,localToken:r}))}async function Xn(t,e,a){try{let n=t.method==="GET"?void 0:await el(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){at(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>$e(i),"PATCH ":()=>ji(i,n),"PATCH capability":()=>Ni(i,n),"POST mcp":()=>Ri(i,n),"DELETE mcp":()=>Pi(i,n),"GET identity":()=>Oi(i),"GET identity/file":()=>Di(i,String(o.path||"")),"PUT identity/file":()=>Hi(i,n),"GET skills":()=>Bi(i),"POST skills":()=>zi(i,n),"DELETE skills":()=>qi(i,n),"GET skills/tree":()=>Ui(i,String(o.slug||"")),"GET skills/file":()=>Fi(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Wi(i,n),"GET skills/deps":()=>Gi(i,String(o.slug||"")),"POST skills/install":()=>Xi(i,n,t),"POST skills/deps":()=>Ki(i,n,t),"GET channels":()=>Ji(i),"GET activity":()=>Vi(i,t),"GET handovers":()=>Yi(i),"POST handovers":()=>Qi(i,n),"DELETE handovers":()=>Zi(n)}[d];if(!u){at(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();at(e,200,f)}catch(n){at(e,400,{error:n?.message||"agent op failed"})}}function Kn(){let t=Wn(process.cwd(),"agentx.json");return $i(t)?JSON.parse(Li(t,"utf-8")):null}function W(t){let e=Kn();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 $e(t){let{def:e,cfg:a}=W(t),n=e.workspace?ye(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 ji(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:$e(t)}}function Ri(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:$e(t)}}function Pi(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:$e(t)}}function Ni(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:$e(t)}}function Oi(t){let{def:e}=W(t);return ye(e.workspace)}function Di(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return ze(a.workspace,e)}function Hi(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return qe(n.workspace,a,String(e?.content??""))}function Bi(t){let{def:e}=W(t),a=ye(e.workspace);return{skills:a.skills,workspace:a.workspace}}function zi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ue(n.workspace,a,{title:e?.title,content:e?.content})}function qi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Fe(n.workspace,a)}function Ui(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=xa(a.workspace,e),r=We(a.workspace,e);return{slug:e,tree:n,deps:r}}function Fi(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return va(n.workspace,e,a)}function Wi(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=W(t);return ba(r.workspace,a,n,String(e?.content??""))}function Gi(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return We(a.workspace,e)}async function Xi(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=Jn(e?.worker),{def:o}=W(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 Vn(a,r,s,`install-${n}:${Date.now()}`)}async function Ki(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Jn(e?.worker),{def:o}=W(t),s=We(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=Wn(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 Vn(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Jn(t){if(t&&typeof t=="string")return t;let e=Y();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Vn(t,e,a,n){let r=Y(),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 Ji(t){let e=Kn(),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 Vi(t,e){try{let n=(Y().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 Rt(){return new Qt}function Yi(t){let e=Rt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Qi(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=Rt().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 Zi(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:Rt().remove(e,a,n)?"Released":"No active handover for that chat"}}function at(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function el(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 be={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 Yn=[{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 Pt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(be)};</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:`${be.brand} \xB7 ${be.subtitle}`,activeTab:"live",subtitle:be.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:tl,scripts:e+`<script>${al}</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 tl=`
|
|
9354
9354
|
/* --- Page frame --- */
|
|
9355
9355
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
9356
9356
|
|
|
@@ -9557,7 +9557,7 @@ loadAgent();
|
|
|
9557
9557
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
9558
9558
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
9559
9559
|
}
|
|
9560
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
9560
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,al=`
|
|
9561
9561
|
'use strict';
|
|
9562
9562
|
|
|
9563
9563
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -10128,7 +10128,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10128
10128
|
});
|
|
10129
10129
|
}
|
|
10130
10130
|
|
|
10131
|
-
`;var
|
|
10131
|
+
`;var Qn=`
|
|
10132
10132
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
10133
10133
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
10134
10134
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -10302,7 +10302,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10302
10302
|
.mx-summary{max-width:56vw}
|
|
10303
10303
|
}
|
|
10304
10304
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
10305
|
-
`;var
|
|
10305
|
+
`;var Zn=`<script>
|
|
10306
10306
|
window.MX=(function(){
|
|
10307
10307
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
10308
10308
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -10411,7 +10411,7 @@ window.MX=(function(){
|
|
|
10411
10411
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
10412
10412
|
setHealth:setHealth,get:get};
|
|
10413
10413
|
})();
|
|
10414
|
-
</script>`;var
|
|
10414
|
+
</script>`;var er=`<script>
|
|
10415
10415
|
window.MXD=(function(){
|
|
10416
10416
|
function el(id){return document.getElementById(id)}
|
|
10417
10417
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -10625,7 +10625,7 @@ window.MXD=(function(){
|
|
|
10625
10625
|
|
|
10626
10626
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
10627
10627
|
})();
|
|
10628
|
-
</script>`;var
|
|
10628
|
+
</script>`;var tr=`<script>
|
|
10629
10629
|
(function(){
|
|
10630
10630
|
var LANES=[
|
|
10631
10631
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -10941,7 +10941,7 @@ window.MXD=(function(){
|
|
|
10941
10941
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
10942
10942
|
load();
|
|
10943
10943
|
})();
|
|
10944
|
-
</script>`;var
|
|
10944
|
+
</script>`;var ar=`<script>
|
|
10945
10945
|
(function(){
|
|
10946
10946
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
10947
10947
|
var esc=MX.esc;
|
|
@@ -11119,7 +11119,7 @@ window.MXD=(function(){
|
|
|
11119
11119
|
}
|
|
11120
11120
|
load();setInterval(load,5000);
|
|
11121
11121
|
})();
|
|
11122
|
-
</script>`;var
|
|
11122
|
+
</script>`;var nr=`
|
|
11123
11123
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
11124
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}
|
|
11125
11125
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -11160,7 +11160,7 @@ window.MXD=(function(){
|
|
|
11160
11160
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
11161
11161
|
.mx-rt-name{max-width:100%}
|
|
11162
11162
|
}
|
|
11163
|
-
`,
|
|
11163
|
+
`,rr=`<script>
|
|
11164
11164
|
(function(){
|
|
11165
11165
|
var root=document.getElementById('mx-routines');
|
|
11166
11166
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -11287,17 +11287,92 @@ window.MXD=(function(){
|
|
|
11287
11287
|
syncBar();
|
|
11288
11288
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
11289
11289
|
})();
|
|
11290
|
-
</script>`;var
|
|
11290
|
+
</script>`;var or=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],sr=`<script>
|
|
11291
|
+
(function(){
|
|
11292
|
+
var root=document.getElementById('mx-feed');
|
|
11293
|
+
if(!root)return;
|
|
11294
|
+
var esc=MX.esc,filter='all',expanded=false,events=[],local='',SHOWN=8;
|
|
11295
|
+
var more=document.getElementById('mx-feed-more');
|
|
11296
|
+
try{var saved=localStorage.getItem('mx-feed-filter');if(saved)filter=saved}catch(e){}
|
|
11297
|
+
var chips=Array.prototype.slice.call(document.querySelectorAll('[data-feed-filter]'));
|
|
11298
|
+
function pressChips(){chips.forEach(function(c){c.setAttribute('aria-pressed',String(c.dataset.feedFilter===filter))})}
|
|
11299
|
+
chips.forEach(function(c){c.addEventListener('click',function(){
|
|
11300
|
+
filter=c.dataset.feedFilter;pressChips();render();
|
|
11301
|
+
try{localStorage.setItem('mx-feed-filter',filter)}catch(e){}
|
|
11302
|
+
})});
|
|
11303
|
+
pressChips();
|
|
11304
|
+
more.addEventListener('click',function(){expanded=!expanded;render()});
|
|
11305
|
+
|
|
11306
|
+
function initials(v){return String(v||'?').split(/[-_. ]+/).slice(0,2).map(function(x){return x.charAt(0)}).join('').toUpperCase()}
|
|
11307
|
+
function problem(e){
|
|
11308
|
+
return e.type==='feed:down'||e.type==='feed:gap'||e.type==='failed'||e.type==='timeout'
|
|
11309
|
+
||e.type==='lost'||(e.type==='task:completed'&&/^failed/.test(e.summary||''));
|
|
11310
|
+
}
|
|
11311
|
+
function label(e){
|
|
11312
|
+
if(e.kind==='announce')return 'Announcement';
|
|
11313
|
+
if(e.type==='feed:down')return 'Unreachable';
|
|
11314
|
+
if(e.type==='feed:up')return 'Back';
|
|
11315
|
+
if(e.type==='feed:gap')return 'Gap';
|
|
11316
|
+
if(e.type==='lost')return 'Lost';
|
|
11317
|
+
if(problem(e))return 'Failed';
|
|
11318
|
+
return e.kind;
|
|
11319
|
+
}
|
|
11320
|
+
function badge(e){
|
|
11321
|
+
var kind=problem(e)?'ax-badge--err':e.kind==='announce'?'ax-badge--warn':e.type==='feed:up'?'ax-badge--live':'ax-badge--ghost';
|
|
11322
|
+
return '<span class="ax-badge '+kind+'">'+esc(label(e))+'</span>';
|
|
11323
|
+
}
|
|
11324
|
+
function keep(e){
|
|
11325
|
+
if(filter==='peers')return e.node!==local;
|
|
11326
|
+
if(filter==='announce')return e.kind==='announce';
|
|
11327
|
+
if(filter==='problems')return problem(e);
|
|
11328
|
+
return true;
|
|
11329
|
+
}
|
|
11330
|
+
function render(){
|
|
11331
|
+
var list=events.filter(keep).slice().reverse();
|
|
11332
|
+
document.getElementById('mx-feed-count').textContent=MX.plural(list.length,'event');
|
|
11333
|
+
more.hidden=list.length<=SHOWN;
|
|
11334
|
+
more.textContent=expanded?'Show less':'Show all';
|
|
11335
|
+
if(!list.length){root.innerHTML='<div class="mx-empty">'+(events.length?'Nothing matches this filter.':'No events yet.')+'</div>';return}
|
|
11336
|
+
var shown=expanded?list:list.slice(0,SHOWN);
|
|
11337
|
+
root.innerHTML=shown.map(function(e,i){
|
|
11338
|
+
var who=e.agentId?'<code>'+esc(e.agentId)+'</code>':'';
|
|
11339
|
+
return '<button type="button" class="ax-row-card mx-item" data-feed="'+i+'">'
|
|
11340
|
+
+'<span class="ax-avatar '+(e.node===local?'ax-avatar--plain':'ax-avatar--blue')+'">'+esc(initials(e.node))+'</span>'
|
|
11341
|
+
+'<span class="ax-row-card__info"><span class="ax-name">'+esc(e.node)
|
|
11342
|
+
+(e.node===local?' <span class="ax-slug">this machine</span>':'')+'</span>'
|
|
11343
|
+
+'<span class="ax-sub">'+who+'<span class="mx-summary">'+esc(e.summary||e.type)+'</span></span></span>'
|
|
11344
|
+
+'<span class="ax-row-card__actions">'+badge(e)+'<span class="mx-node-meta">'+esc(MX.age(e.at))+'</span></span></button>';
|
|
11345
|
+
}).join('');
|
|
11346
|
+
root.querySelectorAll('[data-feed]').forEach(function(el){
|
|
11347
|
+
el.addEventListener('click',function(){
|
|
11348
|
+
var e=shown[Number(el.dataset.feed)];
|
|
11349
|
+
MX.open('Mesh event',label(e)+' on '+e.node,'<div class="mx-detail">'+MX.fields([
|
|
11350
|
+
['Machine',e.node],['Kind',e.kind],['Type',e.type],['Agent',e.agentId||'-'],
|
|
11351
|
+
['Time',new Date(e.at).toLocaleString()],['Record',e.ref||'-'],['Root',e.rootId]
|
|
11352
|
+
])+'<pre>'+esc(e.summary||'')+'</pre></div>');
|
|
11353
|
+
});
|
|
11354
|
+
});
|
|
11355
|
+
}
|
|
11356
|
+
function load(){
|
|
11357
|
+
MX.get('/api/mesh/feed?limit=50').then(function(r){
|
|
11358
|
+
events=r.events||[];local=r.node||'';render();
|
|
11359
|
+
}).catch(function(e){
|
|
11360
|
+
root.innerHTML='<div class="mx-empty">Mesh feed unavailable: '+esc(e.message)+'</div>';
|
|
11361
|
+
});
|
|
11362
|
+
}
|
|
11363
|
+
load();setInterval(load,5000);
|
|
11364
|
+
})();
|
|
11365
|
+
</script>`;var X={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function K(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var nl=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],rl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],ol=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function ir(t){let e=Ge({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Xe([{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">
|
|
11291
11366
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
11292
|
-
${
|
|
11367
|
+
${rl.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("")}
|
|
11293
11368
|
</div>
|
|
11294
11369
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
11295
|
-
${
|
|
11370
|
+
${ol.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
11296
11371
|
</div>
|
|
11297
11372
|
</div>
|
|
11298
11373
|
<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">
|
|
11299
11374
|
<section class="mx-section" aria-labelledby="mx-lanes-title">
|
|
11300
|
-
${
|
|
11375
|
+
${K(X.activity,"What ran","One lane per origin. Each lane is scaled to its own peak so a quiet channel stays readable next to a busy one. Select a column for the day behind it.","mx-lanes-title")}
|
|
11301
11376
|
<div id="mx-lanes"><div class="mx-empty">Loading activity...</div></div>
|
|
11302
11377
|
<div class="mx-axis" id="mx-axis"></div>
|
|
11303
11378
|
<p class="mx-note">Coloured bars are runs that finished; the red cap on a column is the failures inside that day. Select any column for what ran that day, down to a single conversation.</p>
|
|
@@ -11305,32 +11380,32 @@ window.MXD=(function(){
|
|
|
11305
11380
|
|
|
11306
11381
|
<div class="mx-two">
|
|
11307
11382
|
<section class="mx-section" aria-labelledby="mx-origins-title">
|
|
11308
|
-
${
|
|
11383
|
+
${K(X.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
|
|
11309
11384
|
<div class="mx-bars" id="mx-origins"><div class="mx-empty">Loading...</div></div>
|
|
11310
11385
|
</section>
|
|
11311
11386
|
<section class="mx-section" aria-labelledby="mx-causes-title">
|
|
11312
|
-
${
|
|
11387
|
+
${K(X.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
|
|
11313
11388
|
<div class="mx-bars" id="mx-causes"><div class="mx-empty">Loading...</div></div>
|
|
11314
11389
|
<p class="mx-note" id="mx-cause-note"></p>
|
|
11315
11390
|
</section>
|
|
11316
11391
|
</div>
|
|
11317
11392
|
|
|
11318
11393
|
<section class="mx-section" aria-labelledby="mx-scatter-title">
|
|
11319
|
-
${
|
|
11394
|
+
${K(X.effort,"Effort against output","Every recurring job, plotted as runtime spent against tokens produced on its successful runs. Both axes are logarithmic.","mx-scatter-title")}
|
|
11320
11395
|
<div class="mx-scatter" id="mx-scatter"><div class="mx-empty">Loading jobs...</div></div>
|
|
11321
11396
|
<div class="mx-legend" id="mx-scatter-legend"></div>
|
|
11322
11397
|
<p class="mx-note">Bubble size is the number of runs. Anything not healthy is labelled on the chart; select it for the attempt history behind the verdict.</p>
|
|
11323
11398
|
</section>
|
|
11324
11399
|
</div>`,r=`<div class="mx-view" id="mx-view-lifetime" role="tabpanel" aria-labelledby="mx-tab-lifetime" hidden>
|
|
11325
11400
|
<section class="mx-section" aria-labelledby="mx-threads-title">
|
|
11326
|
-
${
|
|
11401
|
+
${K(X.lifetime,"Thread lifetimes","A thread is one agent talking on one channel in one conversation. The bar is its real first-to-last span; each tick is a session cut. Select one for its turns, tokens and time.","mx-threads-title")}
|
|
11327
11402
|
<div class="mx-chips" id="mx-thread-chips"></div>
|
|
11328
11403
|
<div id="mx-threads"><div class="mx-empty">Loading threads...</div></div>
|
|
11329
11404
|
<p class="mx-note">Select a thread to walk its runs, then a run to see which tools it touched. Grey ticks are stale cuts, amber ticks are context-full cuts.</p>
|
|
11330
11405
|
</section>
|
|
11331
11406
|
|
|
11332
11407
|
<section class="mx-section" aria-labelledby="mx-rot-title">
|
|
11333
|
-
${
|
|
11408
|
+
${K(X.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
|
|
11334
11409
|
<div class="mx-bars" id="mx-rotations"><div class="mx-empty">Loading...</div></div>
|
|
11335
11410
|
<p class="mx-note" id="mx-rot-note"></p>
|
|
11336
11411
|
</section>
|
|
@@ -11338,31 +11413,39 @@ window.MXD=(function(){
|
|
|
11338
11413
|
<p id="mx-updated" class="mx-updated" aria-live="polite">Connecting to the fleet...</p>
|
|
11339
11414
|
|
|
11340
11415
|
<section class="mx-section" aria-labelledby="mx-auto-title">
|
|
11341
|
-
${
|
|
11416
|
+
${K(X.schedules,"Today's automations","Persisted attempts are authoritative. Select a schedule to inspect its latest result and runtime.","mx-auto-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-run-count">0 schedules</span><button class="ax-btn ax-btn--ghost mx-show-all" id="mx-show-all" type="button" hidden>Show all</button></div>')}
|
|
11342
11417
|
<div class="ax-stack" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
|
|
11343
11418
|
</section>
|
|
11344
11419
|
|
|
11345
11420
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
11346
|
-
${
|
|
11421
|
+
${K(X.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>')}
|
|
11347
11422
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
11348
|
-
${
|
|
11423
|
+
${nl.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11349
11424
|
</div>
|
|
11350
11425
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
11351
11426
|
</section>
|
|
11352
11427
|
|
|
11428
|
+
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
11429
|
+
${K(X.feed,"Mesh feed","The newest events from this machine and every machine it follows. Unreachable machines and announcements show here too. Select an event for its details.","mx-feed-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-feed-count">0 events</span><button class="ax-btn ax-btn--ghost" id="mx-feed-more" type="button" hidden>Show all</button></div>')}
|
|
11430
|
+
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
11431
|
+
${or.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11432
|
+
</div>
|
|
11433
|
+
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
11434
|
+
</section>
|
|
11435
|
+
|
|
11353
11436
|
<div class="mx-columns">
|
|
11354
11437
|
<section class="mx-section" aria-labelledby="mx-active-title">
|
|
11355
|
-
${
|
|
11438
|
+
${K(X.activity,"Activity provenance","Who initiated current work and where it is running.","mx-active-title",'<span class="ax-tab-count" id="mx-active-count">0 active</span>')}
|
|
11356
11439
|
<div class="ax-stack" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
|
|
11357
11440
|
</section>
|
|
11358
11441
|
<section class="mx-section" aria-labelledby="mx-nodes-title">
|
|
11359
|
-
${
|
|
11442
|
+
${K(X.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
|
|
11360
11443
|
<div class="ax-stack" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
|
|
11361
11444
|
</section>
|
|
11362
11445
|
</div>
|
|
11363
11446
|
|
|
11364
11447
|
<section class="mx-section" aria-labelledby="mx-agents-title">
|
|
11365
|
-
${
|
|
11448
|
+
${K(X.agents,"Agents and skills","Runtime, model, installed skills, and task totals by node.","mx-agents-title",'<span class="ax-tab-count" id="mx-agent-count">0 agents</span>')}
|
|
11366
11449
|
<div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
|
|
11367
11450
|
</section>
|
|
11368
11451
|
</div>`,s=`${e}<main class="mx-content">
|
|
@@ -11378,7 +11461,7 @@ window.MXD=(function(){
|
|
|
11378
11461
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
11379
11462
|
</header>
|
|
11380
11463
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
11381
|
-
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
11464
|
+
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Qn+nr,scripts:Zn+sl+er+tr+rr+ar+sr})}var sl=`<script>
|
|
11382
11465
|
(function(){
|
|
11383
11466
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
11384
11467
|
var range=document.getElementById('mx-range');
|
|
@@ -11406,7 +11489,7 @@ window.MXD=(function(){
|
|
|
11406
11489
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
11407
11490
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
11408
11491
|
})();
|
|
11409
|
-
</script>`;async function
|
|
11492
|
+
</script>`;async function lr(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 il(s,e.days)}function il(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,u=0,f=0,y=0,w=0;for(let{node:g,data:S}of t)if(S){a.runs+=S.totals.runs,a.errors+=S.totals.errors,a.hours+=S.totals.hours,a.agents+=S.totals.agents,a.threads+=S.totals.threads;for(let c of S.days){let m=n.get(c.day)||{day:c.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])m[h][0]+=c[h]?.[0]||0,m[h][1]+=c[h]?.[1]||0;n.set(c.day,m)}for(let c of S.origins){let m=r.get(c.channel)||{channel:c.channel,runs:0,errors:0,hours:0};m.runs+=c.runs,m.errors+=c.errors,m.hours+=c.hours,r.set(c.channel,m)}for(let c of S.causes){let m=o.get(c.cause)||{cause:c.cause,count:0,agents:[],example:""};m.count+=c.count;for(let h of c.agents)m.agents.includes(h)||m.agents.push(h);m.example||(m.example=c.example),o.set(c.cause,m)}for(let c of S.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=S.rotations.total,p+=S.rotations.tokenSum||0,u+=S.rotations.tokenSamples||0,f=Math.max(f,S.rotations.maxTokens),y+=S.retention.traces,w+=S.retention.tracesWithSteps;for(let c of S.jobs)i.push({...c,node:g.name,nodeUrl:g.url});for(let c of S.threads)l.push({...c,node:g.name,nodeUrl:g.url})}let T=t.filter(g=>g.data).map(g=>g.data.since).filter(g=>Number.isFinite(g));return{generatedAt:Date.now(),windowDays:e,since:T.length?Math.min(...T):Date.now()-e*864e5,nodes:t.map(g=>({name:g.node.name,url:g.node.url,ok:!!g.data,error:g.error,runs:g.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((g,S)=>g.day.localeCompare(S.day)),origins:[...r.values()].map(g=>({...g,hours:Math.round(g.hours*100)/100})).sort((g,S)=>S.runs-g.runs),causes:[...o.values()].sort((g,S)=>S.count-g.count),jobs:i.sort((g,S)=>S.hours-g.hours),threads:l.sort((g,S)=>S.lastAt-S.firstAt-(g.lastAt-g.firstAt)||S.runs-g.runs),rotations:{total:d,byReason:[...s.entries()].map(([g,S])=>({reason:g,count:S})).sort((g,S)=>S.count-g.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:y,tracesWithSteps:w}}}async function dr(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 cr(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 ll(s,e.day)}function ll(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 pr(t={}){let e=`
|
|
11410
11493
|
<select id="boardPicker" title="Switch board"></select>
|
|
11411
11494
|
<div class="search">
|
|
11412
11495
|
<span class="icon">\u2315</span>
|
|
@@ -11507,7 +11590,7 @@ window.MXD=(function(){
|
|
|
11507
11590
|
</footer>
|
|
11508
11591
|
</div>
|
|
11509
11592
|
</div>
|
|
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:
|
|
11593
|
+
<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:dl,scripts:`<script>${cl}</script>`,headExtras:`<script>
|
|
11511
11594
|
// The boards page has its own connection dot + wants body height:100%
|
|
11512
11595
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
11513
11596
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -11523,7 +11606,7 @@ window.MXD=(function(){
|
|
|
11523
11606
|
right.insertBefore(dot, right.firstChild);
|
|
11524
11607
|
}
|
|
11525
11608
|
});
|
|
11526
|
-
</script>`})}var
|
|
11609
|
+
</script>`})}var dl=`
|
|
11527
11610
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
11528
11611
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
11529
11612
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -11776,7 +11859,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
11776
11859
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
11777
11860
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
11778
11861
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
11779
|
-
`,
|
|
11862
|
+
`,cl=`
|
|
11780
11863
|
'use strict';
|
|
11781
11864
|
const state = {
|
|
11782
11865
|
boards: [], current: null, items: {},
|
|
@@ -12829,9 +12912,9 @@ function appendEvents(events) {
|
|
|
12829
12912
|
}
|
|
12830
12913
|
|
|
12831
12914
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
12832
|
-
`;function
|
|
12915
|
+
`;function ur(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
12833
12916
|
<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>
|
|
12834
|
-
${
|
|
12917
|
+
${Yn.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:`${be.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:pl})}var pl=`
|
|
12835
12918
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
12836
12919
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
12837
12920
|
.lead {
|
|
@@ -12861,7 +12944,7 @@ article.term .alias {
|
|
|
12861
12944
|
}
|
|
12862
12945
|
article.term p {
|
|
12863
12946
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
12864
|
-
}`;function
|
|
12947
|
+
}`;function mr(t={}){let e=`<div class="ax-wf__root">
|
|
12865
12948
|
<aside class="ax-wf__list">
|
|
12866
12949
|
<header>
|
|
12867
12950
|
<h2>Workflows</h2>
|
|
@@ -12938,7 +13021,7 @@ article.term p {
|
|
|
12938
13021
|
</aside>
|
|
12939
13022
|
</div>
|
|
12940
13023
|
|
|
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:
|
|
13024
|
+
<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:ul,scripts:`<script>${ue({workflowHealth:ra})}${ml}</script>`})}var ul=`
|
|
12942
13025
|
.ax-wf__root {
|
|
12943
13026
|
display: grid;
|
|
12944
13027
|
grid-template-columns: 340px 1fr;
|
|
@@ -13322,7 +13405,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13322
13405
|
font-size: 12px; z-index: 50;
|
|
13323
13406
|
}
|
|
13324
13407
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
13325
|
-
`,
|
|
13408
|
+
`,ml=`
|
|
13326
13409
|
(() => {
|
|
13327
13410
|
const $ = (sel) => document.querySelector(sel)
|
|
13328
13411
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -14111,7 +14194,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14111
14194
|
setInterval(refresh, 15000)
|
|
14112
14195
|
})
|
|
14113
14196
|
})();
|
|
14114
|
-
`;function
|
|
14197
|
+
`;function fr(t={}){let e=`<div class="ax-proc__root">
|
|
14115
14198
|
<header class="ax-proc__header">
|
|
14116
14199
|
<h1>Procedures</h1>
|
|
14117
14200
|
<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>
|
|
@@ -14155,7 +14238,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14155
14238
|
<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>
|
|
14156
14239
|
<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>
|
|
14157
14240
|
</section>
|
|
14158
|
-
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
14241
|
+
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:fl,scripts:`<script>${hl}</script>`})}var fl=`
|
|
14159
14242
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
14160
14243
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14161
14244
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -14181,7 +14264,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14181
14264
|
.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); }
|
|
14182
14265
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
14183
14266
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
14184
|
-
`,
|
|
14267
|
+
`,hl=`
|
|
14185
14268
|
(function(){
|
|
14186
14269
|
function $(sel){ return document.querySelector(sel) }
|
|
14187
14270
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -14281,7 +14364,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14281
14364
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
14282
14365
|
else bootAll()
|
|
14283
14366
|
})();
|
|
14284
|
-
`;function
|
|
14367
|
+
`;function hr(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
14285
14368
|
data-task-id="${P(t.taskId)}"
|
|
14286
14369
|
data-agent-id="${P(t.agentId)}"
|
|
14287
14370
|
data-node-url="${P(t.nodeUrl)}"
|
|
@@ -14324,7 +14407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14324
14407
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
14325
14408
|
</div>
|
|
14326
14409
|
</footer>
|
|
14327
|
-
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14410
|
+
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:gl,scripts:`<script>${xl}</script>`})}var gl=`
|
|
14328
14411
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
14329
14412
|
the sticky topbar. Breathe. */
|
|
14330
14413
|
.ax-task-page {
|
|
@@ -14466,7 +14549,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14466
14549
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
14467
14550
|
}
|
|
14468
14551
|
|
|
14469
|
-
`,
|
|
14552
|
+
`,xl=`
|
|
14470
14553
|
(function () {
|
|
14471
14554
|
var root = document.querySelector('.ax-task-page');
|
|
14472
14555
|
if (!root) return;
|
|
@@ -14851,7 +14934,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14851
14934
|
});
|
|
14852
14935
|
|
|
14853
14936
|
})();
|
|
14854
|
-
`;function
|
|
14937
|
+
`;function gr(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
14855
14938
|
data-agent-id="${P(t.agentId)}"
|
|
14856
14939
|
data-agent-name="${P(e)}"
|
|
14857
14940
|
data-node-url="${P(t.nodeUrl)}">
|
|
@@ -14880,7 +14963,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14880
14963
|
<div class="ax-history__list" id="hist-list">
|
|
14881
14964
|
<div class="ax-history__empty">loading\u2026</div>
|
|
14882
14965
|
</div>
|
|
14883
|
-
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14966
|
+
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vl,scripts:`<script>${bl}</script>`})}var vl=`
|
|
14884
14967
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
14885
14968
|
flush against the sticky topbar. */
|
|
14886
14969
|
.ax-history {
|
|
@@ -14932,7 +15015,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14932
15015
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
14933
15016
|
}
|
|
14934
15017
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
14935
|
-
`,
|
|
15018
|
+
`,bl=`
|
|
14936
15019
|
(function () {
|
|
14937
15020
|
var root = document.querySelector('.ax-history');
|
|
14938
15021
|
if (!root) return;
|
|
@@ -15032,11 +15115,24 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15032
15115
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
15033
15116
|
});
|
|
15034
15117
|
})();
|
|
15035
|
-
`;function
|
|
15118
|
+
`;function vr(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"])?L(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 Ee(t,e,l=>xr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:wl(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return L(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Ee(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return L(e,200,{ok:!0,emission:d})}):L(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"])?L(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Ee(t,e,l=>{try{let d=a.layouts.save(s,l);return L(e,200,{layout:d})}catch(d){return L(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ee(t,e,l=>{let d=mt.safeParse(l);if(!d.success)return L(e,200,{ok:!1,issues:d.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=ft(d.data).map(u=>({path:"",message:u}));return L(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?L(e,200,{workflow:l}):L(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 Ee(t,e,p=>xr(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),L(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return L(e,404,{error:"unknown workflows endpoint",path:n})}var yl=["mesh"];function xr(t,e,a,n){let r=mt.safeParse(a);if(!r.success)return L(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=ft(o);if(s.length>0)return L(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return L(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return L(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 yl)!(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,u=!!p||/yaml round-trip failed/.test(d);return L(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),L(t,200,{workflow:i})}function wl(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",u=a.runs.list({workflowId:d,limit:l});if(!p)return L(e,200,{runs:u});let f=u.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 L(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Ee(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?L(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?L(e,200,{ok:!0,runId:l,status:p}):L(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return kl(t,e,a,l);let d=a.runs.get(l);return d?L(e,200,{run:d}):L(e,404,{error:"run not found"})}return L(e,404,{error:"unknown runs endpoint"})}function kl(t,e,a,n){let r=a.runs.get(n);if(!r)return L(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)}
|
|
15036
15119
|
|
|
15037
|
-
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=
|
|
15120
|
+
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
|
|
15038
15121
|
|
|
15039
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let
|
|
15122
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==d&&(d=u.updatedAt,i(u))},2e3);return!0}function Ee(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){L(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{L(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{L(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>L(e,400,{error:"body read failed",message:r.message})),!0}function L(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{deflateSync as _l}from"zlib";var El=[41,121,255],Sl=[255,255,255],br=new Map;function Ot(t){let e=br.get(t);return e||(e=Cl(t,Tl(t)),br.set(t,e)),e}function Tl(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?Sl:El;a.set(d,o*e+1+s*3)}return a}function Cl(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]),Nt("IHDR",a),Nt("IDAT",_l(e)),Nt("IEND",Buffer.alloc(0))])}function Nt(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(Ml(n)),Buffer.concat([a,n,r])}var Al=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 Ml(t){let e=4294967295;for(let a of t)e=Al[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function nt(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:nt(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:nt(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:nt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function $l(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:nt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Ll=/^\/api\/app\/tasks\/(cancel|followup)$/;async function yr(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=jl(s.searchParams.get("timezone")),w=await o.snapshot({date:Rl(y),timezone:y});return a==="/api/app/activity"?re(e,200,{ts:w.ts,tasks:$l(w.nodes)}):re(e,200,{ts:w.ts,nodes:w.nodes.map(Il)})}if(n==="GET"&&a==="/api/app/approvals")return re(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Ll);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 je(t)}catch(y){return re(e,400,{error:y.message})}let p=Le(d.node);if(!p)return re(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let y=Le(d.taskId);if(!y)return re(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(y)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Le(d.message);if(!T)return re(e,400,{error:"message is required"});f=await o.nodePost(p,w,{message:T,sender:u})}}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=Le(d.cronId);if(!y||typeof d.enabled!="boolean")return re(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=Le(d.key),w=d.action;if(!y||w!=="yes"&&w!=="no"&&w!=="later")return re(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,y,w,u)}return re(e,f.status,f.body)}function Le(t){return typeof t=="string"?t.trim():""}function jl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Rl(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function je(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 re(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Pl=2048,wr=/^[A-Za-z0-9_-]{8,256}$/;async function kr(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 oe(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 oe(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return oe(e,404,{error:"not found"});if(!s||l)return oe(e,503,{error:l});let d;try{d=await je(t)}catch(y){return oe(e,400,{error:y.message})}let p=Nl(d.endpoint,o.allowedHosts);if(!p){let y="";try{y=new URL(String(d.endpoint)).hostname}catch{}return oe(e,400,{error:`not a known push service${y?`: ${y}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return oe(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=d.keys?.p256dh,f=d.keys?.auth;return typeof u!="string"||!wr.test(u)||typeof f!="string"||!wr.test(f)?oe(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?oe(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),oe(e,200,{ok:!0}))}function Nl(t,e){if(typeof t!="string"||t.length>Pl)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 oe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ol=50;function Dl(t){let e={channel:"app",chatId:t.chatId};return t.node==="local"?{path:"/task",body:{agent:t.agent,message:t.message,stream:!0,context:e}}:{path:"/mesh/task",body:{peer:t.node,agent:t.agent,message:t.message,stream:!0,context:e}}}async function _r(t,e,a,n){let{path:r,body:o}=Dl(e),s="",i=[],l=new Map,d=(p,u,f)=>{let{cleanText:y,ui:w}=p==="done"?sa(u):{cleanText:u,ui:void 0},T=Bl(w);return{status:p,text:y,tools:i,...T?{ui:T}:{},...f?{error:f}:{}}};try{let p=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let u=await p.json().then(f=>f?.error).catch(()=>"");return d("error",s,u||`AgentX answered HTTP ${p.status}.`)}for await(let u of zl(p.body)){n(u.event,u.data);let f=u.data??{};if(u.event==="text"&&typeof f.text=="string")s+=f.text;else if(u.event==="tool"&&f.status==="start"&&i.length<Ol){let y={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(y),f.id&&l.set(String(f.id),y)}else if(u.event==="tool"&&f.status==="result"&&f.error===!0&&l.has(String(f.id)))l.get(String(f.id)).error=!0;else{if(u.event==="done")return d("done",typeof f.content=="string"&&f.content?f.content:s);if(u.event==="error")return d("error",s,Hl(f.error))}}return a.aborted?d("stopped",s):d("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?d("stopped",s):d("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function Hl(t){let e=String(t||"The agent could not answer.");return e.startsWith("__queued__")?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function Bl(t){if(!t)return;let e=r=>/^https?:\/\//i.test(r)&&r.length<=2048,a={},n=(t.buttons??[]).filter(r=>e(r.url)).slice(0,8).map(r=>({label:r.label.slice(0,80),url:r.url}));return n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(r=>r.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}}),Object.keys(a).length?a:void 0}async function*zl(t){let e=t.getReader(),a=new TextDecoder,n="";try{for(;;){let{done:r,value:o}=await e.read();if(r)break;n+=a.decode(o,{stream:!0}).replace(/\r\n/g,`
|
|
15123
|
+
`);let s;for(;(s=n.indexOf(`
|
|
15124
|
+
|
|
15125
|
+
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
|
|
15126
|
+
`))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&d.push(p.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
|
|
15127
|
+
`))}}catch{}}}}finally{e.releaseLock()}}var rt=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];orphaned=!1;listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
|
|
15128
|
+
data: ${JSON.stringify(s)}
|
|
15129
|
+
|
|
15130
|
+
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
15131
|
+
|
|
15132
|
+
`)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};var Sr=8e3,ql=/^[A-Za-z0-9_.:-]{1,64}$/,Se=new Map;async function Tr(t,e,a,n,r,o){if(a!=="/api/app/agents"&&a!=="/api/app/chat"&&a!=="/api/app/chat/stop"&&a!=="/api/app/chat/attach"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;if(n==="GET"&&a==="/api/app/agents")return O(e,200,{nodes:await Cr(o)});let s=o.store();if(!s)return O(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return O(e,200,{conversations:s.list(r.id)});let i=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(i){let d=s.get(r.id,decodeURIComponent(i[1]));if(!d)return O(e,404,{error:"no such conversation"});let p=Se.get(d.id);return O(e,200,{...d,running:!!p,...p?{partial:{text:p.text,tools:p.tools}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=s.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=d&&Se.get(d.id);if(!d||!p)return O(e,404,{error:"nothing is running in this conversation"});Ar(e);let{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g}=d;return e.write(Dt("conversation",{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g})),e.write(Dt("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return O(e,404,{error:"not found"});let l;try{l=await je(t,64*1024)}catch(d){return O(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=s.get(r.id,String(l.conversationId??""));if(!d)return O(e,404,{error:"no such conversation"});let p=Se.get(d.id);return p?(p.ac.abort(),Ht(d,o,r.name),O(e,200,{stopped:!0})):await Ht(d,o,r.name)?O(e,200,{stopped:!0}):O(e,404,{error:"nothing is running in this conversation"})}return await Fl(e,l,r,s,o),!0}function Ul(t,e,a){let n=Te(e.url),r=new Set,o=[];for(let s of t){let i=Te(s.url),l=a.find(u=>Te(u.peerUrl)===i);l&&r.add(l.peer);let d=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Cr(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Ul(e.nodes,t.daemon,a)}async function Fl(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Sr){O(t,400,{error:`message must be 1\u2013${Sr} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){O(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!ql.test(T)){O(t,400,{error:"pick an agent"});return}let g=(await Cr(r)).find(c=>c.target===w);if(!g){O(t,400,{error:`unknown node "${w}"`});return}if(!g.online){O(t,409,{error:`${g.name} is offline`});return}let S=g.agents.find(c=>c.id===T);if(!S){O(t,400,{error:`no agent "${T}" on ${g.name}`});return}s=n.create(a.id,{node:w,nodeName:g.name,agent:T,agentName:S.name},o)}if(Se.has(s.id)){O(t,409,{error:"The agent is still answering in this conversation."});return}let i=new rt(r.orphanLimitMs??18e5);Se.set(s.id,i),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()});let{id:l,title:d,node:p,nodeName:u,agent:f,agentName:y}=s;Ar(t),t.write(Dt("conversation",{id:l,title:d,node:p,nodeName:u,agent:f,agentName:y})),i.attach(t);try{let w=await _r(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`},i.ac.signal,(T,g)=>i.broadcast(T,g));i.orphaned&&(w.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ht(s,r,a.name)),n.append(a.id,l,{role:"assistant",content:w.text,status:w.status,at:Date.now(),...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{},...w.tools.length?{tools:w.tools}:{}}),i.broadcast("final",{status:w.status,content:w.text,...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{}})}finally{Se.delete(l),i.finish()}}function Ar(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Dt(t,e){return`event: ${t}
|
|
15133
|
+
data: ${JSON.stringify(e)}
|
|
15134
|
+
|
|
15135
|
+
`}async function Ht(t,e,a){try{let n=Te(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Te(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Te(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Te(t){return t.replace(/\/+$/,"")}function O(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Mr=`
|
|
15040
15136
|
(function () {
|
|
15041
15137
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
15042
15138
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -15280,7 +15376,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15280
15376
|
setInterval(refresh, 15000);
|
|
15281
15377
|
refresh();
|
|
15282
15378
|
})();
|
|
15283
|
-
`;var
|
|
15379
|
+
`;var Ir=`
|
|
15284
15380
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
15285
15381
|
.fx-head h2 { margin: 4px 0 0; }
|
|
15286
15382
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -15337,7 +15433,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15337
15433
|
}
|
|
15338
15434
|
.fx-error:empty { display: none; }
|
|
15339
15435
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
15340
|
-
`;var
|
|
15436
|
+
`;var $r=`
|
|
15341
15437
|
(function () {
|
|
15342
15438
|
var panel = document.getElementById('panel-alerts');
|
|
15343
15439
|
if (!panel) return;
|
|
@@ -15499,7 +15595,539 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15499
15595
|
refresh();
|
|
15500
15596
|
loadRecent();
|
|
15501
15597
|
})();
|
|
15502
|
-
`;var
|
|
15598
|
+
`;var Lr=`
|
|
15599
|
+
(function () {
|
|
15600
|
+
var panel = document.getElementById('panel-chat');
|
|
15601
|
+
var V = window.AXChatView;
|
|
15602
|
+
if (!panel || !V) return;
|
|
15603
|
+
// The head (agent, History, New) and its two sheets stay pinned at the top
|
|
15604
|
+
// of a long conversation, as the composer stays at the bottom.
|
|
15605
|
+
panel.innerHTML = '<h2 class="cx-sr">Chat</h2><div class="cx"><div class="cx-top">' +
|
|
15606
|
+
'<div class="cx-head"><button type="button" id="cx-pick" class="cx-pick" aria-controls="cx-picker" aria-expanded="false">' +
|
|
15607
|
+
'<span class="cx-pick-label">Choose an agent</span><span class="cx-pick-sub">Tap to see the agents on your machines</span></button>' +
|
|
15608
|
+
'<button type="button" id="cx-history-btn" class="fx-btn" aria-controls="cx-history" aria-expanded="false">History</button>' +
|
|
15609
|
+
'<button type="button" id="cx-new" class="fx-btn">New</button></div>' +
|
|
15610
|
+
'<div id="cx-picker" class="cx-sheet" role="region" aria-label="Agents" hidden></div>' +
|
|
15611
|
+
'<div id="cx-history" class="cx-sheet" role="region" aria-label="Past conversations" hidden></div></div>' +
|
|
15612
|
+
'<p id="cx-empty" class="soon">Pick an agent, then ask it anything. Its answer appears here as it writes.</p>' +
|
|
15613
|
+
'<div id="cx-log" class="cx-log" role="log" aria-live="polite"></div>' +
|
|
15614
|
+
'<form id="cx-form" class="cx-composer"><label for="cx-input" class="cx-sr">Message</label>' +
|
|
15615
|
+
'<textarea id="cx-input" rows="1" placeholder="Message" enterkeyhint="send" autocomplete="off"></textarea>' +
|
|
15616
|
+
'<button type="button" id="cx-stop" class="fx-btn fx-danger" hidden>Stop</button>' +
|
|
15617
|
+
'<button type="submit" id="cx-send" class="cx-send">Send</button></form></div>';
|
|
15618
|
+
|
|
15619
|
+
function $(id) { return document.getElementById(id); }
|
|
15620
|
+
var log = $('cx-log'), empty = $('cx-empty'), form = $('cx-form'), input = $('cx-input'), stopBtn = $('cx-stop');
|
|
15621
|
+
var pickBtn = $('cx-pick'), picker = $('cx-picker'), hist = $('cx-history'), histBtn = $('cx-history-btn'), newBtn = $('cx-new');
|
|
15622
|
+
var state = { conv: null, target: null, busy: false, queue: [], stopWanted: false, view: 0 };
|
|
15623
|
+
var NOTES = { stopped: 'Stopped. What the agent wrote so far is kept.', error: 'The agent could not answer.',
|
|
15624
|
+
running: 'Still answering. The answer appears here when it is ready.',
|
|
15625
|
+
lost: 'Connection lost. The agent keeps answering; the answer appears here when the phone is back online.' };
|
|
15626
|
+
|
|
15627
|
+
function remember(k, v) { try { if (v == null) localStorage.removeItem(k); else localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} }
|
|
15628
|
+
function recall(k) { try { return JSON.parse(localStorage.getItem(k) || 'null'); } catch (e) { return null; } }
|
|
15629
|
+
function api(path, opts) {
|
|
15630
|
+
return fetch(path, Object.assign({ credentials: 'same-origin' }, opts || {})).then(function (r) {
|
|
15631
|
+
if (r.status === 401) { location.reload(); throw new Error('not paired'); }
|
|
15632
|
+
return r;
|
|
15633
|
+
});
|
|
15634
|
+
}
|
|
15635
|
+
function post(path, body, signal) {
|
|
15636
|
+
return api(path, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), signal: signal });
|
|
15637
|
+
}
|
|
15638
|
+
|
|
15639
|
+
// --- The log ---
|
|
15640
|
+
function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
|
|
15641
|
+
function clearLog() { log.innerHTML = ''; empty.hidden = false; }
|
|
15642
|
+
function bubble(cls) {
|
|
15643
|
+
var el = document.createElement('div');
|
|
15644
|
+
el.className = 'cx-msg ' + cls;
|
|
15645
|
+
log.appendChild(el);
|
|
15646
|
+
empty.hidden = true;
|
|
15647
|
+
return el;
|
|
15648
|
+
}
|
|
15649
|
+
function userMsg(text) { var el = bubble('cx-user'); el.textContent = text; return el; }
|
|
15650
|
+
function agentMsg() {
|
|
15651
|
+
var el = bubble('cx-agent');
|
|
15652
|
+
el.innerHTML = '<div class="md cx-typing">Thinking\u2026</div><div class="cx-ui"></div><p class="cx-note" hidden></p>';
|
|
15653
|
+
return el;
|
|
15654
|
+
}
|
|
15655
|
+
function setBody(el, text) { el.replaceChild(V.md(text), el.querySelector('.md')); }
|
|
15656
|
+
function setNote(el, text, bad) {
|
|
15657
|
+
var n = el.querySelector('.cx-note');
|
|
15658
|
+
n.hidden = !text; n.textContent = text || ''; n.className = 'cx-note' + (bad ? ' cx-bad' : '');
|
|
15659
|
+
}
|
|
15660
|
+
function renderUi(el, ui) { V.renderUi(el.querySelector('.cx-ui'), ui, send); }
|
|
15661
|
+
function renderConversation(conv) {
|
|
15662
|
+
clearLog();
|
|
15663
|
+
(conv.messages || []).forEach(function (m) {
|
|
15664
|
+
if (m.role === 'user') { userMsg(m.content); return; }
|
|
15665
|
+
var el = agentMsg();
|
|
15666
|
+
setBody(el, m.content || '');
|
|
15667
|
+
V.setTools(el, m.tools);
|
|
15668
|
+
renderUi(el, m.ui);
|
|
15669
|
+
if (m.status && m.status !== 'done') setNote(el, m.error || NOTES[m.status] || '', m.status === 'error');
|
|
15670
|
+
});
|
|
15671
|
+
var live = null;
|
|
15672
|
+
if (conv.running) {
|
|
15673
|
+
// What the agent has written so far; the live stream carries on from it.
|
|
15674
|
+
live = agentMsg();
|
|
15675
|
+
if (conv.partial && conv.partial.text) setBody(live, V.preview(conv.partial.text));
|
|
15676
|
+
V.setTools(live, conv.partial && conv.partial.tools);
|
|
15677
|
+
setNote(live, NOTES.running);
|
|
15678
|
+
}
|
|
15679
|
+
// Follow-ups typed while it answers stay below, waiting to be sent.
|
|
15680
|
+
state.queue.forEach(function (x) { log.appendChild(x.el); });
|
|
15681
|
+
scrollDown();
|
|
15682
|
+
return live;
|
|
15683
|
+
}
|
|
15684
|
+
|
|
15685
|
+
// --- Agent, conversation and the sheets ---
|
|
15686
|
+
function showTarget(t) {
|
|
15687
|
+
pickBtn.querySelector('.cx-pick-label').textContent = t ? (t.agentName || t.agent) : 'Choose an agent';
|
|
15688
|
+
pickBtn.querySelector('.cx-pick-sub').textContent = t ? 'on ' + t.nodeName : 'Tap to see the agents on your machines';
|
|
15689
|
+
}
|
|
15690
|
+
function useConversation(conv) {
|
|
15691
|
+
state.conv = conv;
|
|
15692
|
+
state.target = { node: conv.node, nodeName: conv.nodeName, agent: conv.agent, agentName: conv.agentName };
|
|
15693
|
+
showTarget(state.target);
|
|
15694
|
+
remember('ax-chat-conv', conv.id);
|
|
15695
|
+
remember('ax-chat-target', state.target);
|
|
15696
|
+
}
|
|
15697
|
+
function toggle(sheet, open) {
|
|
15698
|
+
[[picker, pickBtn], [hist, histBtn]].forEach(function (p) {
|
|
15699
|
+
var on = p[0] === sheet && open;
|
|
15700
|
+
p[0].hidden = !on; p[1].setAttribute('aria-expanded', on ? 'true' : 'false');
|
|
15701
|
+
});
|
|
15702
|
+
}
|
|
15703
|
+
function loadPicker() {
|
|
15704
|
+
picker.innerHTML = '<p class="cx-note">Looking for agents\u2026</p>';
|
|
15705
|
+
api('/api/app/agents').then(function (r) { return r.json(); }).then(function (data) {
|
|
15706
|
+
var nodes = picker._data = data.nodes || [];
|
|
15707
|
+
if (!nodes.length) { picker.innerHTML = '<p class="cx-note">No machines answered. Check that AgentX is running.</p>'; return; }
|
|
15708
|
+
picker.innerHTML = nodes.map(function (n, i) {
|
|
15709
|
+
var can = n.target && n.online;
|
|
15710
|
+
var why = !n.target ? 'Not linked to this computer\u2019s mesh' : n.online ? 'Online' : 'Offline';
|
|
15711
|
+
var rows = n.agents.length ? n.agents.map(function (a, j) {
|
|
15712
|
+
return '<li><button type="button" data-n="' + i + '" data-a="' + j + '"' + (can ? '' : ' disabled') + '>' +
|
|
15713
|
+
'<span>' + V.esc(a.name) + '<span class="cx-sub">' + V.esc(a.id) + '</span></span>' +
|
|
15714
|
+
'<span class="cx-state' + (a.busy ? ' cx-busy' : '') + '">' + (a.busy ? 'busy' + (a.running > 1 ? ' \xB7 ' + a.running : '') : 'idle') + '</span></button></li>';
|
|
15715
|
+
}).join('') : '<li class="cx-note">No agents</li>';
|
|
15716
|
+
return '<h3><span class="cx-dot' + (n.online ? ' cx-on' : '') + '"></span>' + V.esc(n.name) + ' <span class="cx-sub">' + V.esc(why) + '</span></h3><ul>' + rows + '</ul>';
|
|
15717
|
+
}).join('');
|
|
15718
|
+
}).catch(function () { picker.innerHTML = '<p class="cx-note cx-bad">Could not load agents. Check the connection and try again.</p>'; });
|
|
15719
|
+
}
|
|
15720
|
+
picker.addEventListener('click', function (ev) {
|
|
15721
|
+
var b = ev.target.closest('button[data-a]');
|
|
15722
|
+
if (!b || !picker._data) return;
|
|
15723
|
+
var n = picker._data[+b.getAttribute('data-n')], a = n.agents[+b.getAttribute('data-a')];
|
|
15724
|
+
state.target = { node: n.target, nodeName: n.name, agent: a.id, agentName: a.name };
|
|
15725
|
+
remember('ax-chat-target', state.target);
|
|
15726
|
+
startNew();
|
|
15727
|
+
toggle(picker, false);
|
|
15728
|
+
input.focus();
|
|
15729
|
+
});
|
|
15730
|
+
function startNew() {
|
|
15731
|
+
if (state.busy) return;
|
|
15732
|
+
state.view++;
|
|
15733
|
+
clearTimeout(pollTimer);
|
|
15734
|
+
state.conv = null;
|
|
15735
|
+
remember('ax-chat-conv', null);
|
|
15736
|
+
showTarget(state.target);
|
|
15737
|
+
clearLog();
|
|
15738
|
+
setBusy(false);
|
|
15739
|
+
}
|
|
15740
|
+
function when(ms) { var d = new Date(ms); return isNaN(d.getTime()) ? '' : d.toLocaleString(); }
|
|
15741
|
+
function loadHistory() {
|
|
15742
|
+
hist.innerHTML = '<p class="cx-note">Loading\u2026</p>';
|
|
15743
|
+
api('/api/app/conversations').then(function (r) { if (!r.ok) throw new Error(); return r.json(); })
|
|
15744
|
+
.then(function (d) { paintHistory(d.conversations || [], false); })
|
|
15745
|
+
.catch(function () { V.cacheAll().then(function (all) { paintHistory(all, true); }); });
|
|
15746
|
+
}
|
|
15747
|
+
function paintHistory(list, offline) {
|
|
15748
|
+
if (!list.length) { hist.innerHTML = '<p class="cx-note">' + (offline ? 'Offline, and nothing is saved on this phone yet.' : 'No conversations yet.') + '</p>'; return; }
|
|
15749
|
+
hist.innerHTML = (offline ? '<p class="cx-note">Offline: showing the conversations saved on this phone.</p>' : '') + '<ul>' + list.map(function (c) {
|
|
15750
|
+
return '<li><button type="button" data-c="' + V.esc(c.id) + '"><span>' + V.esc(c.title) +
|
|
15751
|
+
'<span class="cx-sub">' + V.esc((c.agentName || c.agent) + ' \xB7 ' + c.nodeName + ' \xB7 ' + when(c.updatedAt)) + '</span></span></button></li>';
|
|
15752
|
+
}).join('') + '</ul>';
|
|
15753
|
+
}
|
|
15754
|
+
hist.addEventListener('click', function (ev) {
|
|
15755
|
+
var b = ev.target.closest('button[data-c]');
|
|
15756
|
+
if (!b) return;
|
|
15757
|
+
toggle(hist, false);
|
|
15758
|
+
openConversation(b.getAttribute('data-c'));
|
|
15759
|
+
});
|
|
15760
|
+
var pollTimer = 0;
|
|
15761
|
+
function openConversation(id) {
|
|
15762
|
+
if (state.busy) return;
|
|
15763
|
+
clearTimeout(pollTimer);
|
|
15764
|
+
// The phone's copy first, so it opens at once and offline; the server's
|
|
15765
|
+
// copy replaces it when it arrives. A load that finishes after the user
|
|
15766
|
+
// moved on (New, another conversation, a send) is dropped.
|
|
15767
|
+
var mine = ++state.view, fromServer = false;
|
|
15768
|
+
V.cacheGet(id).then(function (c) { if (c && !fromServer && mine === state.view) { useConversation(c); renderConversation(c); } });
|
|
15769
|
+
return api('/api/app/conversations/' + encodeURIComponent(id)).then(function (r) {
|
|
15770
|
+
if (mine !== state.view) return null;
|
|
15771
|
+
if (r.status === 404) { fromServer = true; V.cacheDrop(id); startNew(); return null; }
|
|
15772
|
+
return r.ok ? r.json() : null;
|
|
15773
|
+
}).then(function (c) {
|
|
15774
|
+
if (!c || mine !== state.view) return;
|
|
15775
|
+
fromServer = true;
|
|
15776
|
+
useConversation(c);
|
|
15777
|
+
var live = renderConversation(c);
|
|
15778
|
+
if (!c.running) { V.cachePut(c); return; }
|
|
15779
|
+
// Still running: pick the live stream up where it is.
|
|
15780
|
+
follow(api('/api/app/chat/attach?conversationId=' + encodeURIComponent(id)), live, c.partial || {});
|
|
15781
|
+
}).catch(function () {});
|
|
15782
|
+
}
|
|
15783
|
+
|
|
15784
|
+
// --- Sending, streaming, stopping ---
|
|
15785
|
+
function setBusy(on) {
|
|
15786
|
+
state.busy = on;
|
|
15787
|
+
stopBtn.hidden = !on;
|
|
15788
|
+
newBtn.disabled = on;
|
|
15789
|
+
log.setAttribute('aria-busy', on ? 'true' : 'false');
|
|
15790
|
+
}
|
|
15791
|
+
function send(text) {
|
|
15792
|
+
text = String(text || '').trim();
|
|
15793
|
+
if (!text) return;
|
|
15794
|
+
if (state.busy) {
|
|
15795
|
+
// A follow-up while the agent answers: shown now, sent as the next
|
|
15796
|
+
// turn so its answer streams here as well.
|
|
15797
|
+
var q = userMsg(text);
|
|
15798
|
+
q.classList.add('cx-queued');
|
|
15799
|
+
state.queue.push({ text: text, el: q });
|
|
15800
|
+
input.value = ''; input.style.height = '';
|
|
15801
|
+
scrollDown();
|
|
15802
|
+
return;
|
|
15803
|
+
}
|
|
15804
|
+
if (!navigator.onLine) { flash('Offline. Messages can be sent once the phone is connected again.'); return; }
|
|
15805
|
+
if (!state.conv && !state.target) { toggle(picker, true); loadPicker(); return; }
|
|
15806
|
+
var body = state.conv
|
|
15807
|
+
? { conversationId: state.conv.id, message: text }
|
|
15808
|
+
: { node: state.target.node, agent: state.target.agent, message: text };
|
|
15809
|
+
state.stopWanted = false;
|
|
15810
|
+
userMsg(text);
|
|
15811
|
+
input.value = ''; input.style.height = '';
|
|
15812
|
+
follow(post('/api/app/chat', body), agentMsg(), null);
|
|
15813
|
+
}
|
|
15814
|
+
// Streams one turn into the bubble el, from a send or from attaching
|
|
15815
|
+
// to a turn that is still running. The phone losing its connection does
|
|
15816
|
+
// not stop the agent: the answer is saved and shown when the phone is back.
|
|
15817
|
+
function follow(request, el, partial) {
|
|
15818
|
+
clearTimeout(pollTimer);
|
|
15819
|
+
state.view++;
|
|
15820
|
+
var raw = (partial && partial.text) || '', tools = ((partial && partial.tools) || []).slice(), ended = false, frame = 0;
|
|
15821
|
+
function paint() { frame = 0; if (!ended && raw) { setBody(el, V.preview(raw)); scrollDown(); } }
|
|
15822
|
+
function finish(content, note, bad, ui) {
|
|
15823
|
+
ended = true;
|
|
15824
|
+
setBody(el, content || '');
|
|
15825
|
+
renderUi(el, ui);
|
|
15826
|
+
setNote(el, note, bad);
|
|
15827
|
+
scrollDown();
|
|
15828
|
+
}
|
|
15829
|
+
setBusy(true);
|
|
15830
|
+
scrollDown();
|
|
15831
|
+
return request.then(function (r) {
|
|
15832
|
+
// Attaching just after the turn ended: reload the saved answer.
|
|
15833
|
+
if (r.status === 404 && partial) { ended = true; return; }
|
|
15834
|
+
if (!r.ok) return r.json().catch(function () { return {}; }).then(function (j) { finish(raw, j.error || ('Failed (HTTP ' + r.status + ')'), true); });
|
|
15835
|
+
return V.readStream(r.body, function (ev, d) {
|
|
15836
|
+
if (ev === 'conversation') { useConversation(d); if (state.stopWanted) { state.stopWanted = false; stop(); } }
|
|
15837
|
+
else if (ev === 'resume') { raw = d.text || ''; tools = (d.tools || []).slice(); V.setTools(el, tools); setNote(el, ''); paint(); }
|
|
15838
|
+
else if (ev === 'text' && typeof d.text === 'string') { raw += d.text; if (!frame) frame = requestAnimationFrame(paint); }
|
|
15839
|
+
else if (ev === 'tool' && d.status === 'start') { tools.push({ id: d.id, name: d.name, arg: d.arg }); V.setTools(el, tools); }
|
|
15840
|
+
else if (ev === 'tool' && d.error) { tools.forEach(function (t) { if (t.id === d.id) t.error = true; }); V.setTools(el, tools); }
|
|
15841
|
+
else if (ev === 'final') finish(d.content, d.status === 'done' ? '' : (d.error || NOTES[d.status]), d.status === 'error', d.ui);
|
|
15842
|
+
});
|
|
15843
|
+
}).catch(function () {}).then(function () {
|
|
15844
|
+
setBusy(false);
|
|
15845
|
+
if (!ended) {
|
|
15846
|
+
// The stream broke before the answer: the agent carries on.
|
|
15847
|
+
setNote(el, state.conv ? NOTES.lost : 'Could not reach AgentX. Check the connection and try again.', !state.conv);
|
|
15848
|
+
if (state.conv) { var id = state.conv.id; pollTimer = setTimeout(function () { if (state.conv && state.conv.id === id) openConversation(id); }, 5000); }
|
|
15849
|
+
return;
|
|
15850
|
+
}
|
|
15851
|
+
if (state.queue.length) {
|
|
15852
|
+
var next = state.queue.splice(0);
|
|
15853
|
+
next.forEach(function (x) { x.el.remove(); });
|
|
15854
|
+
send(next.map(function (x) { return x.text; }).join(V.NL + V.NL));
|
|
15855
|
+
} else if (state.conv) openConversation(state.conv.id);
|
|
15856
|
+
});
|
|
15857
|
+
}
|
|
15858
|
+
function stop() {
|
|
15859
|
+
// Only Stop cancels. Before the conversation exists, wait for its id.
|
|
15860
|
+
if (!state.conv) { state.stopWanted = true; return; }
|
|
15861
|
+
post('/api/app/chat/stop', { conversationId: state.conv.id }).catch(function () {});
|
|
15862
|
+
}
|
|
15863
|
+
function flash(text) {
|
|
15864
|
+
var el = bubble('cx-agent');
|
|
15865
|
+
el.innerHTML = '<p class="cx-note cx-bad"></p>';
|
|
15866
|
+
el.firstChild.textContent = text;
|
|
15867
|
+
scrollDown();
|
|
15868
|
+
}
|
|
15869
|
+
|
|
15870
|
+
form.addEventListener('submit', function (e) { e.preventDefault(); send(input.value); });
|
|
15871
|
+
input.addEventListener('keydown', function (e) {
|
|
15872
|
+
if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); send(input.value); }
|
|
15873
|
+
});
|
|
15874
|
+
input.addEventListener('input', function () { input.style.height = ''; input.style.height = Math.min(input.scrollHeight, 240) + 'px'; });
|
|
15875
|
+
stopBtn.addEventListener('click', stop);
|
|
15876
|
+
pickBtn.addEventListener('click', function () { var open = picker.hidden; toggle(picker, open); if (open) loadPicker(); });
|
|
15877
|
+
histBtn.addEventListener('click', function () { var open = hist.hidden; toggle(hist, open); if (open) loadHistory(); });
|
|
15878
|
+
newBtn.addEventListener('click', function () { startNew(); input.focus(); });
|
|
15879
|
+
|
|
15880
|
+
window.addEventListener('online', function () { if (state.conv && !state.busy) openConversation(state.conv.id); });
|
|
15881
|
+
state.target = recall('ax-chat-target');
|
|
15882
|
+
showTarget(state.target);
|
|
15883
|
+
var last = recall('ax-chat-conv');
|
|
15884
|
+
if (last) openConversation(last);
|
|
15885
|
+
})();
|
|
15886
|
+
`;var jr=`
|
|
15887
|
+
window.AXChatView = (function () {
|
|
15888
|
+
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
15889
|
+
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
15890
|
+
// JSON never flashes; the finished reply arrives with it parsed.
|
|
15891
|
+
var PREVIEW_CUT = new RegExp('(^|' + NL + ')[ ' + TAB + ']*' + FENCE + '[ ' + TAB + ']*agentx:ui', 'i');
|
|
15892
|
+
var KEEP = 100;
|
|
15893
|
+
|
|
15894
|
+
function esc(v) {
|
|
15895
|
+
return String(v == null ? '' : v).replace(/[&<>"']/g, function (c) {
|
|
15896
|
+
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
|
15897
|
+
});
|
|
15898
|
+
}
|
|
15899
|
+
function httpUrl(u) {
|
|
15900
|
+
try { var x = new URL(String(u || ''), location.href); return x.protocol === 'https:' || x.protocol === 'http:' ? x.href : ''; } catch (e) { return ''; }
|
|
15901
|
+
}
|
|
15902
|
+
function preview(text) { var m = PREVIEW_CUT.exec(text); return m ? text.slice(0, m.index) : text; }
|
|
15903
|
+
|
|
15904
|
+
function md(text) {
|
|
15905
|
+
var d = document.createElement('div');
|
|
15906
|
+
d.className = 'md';
|
|
15907
|
+
try { d.innerHTML = markdownToHtml(String(text || '')); } catch (e) { d.textContent = text; }
|
|
15908
|
+
Array.prototype.slice.call(d.querySelectorAll('a')).forEach(function (a) {
|
|
15909
|
+
var h = /^https?:/i.test(a.getAttribute('href') || '') ? httpUrl(a.getAttribute('href')) : '';
|
|
15910
|
+
if (h) { a.href = h; a.target = '_blank'; a.rel = 'noopener noreferrer'; }
|
|
15911
|
+
else a.replaceWith(document.createTextNode(a.textContent));
|
|
15912
|
+
});
|
|
15913
|
+
return d;
|
|
15914
|
+
}
|
|
15915
|
+
|
|
15916
|
+
function setTools(el, tools) {
|
|
15917
|
+
if (!tools || !tools.length) return;
|
|
15918
|
+
var box = el.querySelector('.cx-tools');
|
|
15919
|
+
if (!box) {
|
|
15920
|
+
box = document.createElement('details');
|
|
15921
|
+
box.className = 'cx-tools';
|
|
15922
|
+
box.innerHTML = '<summary></summary><ul></ul>';
|
|
15923
|
+
el.insertBefore(box, el.firstChild);
|
|
15924
|
+
}
|
|
15925
|
+
var last = tools[tools.length - 1], bad = tools.filter(function (t) { return t.error; }).length;
|
|
15926
|
+
box.querySelector('summary').textContent = tools.length + (tools.length === 1 ? ' tool' : ' tools') +
|
|
15927
|
+
' \xB7 ' + last.name + (last.arg ? ' (' + last.arg + ')' : '') + (bad ? ' \xB7 ' + bad + ' failed' : '');
|
|
15928
|
+
box.querySelector('ul').innerHTML = tools.map(function (t) {
|
|
15929
|
+
return '<li' + (t.error ? ' class="cx-bad"' : '') + '>' + esc(t.name) + (t.arg ? ' \xB7 ' + esc(t.arg) : '') + '</li>';
|
|
15930
|
+
}).join('');
|
|
15931
|
+
}
|
|
15932
|
+
|
|
15933
|
+
function link(href, label) {
|
|
15934
|
+
var a = document.createElement('a');
|
|
15935
|
+
a.className = 'cx-ui-btn'; a.href = href; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.textContent = label;
|
|
15936
|
+
return a;
|
|
15937
|
+
}
|
|
15938
|
+
function renderUi(box, ui, send) {
|
|
15939
|
+
box.innerHTML = '';
|
|
15940
|
+
if (!ui) return;
|
|
15941
|
+
var m = ui.media, u = m && httpUrl(m.url);
|
|
15942
|
+
if (u) {
|
|
15943
|
+
var node;
|
|
15944
|
+
if (m.type === 'image') { node = document.createElement('img'); node.loading = 'lazy'; node.alt = m.caption || 'Picture from the agent'; node.referrerPolicy = 'no-referrer'; node.src = u; }
|
|
15945
|
+
else if (m.type === 'video' || m.type === 'audio') { node = document.createElement(m.type); node.controls = true; node.preload = 'metadata'; node.src = u; }
|
|
15946
|
+
else node = link(u, m.caption || 'Open document');
|
|
15947
|
+
box.appendChild(node);
|
|
15948
|
+
if (m.caption && node.tagName !== 'A') { var c = document.createElement('p'); c.className = 'cx-note'; c.textContent = m.caption; box.appendChild(c); }
|
|
15949
|
+
}
|
|
15950
|
+
var btns = (ui.buttons || []).filter(function (b) { return httpUrl(b.url); });
|
|
15951
|
+
if (btns.length) {
|
|
15952
|
+
var row = document.createElement('div');
|
|
15953
|
+
row.className = 'cx-ui-row';
|
|
15954
|
+
btns.forEach(function (b) { row.appendChild(link(httpUrl(b.url), b.label)); });
|
|
15955
|
+
box.appendChild(row);
|
|
15956
|
+
}
|
|
15957
|
+
if (ui.poll && ui.poll.options) {
|
|
15958
|
+
// A poll answer is simply the next message in the conversation.
|
|
15959
|
+
var fs = document.createElement('fieldset'), lg = document.createElement('legend'), opts = document.createElement('div');
|
|
15960
|
+
lg.textContent = ui.poll.question; fs.appendChild(lg);
|
|
15961
|
+
opts.className = 'cx-ui-row'; fs.appendChild(opts);
|
|
15962
|
+
ui.poll.options.forEach(function (o) {
|
|
15963
|
+
if (ui.poll.multiple) {
|
|
15964
|
+
var l = document.createElement('label'), cb = document.createElement('input');
|
|
15965
|
+
cb.type = 'checkbox'; cb.value = o; l.appendChild(cb); l.appendChild(document.createTextNode(o)); opts.appendChild(l);
|
|
15966
|
+
} else {
|
|
15967
|
+
var b = document.createElement('button');
|
|
15968
|
+
b.type = 'button'; b.className = 'cx-ui-btn'; b.textContent = o;
|
|
15969
|
+
b.addEventListener('click', function () { send(o); });
|
|
15970
|
+
opts.appendChild(b);
|
|
15971
|
+
}
|
|
15972
|
+
});
|
|
15973
|
+
if (ui.poll.multiple) {
|
|
15974
|
+
var go = document.createElement('button');
|
|
15975
|
+
go.type = 'button'; go.className = 'cx-ui-btn'; go.textContent = 'Send answer';
|
|
15976
|
+
go.addEventListener('click', function () {
|
|
15977
|
+
var picked = Array.prototype.slice.call(fs.querySelectorAll('input:checked')).map(function (i) { return i.value; });
|
|
15978
|
+
if (picked.length) send(picked.join(', '));
|
|
15979
|
+
});
|
|
15980
|
+
fs.appendChild(go);
|
|
15981
|
+
}
|
|
15982
|
+
box.appendChild(fs);
|
|
15983
|
+
}
|
|
15984
|
+
}
|
|
15985
|
+
|
|
15986
|
+
// Reads the agentx SSE wire from a fetch body: event: <kind>, data: <json>.
|
|
15987
|
+
function readStream(body, onEvent) {
|
|
15988
|
+
var reader = body.getReader(), dec = new TextDecoder(), buf = '';
|
|
15989
|
+
function pump() {
|
|
15990
|
+
return reader.read().then(function (r) {
|
|
15991
|
+
if (r.done) return;
|
|
15992
|
+
buf += dec.decode(r.value, { stream: true });
|
|
15993
|
+
var i;
|
|
15994
|
+
while ((i = buf.indexOf(NL + NL)) >= 0) {
|
|
15995
|
+
var rec = buf.slice(0, i), ev = 'message', data = '';
|
|
15996
|
+
buf = buf.slice(i + 2);
|
|
15997
|
+
rec.split(NL).forEach(function (line) {
|
|
15998
|
+
if (line.indexOf('event:') === 0) ev = line.slice(6).trim();
|
|
15999
|
+
else if (line.indexOf('data:') === 0) data += line.slice(5).trim();
|
|
16000
|
+
});
|
|
16001
|
+
if (data) { try { onEvent(ev, JSON.parse(data)); } catch (e) {} }
|
|
16002
|
+
}
|
|
16003
|
+
return pump();
|
|
16004
|
+
});
|
|
16005
|
+
}
|
|
16006
|
+
return pump();
|
|
16007
|
+
}
|
|
16008
|
+
|
|
16009
|
+
// --- IndexedDB: whole conversations keyed by id, newest KEEP kept ---
|
|
16010
|
+
var dbp = null;
|
|
16011
|
+
function db() {
|
|
16012
|
+
if (!window.indexedDB) return Promise.reject(new Error('no indexedDB'));
|
|
16013
|
+
if (!dbp) dbp = new Promise(function (ok, no) {
|
|
16014
|
+
var r = indexedDB.open('agentx-app-chat', 1);
|
|
16015
|
+
r.onupgradeneeded = function () { r.result.createObjectStore('conversations', { keyPath: 'id' }); };
|
|
16016
|
+
r.onsuccess = function () { ok(r.result); };
|
|
16017
|
+
r.onerror = function () { no(r.error); };
|
|
16018
|
+
});
|
|
16019
|
+
return dbp;
|
|
16020
|
+
}
|
|
16021
|
+
function idb(mode, fn) {
|
|
16022
|
+
return db().then(function (d) {
|
|
16023
|
+
return new Promise(function (ok) {
|
|
16024
|
+
var tx = d.transaction('conversations', mode), req = fn(tx.objectStore('conversations'));
|
|
16025
|
+
tx.oncomplete = function () { ok(req && req.result); };
|
|
16026
|
+
tx.onerror = tx.onabort = function () { ok(null); };
|
|
16027
|
+
});
|
|
16028
|
+
}).catch(function () { return null; });
|
|
16029
|
+
}
|
|
16030
|
+
function cacheAll() {
|
|
16031
|
+
return idb('readonly', function (s) { return s.getAll(); }).then(function (a) {
|
|
16032
|
+
return (a || []).sort(function (x, y) { return y.updatedAt - x.updatedAt; });
|
|
16033
|
+
});
|
|
16034
|
+
}
|
|
16035
|
+
function cachePut(conv) {
|
|
16036
|
+
return idb('readwrite', function (s) { s.put(conv); }).then(cacheAll).then(function (all) {
|
|
16037
|
+
var old = all.slice(KEEP);
|
|
16038
|
+
if (old.length) return idb('readwrite', function (s) { old.forEach(function (c) { s.delete(c.id); }); });
|
|
16039
|
+
});
|
|
16040
|
+
}
|
|
16041
|
+
function cacheGet(id) { return idb('readonly', function (s) { return s.get(id); }); }
|
|
16042
|
+
function cacheDrop(id) { return idb('readwrite', function (s) { s.delete(id); }); }
|
|
16043
|
+
|
|
16044
|
+
return { NL: NL, esc: esc, httpUrl: httpUrl, md: md, preview: preview, setTools: setTools, renderUi: renderUi, readStream: readStream,
|
|
16045
|
+
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
16046
|
+
})();
|
|
16047
|
+
`;var Rr=`
|
|
16048
|
+
body { height: 100dvh; }
|
|
16049
|
+
main { min-height: 0; }
|
|
16050
|
+
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
16051
|
+
.cx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
16052
|
+
.cx { display: flex; flex-direction: column; flex: 1; gap: 10px; }
|
|
16053
|
+
.cx-top {
|
|
16054
|
+
position: sticky; top: -16px; z-index: 1; display: grid; gap: 8px;
|
|
16055
|
+
margin: -16px 0 0; padding: 16px 0 8px; background: var(--ax-bg);
|
|
16056
|
+
}
|
|
16057
|
+
.cx-head { display: flex; gap: 8px; align-items: stretch; }
|
|
16058
|
+
.cx-head .fx-btn { border-radius: var(--ax-radius); min-height: 48px; }
|
|
16059
|
+
.cx-pick {
|
|
16060
|
+
flex: 1; min-width: 0; min-height: 48px; text-align: left; cursor: pointer;
|
|
16061
|
+
display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 6px 12px;
|
|
16062
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius);
|
|
16063
|
+
background: var(--ax-surface); color: var(--ax-text); font: inherit;
|
|
16064
|
+
}
|
|
16065
|
+
.cx-pick-label { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
16066
|
+
.cx-pick-sub { font-size: var(--ax-fs-xs); color: var(--ax-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
16067
|
+
.cx-sheet {
|
|
16068
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius);
|
|
16069
|
+
background: var(--ax-surface); padding: 4px 12px 12px; max-height: 60vh; overflow-y: auto;
|
|
16070
|
+
}
|
|
16071
|
+
.cx-sheet h3 { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); margin: 12px 0 6px; }
|
|
16072
|
+
.cx-sheet ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
|
|
16073
|
+
.cx-sheet li button {
|
|
16074
|
+
width: 100%; min-height: 48px; display: flex; justify-content: space-between; align-items: center; gap: 8px;
|
|
16075
|
+
padding: 8px 12px; text-align: left; cursor: pointer; font: inherit;
|
|
16076
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm);
|
|
16077
|
+
background: var(--ax-surface-2); color: var(--ax-text);
|
|
16078
|
+
}
|
|
16079
|
+
.cx-sheet li button:disabled { opacity: 0.55; cursor: not-allowed; }
|
|
16080
|
+
.cx-sub { display: block; font-size: var(--ax-fs-xs); color: var(--ax-text-2); font-weight: 400; }
|
|
16081
|
+
.cx-sheet h3 .cx-sub { display: inline; }
|
|
16082
|
+
.cx-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ax-muted); flex: none; }
|
|
16083
|
+
.cx-dot.cx-on { background: var(--ax-green); }
|
|
16084
|
+
.cx-state { font-size: var(--ax-fs-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--ax-radius-pill); background: var(--ax-surface-3); color: var(--ax-text-2); white-space: nowrap; }
|
|
16085
|
+
.cx-state.cx-busy { background: var(--ax-amber-t); color: var(--ax-amber-ink); }
|
|
16086
|
+
.cx-log { display: flex; flex-direction: column; gap: 10px; flex: 1; }
|
|
16087
|
+
.cx-msg { max-width: 92%; padding: 10px 12px; border-radius: var(--ax-radius); line-height: 1.5; overflow-wrap: anywhere; }
|
|
16088
|
+
.cx-user { align-self: flex-end; background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); border: var(--ax-border-w) solid color-mix(in oklch, var(--ax-accent) 45%, var(--ax-border)); white-space: pre-wrap; }
|
|
16089
|
+
.cx-queued { opacity: 0.7; }
|
|
16090
|
+
.cx-queued::after { content: "Sent when the agent finishes"; display: block; font-size: var(--ax-fs-xs); color: var(--ax-text-2); margin-top: 4px; }
|
|
16091
|
+
.cx-agent { align-self: flex-start; background: var(--ax-surface); border: var(--ax-border-w) solid var(--ax-border); }
|
|
16092
|
+
.cx-msg .md > :first-child { margin-top: 0; }
|
|
16093
|
+
.cx-msg .md > :last-child { margin-bottom: 0; }
|
|
16094
|
+
.cx-msg .md pre { overflow-x: auto; background: var(--ax-surface-3); padding: 8px; border-radius: var(--ax-radius-sm); }
|
|
16095
|
+
.cx-msg .md table { display: block; overflow-x: auto; border-collapse: collapse; }
|
|
16096
|
+
.cx-msg .md th, .cx-msg .md td { border: 1px solid var(--ax-border); padding: 4px 8px; }
|
|
16097
|
+
.cx-msg .md a { color: var(--ax-accent); }
|
|
16098
|
+
.cx-typing { color: var(--ax-text-2); }
|
|
16099
|
+
.cx-tools { font-size: var(--ax-fs-xs); color: var(--ax-text-2); margin: 0 0 6px; }
|
|
16100
|
+
.cx-tools summary { min-height: 32px; font-weight: 600; }
|
|
16101
|
+
.cx-tools ul { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }
|
|
16102
|
+
.cx-tools li { font-family: var(--ax-mono); background: var(--ax-surface-3); border-radius: var(--ax-radius-pill); padding: 2px 8px; }
|
|
16103
|
+
.cx-tools li.cx-bad { background: var(--ax-red-t); color: var(--ax-red-ink); }
|
|
16104
|
+
.cx-note { margin: 6px 0 0; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
16105
|
+
.cx-bad { color: var(--ax-red-ink); }
|
|
16106
|
+
.cx-ui { display: grid; gap: 8px; margin-top: 8px; }
|
|
16107
|
+
.cx-ui:empty { display: none; }
|
|
16108
|
+
.cx-ui img, .cx-ui video { max-width: 100%; border-radius: var(--ax-radius-sm); }
|
|
16109
|
+
.cx-ui audio { width: 100%; }
|
|
16110
|
+
.cx-ui-row { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
16111
|
+
.cx-ui-btn {
|
|
16112
|
+
display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px; cursor: pointer; font: inherit; font-weight: 600;
|
|
16113
|
+
border: var(--ax-border-w) solid color-mix(in oklch, var(--ax-accent) 50%, var(--ax-border)); border-radius: var(--ax-radius-pill);
|
|
16114
|
+
background: color-mix(in oklch, var(--ax-accent) 12%, var(--ax-surface)); color: var(--ax-accent); text-decoration: none;
|
|
16115
|
+
}
|
|
16116
|
+
.cx-ui fieldset { border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm); margin: 0; padding: 8px 10px; display: grid; gap: 8px; }
|
|
16117
|
+
.cx-ui legend { font-weight: 600; padding: 0 4px; }
|
|
16118
|
+
.cx-ui label { display: flex; align-items: center; gap: 8px; min-height: 44px; }
|
|
16119
|
+
.cx-composer { position: sticky; bottom: -16px; z-index: 1; display: flex; gap: 8px; align-items: flex-end; margin: 0 0 -16px; padding: 8px 0 16px; background: var(--ax-bg); }
|
|
16120
|
+
.cx-composer textarea {
|
|
16121
|
+
flex: 1; min-width: 0; min-height: 44px; max-height: 40vh; resize: none; padding: 10px 12px; font: inherit; font-size: 16px; box-sizing: border-box;
|
|
16122
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); color: var(--ax-text);
|
|
16123
|
+
}
|
|
16124
|
+
.cx-send {
|
|
16125
|
+
min-width: 72px; min-height: 44px; cursor: pointer; font: inherit; font-weight: 700;
|
|
16126
|
+
border: var(--ax-border-w) solid color-mix(in oklch, var(--ax-accent) 50%, var(--ax-border)); border-radius: var(--ax-radius);
|
|
16127
|
+
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
16128
|
+
}
|
|
16129
|
+
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
16130
|
+
`;var Bt=`
|
|
15503
16131
|
var CACHE = 'agentx-app-v2';
|
|
15504
16132
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
15505
16133
|
self.addEventListener('install', function (e) {
|
|
@@ -15567,7 +16195,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
15567
16195
|
return self.clients.openWindow(target);
|
|
15568
16196
|
}));
|
|
15569
16197
|
});
|
|
15570
|
-
`;var
|
|
16198
|
+
`;var Wl="<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 zt(t){return`<meta charset="utf-8">
|
|
15571
16199
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
15572
16200
|
<meta name="theme-color" content="#2979FF">
|
|
15573
16201
|
<meta name="referrer" content="no-referrer">
|
|
@@ -15578,13 +16206,13 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
15578
16206
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
15579
16207
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
15580
16208
|
<title>${t}</title>
|
|
15581
|
-
${
|
|
15582
|
-
<style>${
|
|
16209
|
+
${Wl}
|
|
16210
|
+
<style>${_a}${Kl}</style>`}var Pr=[{id:"chat",label:"Chat",soon:"Loading your conversations\u2026"},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Loading notifications\u2026"}];function Nr(){let t=Pr.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=Pr.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
15583
16211
|
<h2>${a.label}</h2>
|
|
15584
16212
|
<p class="soon">${a.soon}</p>
|
|
15585
16213
|
</section>`).join("");return`<!doctype html>
|
|
15586
16214
|
<html lang="en">
|
|
15587
|
-
<head>${
|
|
16215
|
+
<head>${zt("AgentX")}<style>${Jl}${Ir}${Rr}</style></head>
|
|
15588
16216
|
<body>
|
|
15589
16217
|
<header class="bar">
|
|
15590
16218
|
<div>
|
|
@@ -15596,23 +16224,24 @@ ${fl}
|
|
|
15596
16224
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
15597
16225
|
<main>${e}</main>
|
|
15598
16226
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
15599
|
-
<script>${
|
|
15600
|
-
<script>${
|
|
15601
|
-
<script>${
|
|
16227
|
+
<script>${Gl}</script>
|
|
16228
|
+
<script>${Mr}</script>
|
|
16229
|
+
<script>${$r}</script>
|
|
16230
|
+
<script>${ue({markdownToHtml:Ea})}${jr}${Lr}</script>
|
|
15602
16231
|
</body>
|
|
15603
|
-
</html>`}function
|
|
16232
|
+
</html>`}function Or(){return`<!doctype html>
|
|
15604
16233
|
<html lang="en">
|
|
15605
|
-
<head>${
|
|
16234
|
+
<head>${zt("Pair \xB7 AgentX")}</head>
|
|
15606
16235
|
<body>
|
|
15607
16236
|
<main class="card">
|
|
15608
16237
|
<h1>Pairing this phone\u2026</h1>
|
|
15609
16238
|
<p id="msg" role="status">One moment.</p>
|
|
15610
16239
|
</main>
|
|
15611
|
-
<script>${
|
|
16240
|
+
<script>${Xl}</script>
|
|
15612
16241
|
</body>
|
|
15613
|
-
</html>`}function
|
|
16242
|
+
</html>`}function Dr(){return`<!doctype html>
|
|
15614
16243
|
<html lang="en">
|
|
15615
|
-
<head>${
|
|
16244
|
+
<head>${zt("Not paired \xB7 AgentX")}</head>
|
|
15616
16245
|
<body>
|
|
15617
16246
|
<main class="card">
|
|
15618
16247
|
<h1>This phone isn't paired</h1>
|
|
@@ -15620,7 +16249,7 @@ ${fl}
|
|
|
15620
16249
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
15621
16250
|
</main>
|
|
15622
16251
|
</body>
|
|
15623
|
-
</html>`}function
|
|
16252
|
+
</html>`}function Hr(){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 Gl=`
|
|
15624
16253
|
(function () {
|
|
15625
16254
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
15626
16255
|
function select(tab, focus) {
|
|
@@ -15686,7 +16315,7 @@ ${fl}
|
|
|
15686
16315
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
15687
16316
|
}
|
|
15688
16317
|
})();
|
|
15689
|
-
`,
|
|
16318
|
+
`,Xl=`
|
|
15690
16319
|
(function () {
|
|
15691
16320
|
var msg = document.getElementById('msg');
|
|
15692
16321
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -15703,7 +16332,7 @@ ${fl}
|
|
|
15703
16332
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
15704
16333
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
15705
16334
|
})();
|
|
15706
|
-
`,
|
|
16335
|
+
`,Kl=`
|
|
15707
16336
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
15708
16337
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
15709
16338
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -15715,7 +16344,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
15715
16344
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
15716
16345
|
.muted { color: var(--ax-text-2); }
|
|
15717
16346
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
15718
|
-
`,
|
|
16347
|
+
`,Jl=`
|
|
15719
16348
|
body { display: flex; flex-direction: column; }
|
|
15720
16349
|
.bar {
|
|
15721
16350
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -15752,21 +16381,38 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
15752
16381
|
}
|
|
15753
16382
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
15754
16383
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
15755
|
-
`;var
|
|
16384
|
+
`;var zr="agentx_app",Vl=400*86400;async function qr(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Q;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",Hr());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",Bt);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Ot(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Ot(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",Or())}if(n==="POST"&&a==="/api/app/session"){let i=Br(qt(t),o);return i?(e.setHeader("Set-Cookie",`${zr}=${qt(t)}; Path=/; Max-Age=${Vl}; HttpOnly; Secure; SameSite=Strict`),Re(e,200,{device:i.name})):Re(e,401,{error:"invalid or revoked device token"})}let s=Br(Yl(t),o);return s?n==="GET"&&a==="/app"?fe(e,200,"text/html; charset=utf-8",Nr()):n==="GET"&&a==="/api/app/me"?Re(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await yr(t,e,a,n,s.name,r.fleet)||r.push&&await kr(t,e,a,n,s,r.push)||r.chat&&await Tr(t,e,a,n,s,r.chat)?!0:Re(e,404,{error:"not found"}):a==="/app"?fe(e,401,"text/html; charset=utf-8",Dr()):Re(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function Br(t,e){if(!t)return null;let a=e.verify(t);return a&&ge(a,"app")?a:null}function Yl(t){return qt(t)??Ql(t,zr)}function qt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ql(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Re(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Zl}from"crypto";var Ce={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},ed=/^c[a-z0-9]{8,32}$/;function td(t){return ed.test(t)}var ot=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
16385
|
+
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
16386
|
+
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
16387
|
+
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
16388
|
+
CREATE INDEX IF NOT EXISTS app_chat_conversations_device ON app_chat_conversations(device_id, updated_at);
|
|
16389
|
+
CREATE TABLE IF NOT EXISTS app_chat_messages (
|
|
16390
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id TEXT NOT NULL, role TEXT NOT NULL,
|
|
16391
|
+
content TEXT NOT NULL, status TEXT, error TEXT, ui TEXT, tools TEXT, at INTEGER NOT NULL);
|
|
16392
|
+
CREATE INDEX IF NOT EXISTS app_chat_messages_conversation ON app_chat_messages(conversation_id, id);`)}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${Zl(4).toString("hex")}`,s={id:o,title:nd(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
16393
|
+
(id, device_id, title, node, node_name, agent, agent_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,s.title,s.node,s.nodeName,s.agent,s.agentName??null,r,r),this.pruneDevice(e),s}get(e,a){if(!td(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(ad);return{...Ur(n),messages:r}}list(e,a=Ce.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
16394
|
+
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
16395
|
+
(SELECT substr(m.content, 1, 240) FROM app_chat_messages m WHERE m.conversation_id = c.id ORDER BY m.id DESC LIMIT 1) AS last
|
|
16396
|
+
FROM app_chat_conversations c WHERE c.device_id = ? ORDER BY c.updated_at DESC, c.rowid DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>{let o=typeof r.last=="string"?r.last.replace(/\s+/g," ").trim().slice(0,120):"";return{...Ur(r),messages:r.n,...o?{last:o}:{}}})}append(e,a,n){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return!1;let o=n.content.length>Ce.content?n.content.slice(0,Ce.content)+`
|
|
16397
|
+
|
|
16398
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,Ce.toolsPerMessage);return this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, at)
|
|
16399
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,o,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,s?.length?JSON.stringify(s):null,n.at),this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
16400
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ce.messagesPerConversation),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),!0}pruneDevice(e){let a=this.db.prepare(`SELECT id FROM app_chat_conversations WHERE device_id = ?
|
|
16401
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ce.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function Ur(t){return{id:t.id,title:t.title,node:t.node,nodeName:t.node_name,agent:t.agent,...t.agent_name?{agentName:t.agent_name}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function ad(t){let e=r=>{if(r)try{return JSON.parse(r)}catch{return}},a=e(t.ui),n=e(t.tools);return{role:t.role,content:t.content,at:t.at,...t.status?{status:t.status}:{},...t.error?{error:t.error}:{},...a?{ui:a}:{},...n?{tools:n}:{}}}function nd(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function Bm(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,hd(y,t))}catch(w){console.error(` Board "${y.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Pe(process.cwd(),t.workflows.dir):void 0,d=new Zt(l?{baseDir:l}:void 0),p=new ea(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new ta(l?{baseDir:l}:void 0);Bn(t),fa({business:t.business?.enabled===!0}),rd(async(y,w)=>{try{await pd(y,w,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(T){b(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let y=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
15756
16402
|
Live dashboard: http://${y}:${n}
|
|
15757
16403
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
15758
16404
|
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
|
|
16405
|
+
`),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var cd=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 pd(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ua(t.headers)==="foreign"&&ma(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await qr(t,e,r,o,{nodeName:a.config.node?.name,fleet:Kr(a.config),push:$d(a.config),chat:Ld(a.config)}))return;if(o==="GET"&&cd.has(r)&&Pa("page",r),o==="GET"&&r==="/"){let c=Ma();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(Pt({peers:N(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pr({peers:N(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pt({peers:N(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await he(a.config);if(!c){b(e,503,{error:"no node available"});return}let m=await new Promise(x=>{let k="";t.on("data",v=>k+=v),t.on("end",()=>x(k)),t.on("error",()=>x(""))}),h=await fetch(c.url+r,{method:"POST",headers:{"Content-Type":"application/json",...c.token?{Authorization:`Bearer ${c.token}`}:{}},body:m||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(c){b(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 he(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await pe(t):void 0,x=h?.node??m,k=x?c.find(M=>M.url===x):c[0];if(!k){b(e,400,{error:"unknown node"});return}let v=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",_=await fetch(k.url+r+v,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});b(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(c){b(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 pe(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await he(a.config);if(!c){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wa({peers:N(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fa({peers:N(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(Ba({peers:N(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,m=setTimeout(()=>c.abort(),8e3);try{let h=na(await he(a.config,c.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(h.map(async A=>{try{let E=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:A.name,url:A.url,ok:!0,data:await E.json()}}catch(E){return{name:A.name,url:A.url,ok:!1,error:E.message}}}));b(e,200,{nodes:M});return}let x=h.find(M=>M.url===n.searchParams.get("node"));if(!x){b(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){b(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await aa(t)):void 0,_=await fetch(x.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:v,signal:c.signal,headers:{"Content-Type":"application/json",...x.token?{Authorization:`Bearer ${x.token}`}:{}}});b(e,_.status,await _.json())}catch(h){b(e,502,{error:h.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ir({peers:N(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({peers:N(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mr({peers:N(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fr({peers:N(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Aa({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let c=n.searchParams.get("agent")||"",m=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(hr({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:m,peers:N(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(gr({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:N(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Ia(t,e);return}if(o==="POST"&&r==="/api/setup"){await $a(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await La(t,e);return}if(o==="GET"&&r==="/admin"){Va(t,e,N(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){dn(e,N(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){nn(t,e,N(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}gn(t,e,N(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 Dd(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await jt(t,e,r,h=>Vr(h,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let h=decodeURIComponent(m[1]),x=h.indexOf("::");if(x>0){let k=h.slice(0,x),v=h.slice(x+2),_=a.config.node?.id||a.config.node?.name||"local";if(k===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===k);if(M){let A=Oe(M.url.replace(/\/+$/,""),a.config);if(A){await Wr(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}b(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=Oe(c,a.config);if(!m){b(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Wr(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await xn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Hd(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-IBWQVQV4.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:h});b(e,200,x)}catch(c){b(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(wn({peers:N(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await yn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kn({peers:N(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({peers:N(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 xd(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 zn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await jt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Un(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){Gn(t,e,d[1],N(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let c=t.headers.authorization||"",m=c.startsWith("Bearer ")?c.slice(7):"";if(m!==a.token){let h=new Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ya(t,e);return}if(r.startsWith("/api/admin/approvals")){await cn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await rn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Xn(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(Ga);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){b(e,400,{error:"invalid asset name"});return}let m=Nd("web/"+c);try{let h=await Od(m),x=c.endsWith(".map")?"application/json; charset=utf-8":c.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":x,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await Ne(a.config);b(e,200,c)}catch(c){b(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),m=n.searchParams.get("timezone")||"UTC",h=await Ne(a.config,{date:c,timezone:m});b(e,200,h)}catch(c){b(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(m,h,x,k)=>{let v=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(v)?Math.max(x,Math.min(k,v)):h};try{let m=await he(a.config);b(e,200,await lr(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let c=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(c)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(h,x,k,v)=>{let _=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(_)?Math.max(k,Math.min(v,_)):x};try{let h=await he(a.config);b(e,200,await cr(h,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(h){b(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){b(e,400,{error:"node query param required"});return}let m=n.searchParams,h;if(r==="/api/mesh/thread"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){b(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[x,k]=[m.get("kind"),m.get("key")];if(!x||!k){b(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(x)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){b(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let x=m.get("task");if(!x){b(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(x)}`}try{await dr(e,await he(a.config),c,h)}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Sd(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("agent"),x=c.searchParams.get("task");if(!m||!h||!x){b(e,400,{error:"node, agent, task query params required"});return}await Td(t,e,a,m,h,x);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("agent"),x=c.searchParams.get("task"),k=c.searchParams.get("limit")||"50";if(!m||!h){b(e,400,{error:"node and agent query params required"});return}await Md(e,a,m,h,x,k);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("task"),x=c.searchParams.get("kind");if(!m||!h||x!=="cancel"&&x!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Id(t,e,a,m,h,x);return}if(o==="POST"&&r==="/api/voice/stop"){let c=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!c){b(e,400,{error:"node query param required"});return}await Xt(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 m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:c});if(!m.ok)throw new Error(`HTTP ${m.status}`);let h=await m.json();b(e,200,h)}catch(c){b(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 m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:c});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(c){b(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await pe(t);try{let m=await Rd(a.config,c);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let c=p[1];if(!Cd(t,e,[`agent:${c}`]))return;await Ad(t,e,a.config,c);return}if(r.startsWith("/api/")&&a.token){let c=t.headers.authorization||"",m=c.startsWith("Bearer ")?c.slice(7):"";if(m!==a.token){let h=new Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await bd(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){b(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){b(e,400,{error:"node query param required"});return}await Xt(t,e,a,c,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(_=>({name:_.name,url:_.url,token:_.token}))],x={flag:!1},k=[];t.on("close",()=>{x.flag=!0;for(let _ of k)try{_.abort()}catch{}});let v=setInterval(()=>{if(!x.flag)try{e.write(`: ping
|
|
15760
16406
|
|
|
15761
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(
|
|
16407
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let _ of h)(async()=>{let M={Accept:"text/event-stream"};_.token&&(M.Authorization=`Bearer ${_.token}`);let A=new AbortController;k.push(A);try{let E=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:A.signal});if(!E.ok||!E.body)return;let I=E.body.getReader(),j=new TextDecoder,R="";for(;!x.flag;){let{done:B,value:te}=await I.read();if(B)break;R+=j.decode(te,{stream:!0});let z;for(;(z=R.indexOf(`
|
|
15762
16408
|
|
|
15763
|
-
`))>=0;){let D=R.slice(0,
|
|
16409
|
+
`))>=0;){let D=R.slice(0,z);if(R=R.slice(z+2),x.flag)break;try{e.write(D+`
|
|
15764
16410
|
|
|
15765
|
-
`)}catch{
|
|
15766
|
-
`;
|
|
16411
|
+
`)}catch{x.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let c=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(c.searchParams.get("limit")||50))),h=c.searchParams.get("workflowId")||void 0,x=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:m,workflowId:h}),v=`?limit=${m}${h?`&workflowId=${encodeURIComponent(h)}`:""}${x?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(j=>({url:j.url,token:j.token}))],M=await Promise.all(_.map(async j=>{let R={};j.token&&(R.Authorization=`Bearer ${j.token}`);try{let B=new AbortController,te=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${j.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:R,signal:B.signal});if(!z.ok)return[];let D=await z.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(te)}}catch{return[]}})),A=new Map;for(let j of k)A.set(j.id,j);for(let j of M)for(let R of j)A.set(R.id,R);let E=Array.from(A.values()).sort((j,R)=>j.updatedAt<R.updatedAt?1:-1).slice(0,m),I=x?E.map(j=>fd(j)):E;b(e,200,{runs:I})}catch(c){b(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]),m=a.workflowRuns.get(c);if(m){b(e,200,{run:m});return}let h=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))];for(let x of h)try{let k={};x.token&&(k.Authorization=`Bearer ${x.token}`);let v=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(c)}`,{headers:k});if(v.ok){b(e,200,await v.json());return}}catch{}b(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 m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${m}/api/actions/builtin`,{headers:c}),x=await h.json().catch(()=>({error:`HTTP ${h.status}`}));b(e,h.status,x)}catch(c){b(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 pe(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${h}/workflows/${encodeURIComponent(y[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&vr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,h,x)=>{if(a.token)return!0;let k=gt(m);if(!k)return!0;let v=new Q().verify(k);if(!v)return b(h,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!ge(v,_))return b(h,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(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 w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let c=a.sources.get(w[1]);if(!c){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(T&&o==="GET"){let c=a.sources.get(T[1]);if(!c){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(g&&o==="PATCH"){let[,c,m]=g,h=decodeURIComponent(m),x=a.boards.find(A=>A.id===c);if(!x){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}let v=await pe(t),_=x.columns.find(A=>A.id===v.to),M=x.columns.find(A=>A.id===v.from);if(!_){b(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await md(k,h,M,_),Ut({actor:Ft(t),action:"move",boardId:c,itemId:h,payload:{from:v.from,to:v.to}}),b(e,200,{ok:!0})}catch(A){b(e,502,{error:A.message||"transition failed"})}return}if(S){let[,c,m]=S,h=m?decodeURIComponent(m):void 0,x=a.boards.find(v=>v.id===c);if(!x){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!h){let{columns:v,totals:_}=await ud(x,k,n.searchParams);b(e,200,{columns:v,totals:_});return}if(o==="GET"&&h){try{let v=typeof k.getItem=="function"?await k.getItem(h):null;if(!v){b(e,404,{error:"not found"});return}b(e,200,v)}catch(v){b(e,502,{error:v.message})}return}if(o==="PATCH"&&h){let v=await pe(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(h,v):null;if(!_){b(e,501,{error:"update unsupported"});return}Ut({actor:Ft(t),action:"update",boardId:c,itemId:h,payload:v}),b(e,200,_)}catch(_){b(e,502,{error:_.message})}return}if(o==="POST"&&!h){let v=await pe(t);if(!v.title){b(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){b(e,400,{error:`source ${k.type} does not support create`});return}try{let _=await k.create({title:v.title,description:v.description,labels:v.labels,assigneeUsernames:v.assigneeUsernames,milestoneTitle:v.milestoneTitle,projectHint:v.projectHint});Ut({actor:Ft(t),action:"create",boardId:c,itemId:_.id,payload:{title:v.title}}),b(e,201,_)}catch(_){b(e,502,{error:_.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}}b(e,404,{error:"not found",path:r})}async function ud(t,e,a){if(!e.capabilities.listAll||!e.listAll){let c={};for(let m of t.columns)c[m.id]=[];return{columns:c,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(c=>c.kind!=="closed"),u=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=u?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let c of t.columns)w[c.id]=[];let T=t.columns.find(c=>c.kind==="closed");for(let c of y)T&&w[T.id].push({...c,stage:T.id});let g=t.columns.filter(c=>c.kind!=="closed");for(let c of f){let m=Jt(c,g);if(!m)continue;let h=w[m];h&&h.push({...c,stage:m})}if(i)for(let c of Object.keys(w))w[c]=w[c].filter(m=>m.assignee===i);for(let c of Object.keys(w))w[c].sort((m,h)=>{let x=(m.priority??99)-(h.priority??99);return x!==0?x:(h.updatedAt||"").localeCompare(m.updatedAt||"")});let S=Object.fromEntries(Object.entries(w).map(([c,m])=>[c,m.length]));return{columns:w,totals:S}}async function md(t,e,a,n){let r=Vt(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 fd(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 hd(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 ga(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ut(t){try{let e=Pe(process.cwd(),".agentx");Gr(e)||sd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
16412
|
+
`;od(Pe(e,"board-audit.jsonl"),a)}catch{}}function Ft(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function gd(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,u,f,y,w]=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 T=await l.json();if(o.agents=T.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),i&&i.ok){let g=await i.json();o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(p&&p.ok){let g=await p.json();o.crons=g.map(S=>({id:S.id,enabled:S.enabled===!0,schedule:String(S.schedule||""),timezone:S.timezone,agent:String(S.agent||""),kind:typeof S.command=="string"&&S.command.trim()?"command":"agent",model:S.model,nextRun:S.nextRun,retryPending:S.retryPending===!0,consecutiveErrors:Number(S.consecutiveErrors)||0}))}if(u&&u.ok){let g=await u.json();o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(y&&y.ok){let g=await y.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,ia.routines))}if(f&&f.ok){let g=await f.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Ed(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await vd(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var st=null;function xd(t){if(st)return st;let e=Pe(process.cwd(),".agentx/wiki");return st=Da({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),st}var Wt=new WeakMap;async function vd(t){if(Wt.has(t))return Wt.get(t);try{let e=t.ok?await t.json():null;return Wt.set(t,e),e}catch{return null}}async function lt(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 bd(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||se(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function he(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=se(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:se(a,l)})}let s=await lt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:se(a,i.url)});return[...o.values()]}var yd=3e3,wd=6e3,kd=5*6e4,Gt=new Map,it=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=it.get(a);if(n)return n;let r=(async()=>{let o=await he(t,AbortSignal.timeout(yd)),s=await Promise.all(o.map(async i=>{let l=await gd(i.url,i.token,AbortSignal.timeout(wd),e);return e?l:_d(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>it.delete(a));return it.set(a,r),r}function _d(t,e,a=Date.now()){if(e.reachable&&!e.error)return Gt.set(t,{node:e,at:a}),e;let n=Gt.get(t);return!n||a-n.at>kd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function zm(){Gt.clear(),it.clear()}function Ed(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 Sd(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
16413
|
data: ${JSON.stringify(d)}
|
|
15768
16414
|
|
|
15769
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await
|
|
16415
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ne(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 Td(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await lt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(w){b(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:T}=await f.read();if(T)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Cd(t,e,a){let n=gt(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Q().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ge(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Ad(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await pe(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(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){b(e,502,{error:d.message||"upstream call failed"})}}async function Md(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await lt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(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 u=await fetch(`${s}${p}`,{headers:d}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){b(t,502,{error:u.message||"upstream fetch failed"})}}async function Id(t,e,a,n,r,o){await Xt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Xt(t,e,a,n,r){let o={};try{o=await pe(t)??{}}catch{}let s=await Xr(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Xr(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 lt(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=se(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 $d(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=ca(e.keysFile);return{store:()=>{let r=ut();return r?new ka(r):null},publicKey:()=>pa(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Kr(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ne(t,n),async nodePost(n,r,o){let s=await Xr(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=He({root:process.cwd()}).items.map(Fr)}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=Oe(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(Fr)}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=we(),p=await Be({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=Oe(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 Ld(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=se(t.dashboard,e),n=Kr(t);return{store:()=>{let r=ut();return r?new ot(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ne(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s)}}function Fr(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 jd=`
|
|
15770
16416
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
15771
16417
|
|
|
15772
16418
|
Title pattern:
|
|
@@ -15798,16 +16444,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
15798
16444
|
Shape:
|
|
15799
16445
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
15800
16446
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
15801
|
-
`;async function
|
|
16447
|
+
`;async function Rd(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):
|
|
15802
16448
|
- ${r.knownLabels.slice(0,60).join(`
|
|
15803
16449
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
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:
|
|
16450
|
+
`),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:jd}})});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(),u=Pd(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.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:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function Pd(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 Nd(t){let e=dd(ld(import.meta.url));return Pe(e,t)}async function Od(t){return id(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function pe(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function Jr(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function N(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:Jr(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 Dd(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await tt(await Vr(r,a.config)))}async function Vr(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Lt(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=Oe(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Hn(n)}async function Hd(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),y=f.find(w=>Gr(w));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}
|
|
15805
16451
|
|
|
15806
|
-
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=
|
|
16452
|
+
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
|
|
15807
16453
|
`))>=0;){let y=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
|
|
15808
16454
|
data: ${y.replace(/\n/g," ")}
|
|
15809
16455
|
|
|
15810
16456
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
|
|
15811
16457
|
|
|
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
|
|
15813
|
-
//# sourceMappingURL=board-dashboard-
|
|
16458
|
+
`)}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 Wr(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let y=[];t.on("data",w=>y.push(w)),t.on("end",()=>u(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 u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Oe(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Jr(n),token:n.dashboardToken||n.token}:null}export{Ed as applyAttachSessions,pd as handleBoardRequest,zm as resetLiveCaches,he as resolveNodeTargets,Bm as startBoardDashboard,_d as withLastGood};
|
|
16459
|
+
//# sourceMappingURL=board-dashboard-NRRYCDZW.js.map
|