agentix-cli 0.60.0 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{board-dashboard-BVRRDYAG.js → board-dashboard-C6AZHDHU.js} +655 -188
- package/dist/board-dashboard-C6AZHDHU.js.map +1 -0
- package/dist/{chunk-TM762AXU.js → chunk-BCXKRD5L.js} +4 -4
- package/dist/{chunk-TM762AXU.js.map → chunk-BCXKRD5L.js.map} +1 -1
- package/dist/chunk-RVEMQCWW.js +130 -0
- package/dist/chunk-RVEMQCWW.js.map +1 -0
- package/dist/{chunk-RYFUFX6F.js → chunk-Y76THZUQ.js} +154 -252
- package/dist/chunk-Y76THZUQ.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-BOCLU6ES.js → program-L6VAFALE.js} +2 -2
- package/package.json +1 -1
- package/dist/board-dashboard-BVRRDYAG.js.map +0 -1
- package/dist/chunk-PAOV37KQ.js +0 -29
- package/dist/chunk-PAOV37KQ.js.map +0 -1
- package/dist/chunk-RYFUFX6F.js.map +0 -1
- /package/dist/{program-BOCLU6ES.js.map → program-L6VAFALE.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as Ma}from"./chunk-WWMFNLKD.js";import{a as Pa}from"./chunk-GUJB53QU.js";import{a as C,b as Oa,c as Da,d as Na,e as Ha,h as Ba,i as _e,j as za,k as qa,l as Fa,m as Wa,n as Ga}from"./chunk-WOPFHKBF.js";import{a as Ua}from"./chunk-Z3IP66SL.js";import{a as Ia,b as me,c as $a,d as $,e as P,j as Je,k as Ve,l as ee,m as U,n as Ye,o as La,p as Ra,q as ja}from"./chunk-KAFO5QZR.js";import{A as Ue,G as ne,H as xa,I as va,W as bt,X as wa,a as da,aa as ka,ba as yt,c as ze,d as xt,e as ca,ga as _a,i as pa,ia as ke,ja as Fe,k as ua,ka as We,la as Ge,m as Z,ma as Xe,n as xe,na as Sa,o as vt,oa as Ea,pa as Ta,qa as Ke,sa as Ca,va as Aa,z as qe}from"./chunk-RVEMQCWW.js";import{g as ia,h as la}from"./chunk-E2PWCU2N.js";import{o as ma,r as fa}from"./chunk-S7CVSKOX.js";import{a as ba,b as ya}from"./chunk-LQRBGQIR.js";import"./chunk-27P5NLTC.js";import"./chunk-LXUG2X26.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ha,c as ga}from"./chunk-2D3RYIDU.js";import{a as na,c as ht,d as gt,h as ra,i as oa,j as sa}from"./chunk-WIBMNQKJ.js";import"./chunk-WP6KLXTP.js";import{a as Be}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-JORXRF4E.js";import"./chunk-CRSXKQLZ.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-2VQIPJH5.js";import{b as aa}from"./chunk-E2BJVHBR.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-NBGNPKAF.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 ea,b as ta,c as vo,w as Q,z as ft}from"./chunk-S7TCVIET.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function wt(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 Xa(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:wt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var te={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',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"/>'},ve=(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>",Qe=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ve(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ka(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 Ea}from"./chunk-WWMFNLKD.js";import{a as Ia}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">${ve(te.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${ve(te.refresh)} Refresh</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
@@ -21,24 +21,24 @@ import{a as Ea}from"./chunk-WWMFNLKD.js";import{a as Ia}from"./chunk-GUJB53QU.js
|
|
|
21
21
|
|
|
22
22
|
<div class="bf-grid">
|
|
23
23
|
<section class="bf-col">
|
|
24
|
-
${
|
|
24
|
+
${Qe(te.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
|
+
${Qe(te.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
|
+
${Qe(te.pulse,"In motion","run-count")}
|
|
35
35
|
<div id="running" class="bf-col"></div>
|
|
36
36
|
</aside>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
${
|
|
39
|
+
${Qe(te.file,"Session briefings","brief-count")}
|
|
40
40
|
<div class="bf-toolbar">
|
|
41
|
-
<div class="bf-search">${
|
|
41
|
+
<div class="bf-search">${ve(te.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 @@ ${Je(ee.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">${ve(te.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">${ve(te.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>${ve(te.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 @@ ${Je(ee.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:bo,scripts:`<script>${me({decayOf:wt,rankByDecay:Xa})}const ICON = ${JSON.stringify(te)};${yo}</script>`})}var bo=`
|
|
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
|
+
}`,yo=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 kt(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 _t(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 Ja(t,e=[],a){let{bands:n,gaps:r}=kt(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,b=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:b,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)=>_t(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 wo}from"crypto";import{readFileSync as ko,statSync as _o}from"fs";import{resolve as So,dirname as Eo}from"path";import{fileURLToPath as To}from"url";var Va=new Map;function Ze(t){let e=Va.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Eo(To(import.meta.url)),r=So(n,"web",t),o=_o(r),s=o.size<8e6?wo("sha1").update(ko(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Va.set(t,a),a}var re={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"/>'},et=(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>",Co=[["agent","Agent",re.bot],["client","Client",re.user],["project","Project",re.folder],["channel","Channel",re.route],["node","Node",re.mesh]],Ya={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 Qa(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">${Ya[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",re.timeline],["map","Map",re.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${et(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":""}>${et(re.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
|
+
${Co.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${et(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">${et(re.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="${Ze("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Ao,scripts:`<script>${me({computeBands:kt,packTracks:_t,buildTimeline:Ja})}const ICON = ${JSON.stringify(re)};const SUB = ${JSON.stringify(Ya)};${Mo}</script>`})}var Ao=`
|
|
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
|
+
`,Mo=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 Za(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:Io,scripts:`<script src="${Ze("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Io=`
|
|
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 gd}from"http";import{appendFileSync as xd,existsSync as Zr,mkdirSync as vd}from"fs";import{readFile as bd}from"fs/promises";import{fileURLToPath as yd}from"url";import{dirname as wd,resolve as Pe}from"path";so();var Ja='/*! 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 Ya,writeFileSync as Qa,rmSync as kc,mkdirSync as So,copyFileSync as To,readdirSync as Co}from"fs";import{resolve as _e}from"path";ut();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 Va(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+wo()+Ca,css:_o,scripts:`${e}<script>${Aa}
|
|
1047
|
-
${
|
|
1048
|
-
${
|
|
1049
|
-
${
|
|
1046
|
+
`;import{createServer as Md}from"http";import{appendFileSync as Id,existsSync as po,mkdirSync as $d}from"fs";import{readFile as Ld}from"fs/promises";import{fileURLToPath as Rd}from"url";import{dirname as jd,resolve as De}from"path";vo();var en='/*! 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 tt,readFileSync as an,writeFileSync as nn,rmSync as Oc,mkdirSync as Oo,copyFileSync as Do,readdirSync as No}from"fs";import{resolve as Se}from"path";ft();var oe={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 tn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Je({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.`})+Ve([{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+Lo()+La,css:jo,scripts:`${e}<script>${Ra}
|
|
1047
|
+
${ja}
|
|
1048
|
+
${$o}
|
|
1049
|
+
${Po}</script>`})}var $o=`
|
|
1050
1050
|
(function(){
|
|
1051
1051
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1052
1052
|
async function refresh() {
|
|
@@ -1107,8 +1107,8 @@ ${Eo}</script>`})}var yo=`
|
|
|
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 Lo(){let t=ya().business?`<button data-tab="business">Business</button>
|
|
1111
|
+
`:"";return Ro.replace("__BUSINESS_TABS__",t)}var Ro=`
|
|
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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1251
1251
|
<div id="global-msg" class="msg"></div>
|
|
1252
1252
|
|
|
1253
1253
|
<section id="tab-agents" class="tab active">
|
|
1254
|
-
${U({icon:
|
|
1255
|
-
${
|
|
1254
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1274
1274
|
</section>
|
|
1275
1275
|
|
|
1276
1276
|
<section id="tab-channels" class="tab">
|
|
1277
|
-
${U({icon:
|
|
1278
|
-
${
|
|
1277
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1360
1360
|
</div>
|
|
1361
1361
|
</details>
|
|
1362
1362
|
|
|
1363
|
-
<div id="ch-chatapps-label">${
|
|
1363
|
+
<div id="ch-chatapps-label">${Ye({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">${Ye({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1381
1381
|
</section>
|
|
1382
1382
|
|
|
1383
1383
|
<section id="tab-crons" class="tab">
|
|
1384
|
-
${U({icon:
|
|
1385
|
-
${
|
|
1384
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1479
1479
|
</section>
|
|
1480
1480
|
|
|
1481
1481
|
<section id="tab-webhooks" class="tab">
|
|
1482
|
-
${U({icon:
|
|
1483
|
-
${
|
|
1482
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1499
1499
|
</section>
|
|
1500
1500
|
|
|
1501
1501
|
<section id="tab-mesh" class="tab">
|
|
1502
|
-
${U({icon:
|
|
1502
|
+
${U({icon:oe.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
|
+
${ee({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
|
+
${Ye({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1529
1529
|
</section>
|
|
1530
1530
|
|
|
1531
1531
|
<section id="tab-business" class="tab">
|
|
1532
|
-
${U({icon:
|
|
1533
|
-
${
|
|
1532
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1617
1617
|
</section>
|
|
1618
1618
|
|
|
1619
1619
|
<section id="tab-boards-cfg" class="tab">
|
|
1620
|
-
${U({icon:
|
|
1621
|
-
${
|
|
1620
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1642
1642
|
</section>
|
|
1643
1643
|
|
|
1644
1644
|
<section id="tab-actions" class="tab">
|
|
1645
|
-
${U({icon:
|
|
1646
|
-
${
|
|
1645
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1698
1698
|
</section>
|
|
1699
1699
|
|
|
1700
1700
|
<section id="tab-tokens" class="tab">
|
|
1701
|
-
${U({icon:
|
|
1702
|
-
${
|
|
1701
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
1718
1718
|
</section>
|
|
1719
1719
|
|
|
1720
1720
|
<section id="tab-advanced" class="tab">
|
|
1721
|
-
${U({icon:
|
|
1722
|
-
${
|
|
1721
|
+
${U({icon:oe.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
|
+
${ee({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 @@ ${Eo}</script>`})}var yo=`
|
|
|
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
|
+
`,jo=`
|
|
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
|
+
`,Po=`
|
|
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 Za(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Va({peers:a,localToken:n}))}async function en(t,e){let a=_t();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function tn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await zo(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Ao(t),r={"GET /api/admin/state":()=>Io(),"POST /api/admin/agents":()=>Oo(n),"PATCH /api/admin/agents":()=>No(n),"DELETE /api/admin/agents":()=>Do(n),"POST /api/admin/agents/access":()=>$o(n),"POST /api/admin/channels/telegram":()=>Ho(n),"DELETE /api/admin/channels/telegram":()=>ds(n),"POST /api/admin/channels/telegram/toggle":()=>cs(n),"POST /api/admin/crons":()=>ps(n),"DELETE /api/admin/crons":()=>us(n),"POST /api/admin/config/raw":()=>ms(n),"GET /api/admin/tokens":()=>Lo(),"POST /api/admin/tokens":()=>jo(n),"DELETE /api/admin/tokens":()=>Ro(n),"POST /api/admin/agents/test":()=>Po(n),"POST /api/admin/agents/integrations":()=>Xo(n),"DELETE /api/admin/agents/integrations":()=>Ko(n),"PATCH /api/admin/agents/integrations":()=>Jo(n),"PATCH /api/admin/channels/telegram":()=>Bo(n),"POST /api/admin/channels/slack":()=>as(n),"POST /api/admin/channels/slack/toggle":()=>ns(n),"POST /api/admin/channels/discord":()=>rs(n),"POST /api/admin/channels/discord/toggle":()=>os(n),"POST /api/admin/channels/gitlab":()=>ss(n),"POST /api/admin/channels/gitlab/toggle":()=>is(n),"GET /api/admin/channels/whatsapp/state":()=>$e("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>$e("/webrtc/history"),"POST /api/admin/actions":()=>Ts(n),"DELETE /api/admin/actions":()=>Cs(n),"POST /api/admin/actions/run":()=>As(n),"GET /api/admin/channels/whatsapp/chats":()=>$e("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>$e("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ie("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ls(n),"POST /api/admin/webhooks":()=>Vo(n),"PATCH /api/admin/webhooks":()=>Yo(n),"DELETE /api/admin/webhooks":()=>ts(n),"POST /api/admin/mesh/peers":()=>Qo(n),"DELETE /api/admin/mesh/peers":()=>Zo(n),"POST /api/admin/mesh/toggle":()=>es(n),"GET /api/admin/files":()=>qo(t),"GET /api/admin/files/read":()=>Uo(t),"PUT /api/admin/files":()=>Fo(n),"POST /api/admin/files/skill":()=>Wo(n),"DELETE /api/admin/files/skill":()=>Go(n),"POST /api/admin/business/orgchart":()=>fs(n),"DELETE /api/admin/business/orgchart":()=>hs(n),"POST /api/admin/business/project":()=>gs(n),"DELETE /api/admin/business/project":()=>bs(n),"POST /api/admin/business/client":()=>xs(n),"DELETE /api/admin/business/client":()=>vs(n),"POST /api/admin/business/contact":()=>ys(n),"DELETE /api/admin/business/contact":()=>ws(n),"POST /api/admin/boards":()=>ks(n),"DELETE /api/admin/boards":()=>_s(n),"POST /api/admin/boards/columns":()=>Es(n),"DELETE /api/admin/boards/columns":()=>Ss(n),"POST /api/admin/notifications":()=>Is(n),"POST /api/admin/screen":()=>$s(n),"POST /api/admin/webhooks/triggers":()=>Ls(n),"POST /api/admin/mesh/health":()=>Ms(n),"GET /api/admin/projects":()=>$e("/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){wt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();wt(e,200,i)}catch(n){wt(e,400,{error:n.message||"admin op failed"})}}function wt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ao(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 Mo(t){let e=_e(process.cwd(),t);if(!Qe(e))return[];let a=[];for(let n of Co(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ya(_e(e,n.name),"utf-8")))}catch{}return a}function _t(){let t=_e(process.cwd(),"agentx.json");return Qe(t)?JSON.parse(Ya(t,"utf-8")):null}function Io(){let t=_t();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:ca(w.local),ntfy:Ha(t.channels?.ntfy)},g=[];try{g=Mo(".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:ka(t.screen),actions:g}}function $o(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 Lo(){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 jo(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 Ro(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 Po(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 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=nn(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=_e(process.cwd(),"agents",e),{summary:l}=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=_e(i,"CLAUDE.md");if(!Qe(d))try{So(i,{recursive:!0}),Qa(d,`# ${a}
|
|
4763
|
+
`;function rn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(tn({peers:a,localToken:n}))}async function on(t,e){let a=Tt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function sn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Qo(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Ho(t),r={"GET /api/admin/state":()=>zo(),"POST /api/admin/agents":()=>Xo(n),"PATCH /api/admin/agents":()=>Ko(n),"DELETE /api/admin/agents":()=>Jo(n),"POST /api/admin/agents/access":()=>qo(n),"POST /api/admin/channels/telegram":()=>Vo(n),"DELETE /api/admin/channels/telegram":()=>ys(n),"POST /api/admin/channels/telegram/toggle":()=>ws(n),"POST /api/admin/crons":()=>ks(n),"DELETE /api/admin/crons":()=>_s(n),"POST /api/admin/config/raw":()=>Ss(n),"GET /api/admin/tokens":()=>Uo(),"POST /api/admin/tokens":()=>Fo(n),"DELETE /api/admin/tokens":()=>Wo(n),"POST /api/admin/agents/test":()=>Go(n),"POST /api/admin/agents/integrations":()=>rs(n),"DELETE /api/admin/agents/integrations":()=>os(n),"PATCH /api/admin/agents/integrations":()=>ss(n),"PATCH /api/admin/channels/telegram":()=>Yo(n),"POST /api/admin/channels/slack":()=>ms(n),"POST /api/admin/channels/slack/toggle":()=>fs(n),"POST /api/admin/channels/discord":()=>hs(n),"POST /api/admin/channels/discord/toggle":()=>gs(n),"POST /api/admin/channels/gitlab":()=>xs(n),"POST /api/admin/channels/gitlab/toggle":()=>vs(n),"GET /api/admin/channels/whatsapp/state":()=>Le("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Le("/webrtc/history"),"POST /api/admin/actions":()=>Ds(n),"DELETE /api/admin/actions":()=>Ns(n),"POST /api/admin/actions/run":()=>Hs(n),"GET /api/admin/channels/whatsapp/chats":()=>Le("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Le("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>le("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>bs(n),"POST /api/admin/webhooks":()=>is(n),"PATCH /api/admin/webhooks":()=>ls(n),"DELETE /api/admin/webhooks":()=>us(n),"POST /api/admin/mesh/peers":()=>ds(n),"DELETE /api/admin/mesh/peers":()=>cs(n),"POST /api/admin/mesh/toggle":()=>ps(n),"GET /api/admin/files":()=>Zo(t),"GET /api/admin/files/read":()=>es(t),"PUT /api/admin/files":()=>ts(n),"POST /api/admin/files/skill":()=>as(n),"DELETE /api/admin/files/skill":()=>ns(n),"POST /api/admin/business/orgchart":()=>Es(n),"DELETE /api/admin/business/orgchart":()=>Ts(n),"POST /api/admin/business/project":()=>Cs(n),"DELETE /api/admin/business/project":()=>Is(n),"POST /api/admin/business/client":()=>As(n),"DELETE /api/admin/business/client":()=>Ms(n),"POST /api/admin/business/contact":()=>$s(n),"DELETE /api/admin/business/contact":()=>Ls(n),"POST /api/admin/boards":()=>Rs(n),"DELETE /api/admin/boards":()=>js(n),"POST /api/admin/boards/columns":()=>Ps(n),"DELETE /api/admin/boards/columns":()=>Os(n),"POST /api/admin/notifications":()=>zs(n),"POST /api/admin/screen":()=>qs(n),"POST /api/admin/webhooks/triggers":()=>Us(n),"POST /api/admin/mesh/health":()=>Bs(n),"GET /api/admin/projects":()=>Le("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>le("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>le("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>le("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>le("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>le("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>le("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>le("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>le("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){St(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();St(e,200,i)}catch(n){St(e,400,{error:n.message||"admin op failed"})}}function St(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ho(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 Bo(t){let e=Se(process.cwd(),t);if(!tt(e))return[];let a=[];for(let n of No(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(an(Se(e,n.name),"utf-8")))}catch{}return a}function Tt(){let t=Se(process.cwd(),"agentx.json");return tt(t)?JSON.parse(an(t,"utf-8")):null}function zo(){let t=Tt();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(g=>{let x=g.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:g.kind,label:g.label,enabled:g.enabled!==!1,credentials:x,credStatus:k,metadata:g.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||{},b={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:ma(w.local),ntfy:Fa(t.channels?.ntfy)},h=[];try{h=Bo(".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,g)=>m.id.localeCompare(g.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:u,nodeName:t.node?.name,business:b,boards:E,notifications:T,screen:Ca(t.screen),actions:h}}function qo(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 Uo(){return new Z().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 Fo(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 Z().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Wo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Z().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Go(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=Q();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 Xo(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=dn(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=Se(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=Se(i,"CLAUDE.md");if(!tt(d))try{Oo(i,{recursive:!0}),nn(d,`# ${a}
|
|
4764
4764
|
|
|
4765
4765
|
${s||"You are "+a+"."}
|
|
4766
|
-
`)}catch{}return{summary:l}}function No(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=nn(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 Do(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 Ho(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 Bo(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 $e(t){let{url:e,headers:a}=Et(),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}=Et(),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 zo(t,e){try{let{url:a,headers:n}=Et(),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 Et(){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 Le(t){let a=_t()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function kt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function qo(t){let e=kt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=we(Le(e));return{agentId:e,...a}}function Uo(t){let e=kt(t,"agent").trim(),a=kt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return ze(Le(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=qe(Le(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Wo(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(Le(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=Fe(Le(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}=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 Ko(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 Jo(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 an=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Vo(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(!an.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 Yo(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"&&an.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 Qo(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 Zo(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 es(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 ts(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 as(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 ns(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 rs(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 os(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 ss(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 is(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 ls(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-RAYGNDWT.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 ds(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 cs(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 ps(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 us(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 ms(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=_e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Qe(n))try{To(n,r)}catch{}Qa(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 nn(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function fs(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 hs(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 gs(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 xs(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 vs(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 bs(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 ys(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 ws(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 ks(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 _s(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 Es(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 Ss(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 Ts(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 Cs(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 As(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 Ms(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 Is(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=pa(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=Ba(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 $s(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=_a(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ls(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}}ut();import{resolve as Ps}from"path";function rn(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 Ko(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=dn(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 Jo(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 Vo(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 Yo(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 Le(t){let{url:e,headers:a}=Ct(),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 le(t,e){let{url:a,headers:n}=Ct(),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 Qo(t,e){try{let{url:a,headers:n}=Ct(),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 Ct(){let t="http://127.0.0.1:18800",e={};try{let a=Q();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Re(t){let a=Tt()?.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 Et(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Zo(t){let e=Et(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ke(Re(e));return{agentId:e,...a}}function es(t){let e=Et(t,"agent").trim(),a=Et(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Fe(Re(e),a)}function ts(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=We(Re(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function as(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=Ge(Re(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function ns(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=Xe(Re(e),a);return{summary:`removed skill "${a}"`,...n}}function rs(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 os(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 ss(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 ln=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function is(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(!ln.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 ls(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"&&ln.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 ds(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 cs(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 ps(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 us(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 ms(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 fs(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 hs(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 gs(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 xs(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 vs(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 bs(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-RAYGNDWT.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 ys(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 ws(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 ks(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 _s(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=Se(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(tt(n))try{Do(n,r)}catch{}nn(n,JSON.stringify(a,null,2)+`
|
|
4767
|
+
`,"utf-8");try{let s=Q().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 dn(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Es(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 Ts(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 Cs(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 As(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 Ms(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 Is(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 $s(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 Ls(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 Rs(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 js(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 Ps(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 Os(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 Ds(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 Ns(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 Hs(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 Bs(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 zs(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=fa(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=Wa(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 qs(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Aa(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Us(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ft();import{resolve as Gs}from"path";function cn(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:Fs,scripts:`${e}<script>${Ws}</script>`})}var Fs=`
|
|
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; }`,Ws=`
|
|
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 un(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cn({peers:a,localToken:n}))}async function mn(t,e,a){try{let n=t.method==="GET"?void 0:await ti(t),r=Xs(),o={"GET /api/admin/graph/state":()=>Ks(r),"POST /api/admin/graph/classifications/approve":()=>Js(r,n),"POST /api/admin/graph/classifications/reject":()=>Vs(r,n),"POST /api/admin/graph/nodes":()=>Ys(r,n),"PATCH /api/admin/graph/nodes":()=>Qs(r,n),"DELETE /api/admin/graph/nodes":()=>Zs(r,n),"PUT /api/admin/graph/schema":()=>ei(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){At(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();At(e,200,l)}catch(n){At(e,400,{error:n?.message||"graph op failed"})}}function Xs(){let t=Q(),e=Gs(process.cwd(),t.graph.baseDir);return new aa({baseDir:e})}function Ks(t){let e=Q(),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 Js(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=fn(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=Mt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Vs(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=fn(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function fn(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 Ys(t,e){let a=pn(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?pn(String(e.parentId)):null,o=Mt({[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 Qs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Mt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Zs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function ei(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 Mt(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 pn(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function At(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ti(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 hn(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:ai,scripts:`${e}<script>${ni}</script>`})}var ai=`
|
|
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
|
+
`,ni=`
|
|
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 ri=["yes","no","later"];function de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function gn(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 xn(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(hn({peers:e,localToken:a}))}async function vn(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 de(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=qe(s,{includeSnoozed:n.searchParams.get("all")==="1"});return de(e,200,{...i,settings:_e(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await gn(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!ri.includes(d))return de(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=_e(s.configPath),u=await Ue(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?(de(e,200,{ok:!0,message:u.message}),!0):(de(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await gn(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=za(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await qa(l,{configPath:s.configPath,reload:s.reload});return p.success?(de(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(de(e,400,{error:p.error}),!0)}}catch(i){return de(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return de(e,404,{error:"Not found"}),!0}import{resolve as ii}from"path";import{existsSync as li}from"fs";import di from"better-sqlite3";function bn(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:oi,scripts:`<script>${si}</script>`})}var oi=`
|
|
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
|
+
`,si=`
|
|
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 kn={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 _n(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function It(t){let e=kn[_n(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 ci(){let t=ii(process.cwd(),".agentx/db.sqlite");if(!li(t))return null;try{let e=new di(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Sn(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(bn({peers:a}))}function pi(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 ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function En(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=ci();if(!r)return ce(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=pi(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 ce(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 ce(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
|
-
`,u=r.db.prepare(d).all(l).map(f=>({...f,plain:
|
|
6018
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6017
|
+
`,u=r.db.prepare(d).all(l).map(f=>({...f,plain:Tn(f.error)}));return ce(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return ce(e,200,ui(r.db)),!0;if(n==="activity")return ce(e,200,mi(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=yn(i.searchParams.get("range"));return ce(e,200,wn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=yn(i.searchParams.get("range")),d=wn(r.db,l),p=fi(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 ce(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Tn(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 ui(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),b=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+It(M),0),h=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+It(M),0),E=t.prepare(`
|
|
6019
6019
|
SELECT agent_id,
|
|
6020
6020
|
COUNT(*) AS tasks,
|
|
6021
6021
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -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),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),
|
|
6036
|
+
`).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),g=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),x=m.filter(_=>!g.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(_=>({..._,plain:
|
|
6041
|
+
`).all(o).map(_=>({..._,plain:Tn(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:b,spendToday:T,spendDelta:T-h,idleAgentCount:x.length},perAgent:E,perChannel:c,idleAgents:x,recentErrors:v}}function mi(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 yn(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 wn(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
6069
6069
|
SELECT day, agent_id, model,
|
|
6070
6070
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
6071
6071
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -6073,20 +6073,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6073
6073
|
FROM usage_daily
|
|
6074
6074
|
${a}
|
|
6075
6075
|
ORDER BY day
|
|
6076
|
-
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,u=0,f=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,b=0,w=0,T=0,h=0,E={},c={};for(let S of n){let I=It(S),R=_n(S.model),j=kn[R],B=(S.tier2_input_tokens||0)/1e6*j.input*.5+(S.tier2_output_tokens||0)/1e6*j.output*.5+(S.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(S.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,ae=(S.input_tokens||0)+(S.tier2_input_tokens||0),z=(S.output_tokens||0)+(S.tier2_output_tokens||0),N=(S.cache_read_tokens||0)+(S.tier2_cache_read_tokens||0),H=(S.cache_create_tokens||0)+(S.tier2_cache_create_tokens||0);u+=I,S.day>=s&&(p+=I,w+=S.tasks||0),S.day>=i&&S.day<s&&(h+=I,T+=S.tasks||0),S.day===r&&(l+=I),S.day===o&&(d+=I),S.day===r&&(f+=B),S.day>=s&&(b+=B);let V=E[S.day]||(E[S.day]={date:S.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});V.tasks+=S.tasks||0,V.input+=ae,V.output+=z,V.cacheRead+=N,V.cacheCreate+=H,V.cost+=I,V.tier2+=B;let q=V.agents[S.agent_id]||(V.agents[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});q.tasks+=S.tasks||0,q.cost+=I,q.tier2+=B,q.input+=ae,q.output+=z,q.cacheRead+=N,q.cacheCreate+=H,S.model&&(q.model=S.model);let Y=c[S.agent_id]||(c[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});Y.tasks+=S.tasks||0,Y.cost+=I,Y.tier2+=B,Y.input+=ae,Y.output+=z,Y.cacheRead+=N,Y.cacheCreate+=H,S.model&&(Y.model=S.model)}let m=Object.values(E).sort((S,I)=>S.date<I.date?-1:1),g=0,x=0,k=0,v=0,_=0,M=0;for(let S of m)g+=S.tasks,x+=S.input,k+=S.output,v+=S.cacheRead,_+=S.cacheCreate,M+=S.cost;let A=Object.entries(c).map(([S,I])=>({agent_id:S,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((S,I)=>I.cost-S.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:b,tier2PctToday:l>0?f/l:0,spendRange:M,avgDailyRange:m.length?M/m.length:0,tasksRange:g,tokensRange:x+k+v+_,cacheHitRange:v+x>0?v/(v+x):0,costPerTaskRange:g>0?M/g:0,spendDeltaWoW:h>0?(p-h)/h:0,tasksDeltaWoW:T>0?(w-T)/T:0},days:m,perAgent:A}}function fi(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 hi}from"path";import{existsSync as gi}from"fs";import xi from"better-sqlite3";function vi(){let t=hi(process.cwd(),".agentx/intent/ledger.sqlite");if(!gi(t))return null;try{let e=new xi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Cn>6e4&&(Cn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Cn=0;function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function bi(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 An(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=vi();if(!r)return be(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=bi(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":"",b=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}),h=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,E=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 be(e,200,{since:s??null,eventsBySource:b,totalDecisions:w,decisionsByOutcome:T,totalDivergences:h,divergencesBySource:E,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 b=`
|
|
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 be(e,200,{rows:r.db.prepare(b).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 b=`
|
|
6090
6090
|
SELECT ts, source, decided_by,
|
|
6091
6091
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
6092
6092
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
@@ -6094,7 +6094,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6094
6094
|
FROM intent_divergences
|
|
6095
6095
|
${u.length?"WHERE "+u.join(" AND "):""}
|
|
6096
6096
|
ORDER BY ts DESC LIMIT @limit
|
|
6097
|
-
`;return
|
|
6097
|
+
`;return be(e,200,{rows:r.db.prepare(b).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 b=`
|
|
6098
6098
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
6099
6099
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
6100
6100
|
FROM intent_decisions d
|
|
@@ -6103,7 +6103,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6103
6103
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6104
6104
|
WHERE ${u.join(" AND ")}
|
|
6105
6105
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
6106
|
-
`;return
|
|
6106
|
+
`;return be(e,200,{rows:r.db.prepare(b).all(f)}),!0}return be(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return be(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Mn(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 In(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:yi,scripts:`<script>${wi}</script>`})}var yi=`
|
|
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
|
+
`,wi=`
|
|
7099
7099
|
(function(){
|
|
7100
7100
|
const $ = (sel) => document.querySelector(sel);
|
|
7101
7101
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -7745,22 +7745,22 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7745
7745
|
load();
|
|
7746
7746
|
});
|
|
7747
7747
|
})();
|
|
7748
|
-
`;import{resolve as
|
|
7748
|
+
`;import{resolve as Rt,join as Pi}from"path";import{existsSync as jt,readdirSync as Oi,readFileSync as Di}from"fs";import Ni from"better-sqlite3";var Rn=String.raw`[\w.-]+(?:/[\w.-]+)+`,ki=new RegExp(`^(?:chat:)?(${Rn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),_i=new RegExp(`^\\[(?:GitLab|GitHub) (${Rn}) `);function Ln(t){if(!t)return null;let e=t.match(ki);return e?e[1]:null}function $t(t){if(!t)return null;let e=t.trimStart().match(_i);return e?e[1]:null}function at(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Ln(typeof n?.chatId=="string"?n.chatId:null)??Ln(e)??$t(a)}function Si(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function nt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ei=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Ti=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ci=t=>/^issue/i.test(t)?"issue":"mr";function Ai(t){let e=t.subject.match(Ei)??t.inputPreview.trimStart().match(Ti);return e?{kind:Ci(e[1]),n:Number(e[2])}:null}function Mi(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 jn(t){if(!Si(t.projectId))return[];let e=Ai(t);return e?[e]:Mi(t.inputPreview)}var Ii=6e4,$i=5*6e4,Li=40,Pn=6,On=new Map;function Dn(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 jn(n)){let s=nt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Li)return[...e.values()]}}return[...e.values()]}async function Nn(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=nt(s.project,s.ref),l=On.get(i);l&&n-l.at<(s.github?$i:Ii)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Pn)await Promise.all(o.slice(s,s+Pn).map(async i=>{let l=nt(i.project,i.ref),d=null;try{d=i.github?await ji(i,e,a):await Ri(i,e,a)}catch{}On.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function Hn(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 Ri(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 Hn(`${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 ji(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 Hn(`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 Pt(){let t=Rt(process.cwd(),".agentx/intent/ledger.sqlite");if(!jt(t))return null;try{let e=new Ni(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(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Bn=0;function pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Ee={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 Hi(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Ee)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Ee)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Ee)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 Ee)return s}return"workflow"}return t}function Un(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 Bi(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 Fn(t,e,a){return ca(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 zi(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&&!Lt(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!Lt(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&&!Lt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=zn(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:zn(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 zn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Lt(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 Wn(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 qi(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 Gn(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 v=o.map(I=>I.id),_=v.map((I,
|
|
7753
|
+
`).all(r),s=new Map,i=new Map;if(o.length>0){let v=o.map(I=>I.id),_=v.map((I,R)=>`@id${R}`).join(","),M=Object.fromEntries(v.map((I,R)=>[`id${R}`,I])),A=t.prepare(`
|
|
7754
7754
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
7755
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
|
|
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 S=t.prepare(`
|
|
7757
7757
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
7758
7758
|
FROM intent_resolutions WHERE decision_event_id IN (${_})
|
|
7759
|
-
`).all(M);for(let I of
|
|
7759
|
+
`).all(M);for(let I of S)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=[],b=e?.business?.projects??[],w=e?.business?.contactMap??[],T=xt(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Fn(v.source,_,w),A=Wn(v.source,_),S=v.project??at(_,v.subject,A),I=null,R=null;M?(I=M.client,R=M.project||`${M.client}/_chat`):S&&(I=ze(S,b),R=S);let j=Hi(v.source,v.intent||"",_),B=Ee[j]||{label:j,color:"#6b7280"};p.has(j)||p.set(j,{id:j,label:B.label,color:B.color});let ae="__system",z,N=zi(v.source,v.intent||"",_);if(N){ae=N.id,z=N.kind;let H=M?.displayName||N.name;(!u.has(N.id)||M?.displayName)&&u.set(N.id,{id:N.id,name:H,avatar:F(H),kind:N.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 V=`${v.id}|${H.decided_by}`,q=i.get(V),Y=H.decided_at,Zt=q?.resolved_at??null,ut=Zt===null,go=q?.duration_ms??(ut?n-Y:0),xo=ut?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",G,$e;if(I)G=I,$e=R;else{let mt=T.get(H.agent_id);mt?(G=mt,$e=`${mt}/_${v.source}`):(G="unmapped",$e=`unmapped/_${v.source}`)}l.has(G)||l.set(G,{id:G,name:G,color:Un(G),projects:[]}),d.has(G)||d.set(G,new Set),d.get(G).add($e),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:G,projectId:$e,channelId:j,initiatorId:ae,initiatorKind:z,subject:qi(v.subject),intent:v.intent||"",startedAt:Y,resolvedAt:Zt,duration:go,active:ut,outcome:xo,tokens:0,inputPreview:A,system:Bi(H.agent_id,e)})}}let h=[...l.values()].map(v=>({...v,projects:[...d.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),E=[],c=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,S=A?v.roles?.[A]?.title:void 0;return typeof S=="string"&&S.trim()?S.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let S={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)};E.push(S),c.add(M)}}for(let v of f)c.has(v.agentId)||(E.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),c.add(v.agentId));E.sort((v,_)=>v.id.localeCompare(_.id));let m=[],g=new Set;for(let[v,_]of Object.entries(Ee))m.push({id:v,label:_.label,color:_.color}),g.add(v);for(let v of p.values())g.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:h,agents:E,channels:m,initiators:x,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function Ot(t){let e=Pt();if(!e)return null;try{return Gn(e.db,fe,t)}finally{e.close()}}function Xn(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 b=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:b})}}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=Ui(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Un(f.clientId),projects:[]}),f.projectId!==u.projectId){let b=e.get(f.clientId);b.projects.includes(f.projectId)||e.set(f.clientId,{...b,projects:[...b.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 Ui(t){if(t.clientId!=="unmapped")return t;let e=$t(t.inputPreview);if(!e)return t;let a=fe?.business?.projects??[];return{...t,projectId:e,clientId:ze(e,a)}}async function rt(t){let e=fe?.channels?.gitlab,a=await Nn(Dn(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 fe=null;function Kn(t){fe=t}async function Jn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Pt();if(!n)return pe(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Vn(parseInt(r.searchParams.get("hours")||"6",10));pe(e,200,await rt(Gn(n.db,fe,o)))}catch(r){pe(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Fi=5e3;async function Dt(t,e,a,n=Ot){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=Vn(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),u=p&&await
|
|
7763
|
+
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await rt(p);if(s)break;u?(e.write(`event: snapshot
|
|
7764
7764
|
`),e.write(`data: ${JSON.stringify(u)}
|
|
7765
7765
|
|
|
7766
7766
|
`)):e.write(`event: error
|
|
@@ -7769,7 +7769,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
7769
7769
|
`)}catch(p){e.write(`event: error
|
|
7770
7770
|
data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
7771
7771
|
|
|
7772
|
-
`)}let d=Date.now();for(;!s&&Date.now()-d<
|
|
7772
|
+
`)}let d=Date.now();for(;!s&&Date.now()-d<Fi;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Vn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Wi(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Rt(process.cwd(),".agentx/task-history",t,n);if(!jt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Rt(process.cwd(),".agentx/task-history",t,o);return jt(s)?qn(s,e,a):null}return qn(r,e,a)}function qn(t,e,a){let n=null,r=1/0;for(let o of Oi(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Di(Pi(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 Yn(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 pe(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Pt();if(!l)return pe(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 pe(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 pe(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 b=Wn(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)||b,T=null,h=null;if(p.agent_id){let k=Wi(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(T=k.responseText);let v=k.transcript;Array.isArray(v)&&(h=v.length)}}let E=fe?.business?.projects??[],c=fe?.business?.contactMap??[],m=xt(fe?.business??{}),g={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=Fn(d.source,f,c);if(x)g={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||at(f,d.subject,b)){let k=d.project||at(f,d.subject,b);g={client:ze(k,E),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&&(g={client:k,project:`${k}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}pe(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:h,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:g})}catch(d){pe(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Ji,readFileSync as Vi}from"fs";import{resolve as Zn}from"path";ft();function Qn(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=Gi.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:Xi,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>${Ki}</script>`})}var Gi=`
|
|
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
|
+
`,Xi=`
|
|
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
|
+
`,Ki=`
|
|
8481
8481
|
const $ = (id) => document.getElementById(id);
|
|
8482
8482
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
8483
8483
|
|
|
@@ -9333,15 +9333,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
9333
9333
|
/* ===== Boot ===== */
|
|
9334
9334
|
initOptsToggles();
|
|
9335
9335
|
loadAgent();
|
|
9336
|
-
`;function
|
|
9337
|
-
`);return
|
|
9338
|
-
`);return
|
|
9336
|
+
`;function er(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qn({agentId:a,peers:n,localToken:r}))}async function tr(t,e,a){try{let n=t.method==="GET"?void 0:await vl(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){ot(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>je(i),"PATCH ":()=>Yi(i,n),"PATCH capability":()=>el(i,n),"POST mcp":()=>Qi(i,n),"DELETE mcp":()=>Zi(i,n),"GET identity":()=>tl(i),"GET identity/file":()=>al(i,String(o.path||"")),"PUT identity/file":()=>nl(i,n),"GET skills":()=>rl(i),"POST skills":()=>ol(i,n),"DELETE skills":()=>sl(i,n),"GET skills/tree":()=>il(i,String(o.slug||"")),"GET skills/file":()=>ll(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>dl(i,n),"GET skills/deps":()=>cl(i,String(o.slug||"")),"POST skills/install":()=>pl(i,n,t),"POST skills/deps":()=>ul(i,n,t),"GET channels":()=>ml(i),"GET activity":()=>fl(i,t),"GET handovers":()=>hl(i),"POST handovers":()=>gl(i,n),"DELETE handovers":()=>xl(n)}[d];if(!u){ot(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();ot(e,200,f)}catch(n){ot(e,400,{error:n?.message||"agent op failed"})}}function ar(){let t=Zn(process.cwd(),"agentx.json");return Ji(t)?JSON.parse(Vi(t,"utf-8")):null}function W(t){let e=ar();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 je(t){let{def:e,cfg:a}=W(t),n=e.workspace?ke(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 Yi(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:je(t)}}function Qi(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:je(t)}}function Zi(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:je(t)}}function el(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:je(t)}}function tl(t){let{def:e}=W(t);return ke(e.workspace)}function al(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return Fe(a.workspace,e)}function nl(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return We(n.workspace,a,String(e?.content??""))}function rl(t){let{def:e}=W(t),a=ke(e.workspace);return{skills:a.skills,workspace:a.workspace}}function ol(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ge(n.workspace,a,{title:e?.title,content:e?.content})}function sl(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Xe(n.workspace,a)}function il(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=Sa(a.workspace,e),r=Ke(a.workspace,e);return{slug:e,tree:n,deps:r}}function ll(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return Ea(n.workspace,e,a)}function dl(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 Ta(r.workspace,a,n,String(e?.content??""))}function cl(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return Ke(a.workspace,e)}async function pl(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=nr(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(`
|
|
9337
|
+
`);return rr(a,r,s,`install-${n}:${Date.now()}`)}async function ul(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=nr(e?.worker),{def:o}=W(t),s=Ke(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=Zn(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(`
|
|
9338
|
+
`);return rr(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function nr(t){if(t&&typeof t=="string")return t;let e=Q();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function rr(t,e,a,n){let r=Q(),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 ml(t){let e=ar(),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 fl(t,e){try{let n=(Q().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 Nt(){return new na}function hl(t){let e=Nt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function gl(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=Nt().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 xl(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:Nt().remove(e,a,n)?"Released":"No active handover for that chat"}}function ot(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function vl(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 ye={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 or=[{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 Ht(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(ye)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
9339
9339
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
9340
9340
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
9341
9341
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
9342
9342
|
<main id="grid" class="ax-live__body"></main>
|
|
9343
9343
|
</div>
|
|
9344
|
-
`;return $({title:`${
|
|
9344
|
+
`;return $({title:`${ye.brand} \xB7 ${ye.subtitle}`,activeTab:"live",subtitle:ye.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:bl,scripts:e+`<script>${yl}</script>`,headExtras:`<script>
|
|
9345
9345
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
9346
9346
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
9347
9347
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -9352,7 +9352,7 @@ loadAgent();
|
|
|
9352
9352
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
9353
9353
|
right.insertBefore(extras, right.firstChild);
|
|
9354
9354
|
});
|
|
9355
|
-
</script>`})}var
|
|
9355
|
+
</script>`})}var bl=`
|
|
9356
9356
|
/* --- Page frame --- */
|
|
9357
9357
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
9358
9358
|
|
|
@@ -9559,7 +9559,7 @@ loadAgent();
|
|
|
9559
9559
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
9560
9560
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
9561
9561
|
}
|
|
9562
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
9562
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,yl=`
|
|
9563
9563
|
'use strict';
|
|
9564
9564
|
|
|
9565
9565
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -10130,7 +10130,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10130
10130
|
});
|
|
10131
10131
|
}
|
|
10132
10132
|
|
|
10133
|
-
`;var
|
|
10133
|
+
`;var sr=`
|
|
10134
10134
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
10135
10135
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
10136
10136
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -10304,7 +10304,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10304
10304
|
.mx-summary{max-width:56vw}
|
|
10305
10305
|
}
|
|
10306
10306
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
10307
|
-
`;var
|
|
10307
|
+
`;var ir=`<script>
|
|
10308
10308
|
window.MX=(function(){
|
|
10309
10309
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
10310
10310
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -10413,7 +10413,7 @@ window.MX=(function(){
|
|
|
10413
10413
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
10414
10414
|
setHealth:setHealth,get:get};
|
|
10415
10415
|
})();
|
|
10416
|
-
</script>`;var
|
|
10416
|
+
</script>`;var lr=`<script>
|
|
10417
10417
|
window.MXD=(function(){
|
|
10418
10418
|
function el(id){return document.getElementById(id)}
|
|
10419
10419
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -10627,7 +10627,7 @@ window.MXD=(function(){
|
|
|
10627
10627
|
|
|
10628
10628
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
10629
10629
|
})();
|
|
10630
|
-
</script>`;var
|
|
10630
|
+
</script>`;var dr=`<script>
|
|
10631
10631
|
(function(){
|
|
10632
10632
|
var LANES=[
|
|
10633
10633
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -10943,7 +10943,7 @@ window.MXD=(function(){
|
|
|
10943
10943
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
10944
10944
|
load();
|
|
10945
10945
|
})();
|
|
10946
|
-
</script>`;var
|
|
10946
|
+
</script>`;var cr=`<script>
|
|
10947
10947
|
(function(){
|
|
10948
10948
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
10949
10949
|
var esc=MX.esc;
|
|
@@ -11121,7 +11121,7 @@ window.MXD=(function(){
|
|
|
11121
11121
|
}
|
|
11122
11122
|
load();setInterval(load,5000);
|
|
11123
11123
|
})();
|
|
11124
|
-
</script>`;var
|
|
11124
|
+
</script>`;var pr=`
|
|
11125
11125
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
11126
11126
|
.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}
|
|
11127
11127
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -11162,7 +11162,7 @@ window.MXD=(function(){
|
|
|
11162
11162
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
11163
11163
|
.mx-rt-name{max-width:100%}
|
|
11164
11164
|
}
|
|
11165
|
-
`,
|
|
11165
|
+
`,ur=`<script>
|
|
11166
11166
|
(function(){
|
|
11167
11167
|
var root=document.getElementById('mx-routines');
|
|
11168
11168
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -11289,7 +11289,7 @@ window.MXD=(function(){
|
|
|
11289
11289
|
syncBar();
|
|
11290
11290
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
11291
11291
|
})();
|
|
11292
|
-
</script>`;var
|
|
11292
|
+
</script>`;var mr=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],fr=`<script>
|
|
11293
11293
|
(function(){
|
|
11294
11294
|
var root=document.getElementById('mx-feed');
|
|
11295
11295
|
if(!root)return;
|
|
@@ -11364,12 +11364,12 @@ window.MXD=(function(){
|
|
|
11364
11364
|
}
|
|
11365
11365
|
load();setInterval(load,5000);
|
|
11366
11366
|
})();
|
|
11367
|
-
</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
|
|
11367
|
+
</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 wl=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],kl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],_l=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function hr(t){let e=Je({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Ve([{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">
|
|
11368
11368
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
11369
|
-
${
|
|
11369
|
+
${kl.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("")}
|
|
11370
11370
|
</div>
|
|
11371
11371
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
11372
|
-
${
|
|
11372
|
+
${_l.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
11373
11373
|
</div>
|
|
11374
11374
|
</div>
|
|
11375
11375
|
<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">
|
|
@@ -11422,7 +11422,7 @@ window.MXD=(function(){
|
|
|
11422
11422
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
11423
11423
|
${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>')}
|
|
11424
11424
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
11425
|
-
${
|
|
11425
|
+
${wl.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11426
11426
|
</div>
|
|
11427
11427
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
11428
11428
|
</section>
|
|
@@ -11430,7 +11430,7 @@ window.MXD=(function(){
|
|
|
11430
11430
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
11431
11431
|
${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>')}
|
|
11432
11432
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
11433
|
-
${
|
|
11433
|
+
${mr.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
11434
11434
|
</div>
|
|
11435
11435
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
11436
11436
|
</section>
|
|
@@ -11463,7 +11463,7 @@ window.MXD=(function(){
|
|
|
11463
11463
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
11464
11464
|
</header>
|
|
11465
11465
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
11466
|
-
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
11466
|
+
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:sr+pr,scripts:ir+Sl+lr+dr+ur+cr+fr})}var Sl=`<script>
|
|
11467
11467
|
(function(){
|
|
11468
11468
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
11469
11469
|
var range=document.getElementById('mx-range');
|
|
@@ -11491,7 +11491,7 @@ window.MXD=(function(){
|
|
|
11491
11491
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
11492
11492
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
11493
11493
|
})();
|
|
11494
|
-
</script>`;async function
|
|
11494
|
+
</script>`;async function gr(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 El(s,e.days)}function El(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,b=0,w=0;for(let{node:h,data:E}of t)if(E){a.runs+=E.totals.runs,a.errors+=E.totals.errors,a.hours+=E.totals.hours,a.agents+=E.totals.agents,a.threads+=E.totals.threads;for(let c of E.days){let m=n.get(c.day)||{day:c.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let g of["cron","workflow","direct"])m[g][0]+=c[g]?.[0]||0,m[g][1]+=c[g]?.[1]||0;n.set(c.day,m)}for(let c of E.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 E.causes){let m=o.get(c.cause)||{cause:c.cause,count:0,agents:[],example:""};m.count+=c.count;for(let g of c.agents)m.agents.includes(g)||m.agents.push(g);m.example||(m.example=c.example),o.set(c.cause,m)}for(let c of E.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=E.rotations.total,p+=E.rotations.tokenSum||0,u+=E.rotations.tokenSamples||0,f=Math.max(f,E.rotations.maxTokens),b+=E.retention.traces,w+=E.retention.tracesWithSteps;for(let c of E.jobs)i.push({...c,node:h.name,nodeUrl:h.url});for(let c of E.threads)l.push({...c,node:h.name,nodeUrl:h.url})}let T=t.filter(h=>h.data).map(h=>h.data.since).filter(h=>Number.isFinite(h));return{generatedAt:Date.now(),windowDays:e,since:T.length?Math.min(...T):Date.now()-e*864e5,nodes:t.map(h=>({name:h.node.name,url:h.node.url,ok:!!h.data,error:h.error,runs:h.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((h,E)=>h.day.localeCompare(E.day)),origins:[...r.values()].map(h=>({...h,hours:Math.round(h.hours*100)/100})).sort((h,E)=>E.runs-h.runs),causes:[...o.values()].sort((h,E)=>E.count-h.count),jobs:i.sort((h,E)=>E.hours-h.hours),threads:l.sort((h,E)=>E.lastAt-E.firstAt-(h.lastAt-h.firstAt)||E.runs-h.runs),rotations:{total:d,byReason:[...s.entries()].map(([h,E])=>({reason:h,count:E})).sort((h,E)=>E.count-h.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:b,tracesWithSteps:w}}}async function xr(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 vr(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 Tl(s,e.day)}function Tl(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 br(t={}){let e=`
|
|
11495
11495
|
<select id="boardPicker" title="Switch board"></select>
|
|
11496
11496
|
<div class="search">
|
|
11497
11497
|
<span class="icon">\u2315</span>
|
|
@@ -11592,7 +11592,7 @@ window.MXD=(function(){
|
|
|
11592
11592
|
</footer>
|
|
11593
11593
|
</div>
|
|
11594
11594
|
</div>
|
|
11595
|
-
<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:
|
|
11595
|
+
<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:Cl,scripts:`<script>${Al}</script>`,headExtras:`<script>
|
|
11596
11596
|
// The boards page has its own connection dot + wants body height:100%
|
|
11597
11597
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
11598
11598
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -11608,7 +11608,7 @@ window.MXD=(function(){
|
|
|
11608
11608
|
right.insertBefore(dot, right.firstChild);
|
|
11609
11609
|
}
|
|
11610
11610
|
});
|
|
11611
|
-
</script>`})}var
|
|
11611
|
+
</script>`})}var Cl=`
|
|
11612
11612
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
11613
11613
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
11614
11614
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -11861,7 +11861,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
11861
11861
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
11862
11862
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
11863
11863
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
11864
|
-
`,
|
|
11864
|
+
`,Al=`
|
|
11865
11865
|
'use strict';
|
|
11866
11866
|
const state = {
|
|
11867
11867
|
boards: [], current: null, items: {},
|
|
@@ -12914,9 +12914,9 @@ function appendEvents(events) {
|
|
|
12914
12914
|
}
|
|
12915
12915
|
|
|
12916
12916
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
12917
|
-
`;function
|
|
12917
|
+
`;function yr(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
12918
12918
|
<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>
|
|
12919
|
-
${
|
|
12919
|
+
${or.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:`${ye.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ml})}var Ml=`
|
|
12920
12920
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
12921
12921
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
12922
12922
|
.lead {
|
|
@@ -12946,7 +12946,7 @@ article.term .alias {
|
|
|
12946
12946
|
}
|
|
12947
12947
|
article.term p {
|
|
12948
12948
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
12949
|
-
}`;function
|
|
12949
|
+
}`;function wr(t={}){let e=`<div class="ax-wf__root">
|
|
12950
12950
|
<aside class="ax-wf__list">
|
|
12951
12951
|
<header>
|
|
12952
12952
|
<h2>Workflows</h2>
|
|
@@ -13023,7 +13023,7 @@ article.term p {
|
|
|
13023
13023
|
</aside>
|
|
13024
13024
|
</div>
|
|
13025
13025
|
|
|
13026
|
-
<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:
|
|
13026
|
+
<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:Il,scripts:`<script>${me({workflowHealth:da})}${$l}</script>`})}var Il=`
|
|
13027
13027
|
.ax-wf__root {
|
|
13028
13028
|
display: grid;
|
|
13029
13029
|
grid-template-columns: 340px 1fr;
|
|
@@ -13407,7 +13407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13407
13407
|
font-size: 12px; z-index: 50;
|
|
13408
13408
|
}
|
|
13409
13409
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
13410
|
-
|
|
13410
|
+
`,$l=`
|
|
13411
13411
|
(() => {
|
|
13412
13412
|
const $ = (sel) => document.querySelector(sel)
|
|
13413
13413
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -14196,7 +14196,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14196
14196
|
setInterval(refresh, 15000)
|
|
14197
14197
|
})
|
|
14198
14198
|
})();
|
|
14199
|
-
`;function
|
|
14199
|
+
`;function kr(t={}){let e=`<div class="ax-proc__root">
|
|
14200
14200
|
<header class="ax-proc__header">
|
|
14201
14201
|
<h1>Procedures</h1>
|
|
14202
14202
|
<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>
|
|
@@ -14240,7 +14240,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14240
14240
|
<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>
|
|
14241
14241
|
<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>
|
|
14242
14242
|
</section>
|
|
14243
|
-
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
14243
|
+
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ll,scripts:`<script>${Rl}</script>`})}var Ll=`
|
|
14244
14244
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
14245
14245
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
14246
14246
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -14266,7 +14266,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14266
14266
|
.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); }
|
|
14267
14267
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
14268
14268
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
14269
|
-
`,
|
|
14269
|
+
`,Rl=`
|
|
14270
14270
|
(function(){
|
|
14271
14271
|
function $(sel){ return document.querySelector(sel) }
|
|
14272
14272
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -14366,7 +14366,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14366
14366
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
14367
14367
|
else bootAll()
|
|
14368
14368
|
})();
|
|
14369
|
-
`;function
|
|
14369
|
+
`;function _r(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
14370
14370
|
data-task-id="${P(t.taskId)}"
|
|
14371
14371
|
data-agent-id="${P(t.agentId)}"
|
|
14372
14372
|
data-node-url="${P(t.nodeUrl)}"
|
|
@@ -14409,7 +14409,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14409
14409
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
14410
14410
|
</div>
|
|
14411
14411
|
</footer>
|
|
14412
|
-
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14412
|
+
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:jl,scripts:`<script>${Pl}</script>`})}var jl=`
|
|
14413
14413
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
14414
14414
|
the sticky topbar. Breathe. */
|
|
14415
14415
|
.ax-task-page {
|
|
@@ -14551,7 +14551,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14551
14551
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
14552
14552
|
}
|
|
14553
14553
|
|
|
14554
|
-
`,
|
|
14554
|
+
`,Pl=`
|
|
14555
14555
|
(function () {
|
|
14556
14556
|
var root = document.querySelector('.ax-task-page');
|
|
14557
14557
|
if (!root) return;
|
|
@@ -14936,7 +14936,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14936
14936
|
});
|
|
14937
14937
|
|
|
14938
14938
|
})();
|
|
14939
|
-
`;function
|
|
14939
|
+
`;function Sr(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
14940
14940
|
data-agent-id="${P(t.agentId)}"
|
|
14941
14941
|
data-agent-name="${P(e)}"
|
|
14942
14942
|
data-node-url="${P(t.nodeUrl)}">
|
|
@@ -14965,7 +14965,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14965
14965
|
<div class="ax-history__list" id="hist-list">
|
|
14966
14966
|
<div class="ax-history__empty">loading\u2026</div>
|
|
14967
14967
|
</div>
|
|
14968
|
-
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14968
|
+
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ol,scripts:`<script>${Dl}</script>`})}var Ol=`
|
|
14969
14969
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
14970
14970
|
flush against the sticky topbar. */
|
|
14971
14971
|
.ax-history {
|
|
@@ -15017,7 +15017,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15017
15017
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
15018
15018
|
}
|
|
15019
15019
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
15020
|
-
`,
|
|
15020
|
+
`,Dl=`
|
|
15021
15021
|
(function () {
|
|
15022
15022
|
var root = document.querySelector('.ax-history');
|
|
15023
15023
|
if (!root) return;
|
|
@@ -15117,24 +15117,24 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15117
15117
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
15118
15118
|
});
|
|
15119
15119
|
})();
|
|
15120
|
-
`;function
|
|
15120
|
+
`;function Tr(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 Te(t,e,l=>Er(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Hl(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?Te(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"])?Te(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"])?Te(t,e,l=>{let d=ht.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=gt(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 Te(t,e,p=>Er(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 Nl=["mesh"];function Er(t,e,a,n){let r=ht.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=gt(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 Nl)!(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 Hl(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(b=>({id:b.id,workflowId:b.workflowId,workflowVersion:b.workflowVersion,homeNode:b.homeNode,status:b.status,pending:b.pending,entityRef:b.entityRef,history:(b.history||[]).slice(-5),parentRunId:b.parentRunId,parentNodeId:b.parentNodeId,rootRunId:b.rootRunId,depth:b.depth,createdAt:b.createdAt,updatedAt:b.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 Te(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 Bl(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 Bl(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)}
|
|
15121
15121
|
|
|
15122
15122
|
`);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)}
|
|
15123
15123
|
|
|
15124
|
-
`)}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
|
|
15124
|
+
`)}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 Te(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 zl}from"zlib";var ql=[41,121,255],Ul=[255,255,255],Cr=new Map;function zt(t){let e=Cr.get(t);return e||(e=Wl(t,Fl(t)),Cr.set(t,e)),e}function Fl(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?Ul:ql;a.set(d,o*e+1+s*3)}return a}function Wl(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]),Bt("IHDR",a),Bt("IDAT",zl(e)),Bt("IEND",Buffer.alloc(0))])}function Bt(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(Xl(n)),Buffer.concat([a,n,r])}var Gl=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 Xl(t){let e=4294967295;for(let a of t)e=Gl[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function st(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 Kl(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:st(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:st(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:st(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Jl(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:st(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Vl=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Ar(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 b=Yl(s.searchParams.get("timezone")),w=await o.snapshot({date:Ql(b),timezone:b});return a==="/api/app/activity"?se(e,200,{ts:w.ts,tasks:Jl(w.nodes)}):se(e,200,{ts:w.ts,nodes:w.nodes.map(Kl)})}if(n==="GET"&&a==="/api/app/approvals")return se(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Vl);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 we(t)}catch(b){return se(e,400,{error:b.message})}let p=Pe(d.node);if(!p)return se(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let b=Pe(d.taskId);if(!b)return se(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(b)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Pe(d.message);if(!T)return se(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 b=Pe(d.cronId);if(!b||typeof d.enabled!="boolean")return se(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(b)}/enabled`,{enabled:d.enabled})}else{let b=Pe(d.key),w=d.action;if(!b||w!=="yes"&&w!=="no"&&w!=="later")return se(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,b,w,u)}return se(e,f.status,f.body)}function Pe(t){return typeof t=="string"?t.trim():""}function Yl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Ql(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function we(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 se(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Zl=2048,Mr=/^[A-Za-z0-9_-]{8,256}$/;async function Ir(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 ie(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(b=>b.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return ie(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return ie(e,404,{error:"not found"});if(!s||l)return ie(e,503,{error:l});let d;try{d=await we(t)}catch(b){return ie(e,400,{error:b.message})}let p=ed(d.endpoint,o.allowedHosts);if(!p){let b="";try{b=new URL(String(d.endpoint)).hostname}catch{}return ie(e,400,{error:`not a known push service${b?`: ${b}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return ie(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=d.keys?.p256dh,f=d.keys?.auth;return typeof u!="string"||!Mr.test(u)||typeof f!="string"||!Mr.test(f)?ie(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?ie(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}),ie(e,200,{ok:!0}))}function ed(t,e){if(typeof t!="string"||t.length>Zl)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 ie(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var td=50;function ad(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}=ad(e),s="",i=[],l=new Map,d=(p,u,f)=>{let{cleanText:b,ui:w}=p==="done"?pa(u):{cleanText:u,ui:void 0},T=rd(w);return{status:p,text:b,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 od(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<td){let b={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(b),f.id&&l.set(String(f.id),b)}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,nd(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 nd(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 rd(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*od(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,`
|
|
15125
15125
|
`);let s;for(;(s=n.indexOf(`
|
|
15126
15126
|
|
|
15127
15127
|
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
|
|
15128
15128
|
`))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(`
|
|
15129
|
-
`))}}catch{}}}}finally{e.releaseLock()}}var
|
|
15129
|
+
`))}}catch{}}}}finally{e.releaseLock()}}var it=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}
|
|
15130
15130
|
data: ${JSON.stringify(s)}
|
|
15131
15131
|
|
|
15132
15132
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
15133
15133
|
|
|
15134
|
-
`)},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
|
|
15134
|
+
`)},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 Rr=8e3,sd=/^[A-Za-z0-9_.:-]{1,64}$/,Ce=new Map;async function jr(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 D(e,200,{nodes:await Pr(o)});let s=o.store();if(!s)return D(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return D(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 D(e,404,{error:"no such conversation"});let p=Ce.get(d.id);return D(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&&Ce.get(d.id);if(!d||!p)return D(e,404,{error:"nothing is running in this conversation"});Or(e);let{id:u,title:f,node:b,nodeName:w,agent:T,agentName:h}=d;return e.write(qt("conversation",{id:u,title:f,node:b,nodeName:w,agent:T,agentName:h})),e.write(qt("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return D(e,404,{error:"not found"});let l;try{l=await we(t,64*1024)}catch(d){return D(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=s.get(r.id,String(l.conversationId??""));if(!d)return D(e,404,{error:"no such conversation"});let p=Ce.get(d.id);return p?(p.ac.abort(),Ut(d,o,r.name),D(e,200,{stopped:!0})):await Ut(d,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await ld(e,l,r,s,o),!0}function id(t,e,a){let n=Ae(e.url),r=new Set,o=[];for(let s of t){let i=Ae(s.url),l=a.find(u=>Ae(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,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Pr(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return id(e.nodes,t.daemon,a)}async function ld(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Rr){D(t,400,{error:`message must be 1\u2013${Rr} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!sd.test(T)){D(t,400,{error:"pick an agent"});return}let h=(await Pr(r)).find(c=>c.target===w);if(!h){D(t,400,{error:`unknown node "${w}"`});return}if(!h.online){D(t,409,{error:`${h.name} is offline`});return}let E=h.agents.find(c=>c.id===T);if(!E){D(t,400,{error:`no agent "${T}" on ${h.name}`});return}s=n.create(a.id,{node:w,nodeName:h.name,agent:T,agentName:E.name},o)}if(Ce.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new it(r.orphanLimitMs??18e5);Ce.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:b}=s;Or(t),t.write(qt("conversation",{id:l,title:d,node:p,nodeName:u,agent:f,agentName:b})),i.attach(t);try{let w=await $r(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`},i.ac.signal,(T,h)=>i.broadcast(T,h));i.orphaned&&(w.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ut(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{Ce.delete(l),i.finish()}}function Or(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function qt(t,e){return`event: ${t}
|
|
15135
15135
|
data: ${JSON.stringify(e)}
|
|
15136
15136
|
|
|
15137
|
-
`}async function
|
|
15137
|
+
`}async function Ut(t,e,a){try{let n=Ae(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Ae(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ae(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 Ae(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var dd=8e3;async function Nr(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return J(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let f=String(t.headers["content-type"]||"");if(!wa(f))return J(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let b=ka(t.headers["x-audio-duration-ms"]);if(b)return J(e,413,{error:b});let w=await yt(t,bt.bytes);if(!w)return J(e,413,{error:`The recording is larger than ${bt.bytes/1024/1024} MB.`});if(!w.length)return J(e,400,{error:"The recording is empty."});let T={"Content-Type":f},h=t.headers["x-audio-duration-ms"];return typeof h=="string"&&/^\d{1,9}$/.test(h)&&(T["X-Audio-Duration-Ms"]=h),Dr(e,o.daemon,"/voice/transcribe",w,T,18e4)}let s,i=await yt(t,64*1024);if(!i)return J(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return J(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return J(e,503,{error:"The database on this computer is unavailable."});let d=l.get(r.id,String(s?.conversationId??""));if(!d)return J(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,dd):"";if(!p.trim())return J(e,400,{error:"text is required"});let u={agent:d.agent,text:p,...d.node!=="local"?{peer:d.node}:{}};return Dr(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(u)),{"Content-Type":"application/json"},9e4)}async function Dr(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(cd(l)?.endpoints)?J(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return J(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function cd(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}var pd={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},lt=class{constructor(e=pd,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},ud="That code didn't work. Check it, or run agentx app pair for a new one.",md=400;async function Hr(t,e){let a=Date.now(),n=e.log??(d=>console.log(d)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await we(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await fd(a,e.minMs??md),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:ud}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function fd(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}var Br=`
|
|
15138
15138
|
(function () {
|
|
15139
15139
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
15140
15140
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -15378,7 +15378,7 @@ data: ${JSON.stringify(e)}
|
|
|
15378
15378
|
setInterval(refresh, 15000);
|
|
15379
15379
|
refresh();
|
|
15380
15380
|
})();
|
|
15381
|
-
`;var
|
|
15381
|
+
`;var zr=`
|
|
15382
15382
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
15383
15383
|
.fx-head h2 { margin: 4px 0 0; }
|
|
15384
15384
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -15435,7 +15435,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15435
15435
|
}
|
|
15436
15436
|
.fx-error:empty { display: none; }
|
|
15437
15437
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
15438
|
-
`;var
|
|
15438
|
+
`;var qr=`
|
|
15439
15439
|
(function () {
|
|
15440
15440
|
var panel = document.getElementById('panel-alerts');
|
|
15441
15441
|
if (!panel) return;
|
|
@@ -15597,7 +15597,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15597
15597
|
refresh();
|
|
15598
15598
|
loadRecent();
|
|
15599
15599
|
})();
|
|
15600
|
-
`;var
|
|
15600
|
+
`;var Ur=`
|
|
15601
15601
|
(function () {
|
|
15602
15602
|
var panel = document.getElementById('panel-chat');
|
|
15603
15603
|
var V = window.AXChatView;
|
|
@@ -15628,6 +15628,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15628
15628
|
|
|
15629
15629
|
function remember(k, v) { try { if (v == null) localStorage.removeItem(k); else localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} }
|
|
15630
15630
|
function recall(k) { try { return JSON.parse(localStorage.getItem(k) || 'null'); } catch (e) { return null; } }
|
|
15631
|
+
function emit(type, detail) { document.dispatchEvent(new CustomEvent('ax-chat', { detail: Object.assign({ type: type }, detail || {}) })); }
|
|
15631
15632
|
function api(path, opts) {
|
|
15632
15633
|
return fetch(path, Object.assign({ credentials: 'same-origin' }, opts || {})).then(function (r) {
|
|
15633
15634
|
if (r.status === 401) { location.reload(); throw new Error('not paired'); }
|
|
@@ -15688,10 +15689,12 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15688
15689
|
function showTarget(t) {
|
|
15689
15690
|
pickBtn.querySelector('.cx-pick-label').textContent = t ? (t.agentName || t.agent) : 'Choose an agent';
|
|
15690
15691
|
pickBtn.querySelector('.cx-pick-sub').textContent = t ? 'on ' + t.nodeName : 'Tap to see the agents on your machines';
|
|
15692
|
+
emit('target', { target: t });
|
|
15691
15693
|
}
|
|
15692
15694
|
function useConversation(conv) {
|
|
15693
15695
|
state.conv = conv;
|
|
15694
|
-
state.target
|
|
15696
|
+
var color = state.target && state.target.agent === conv.agent ? state.target.color : undefined;
|
|
15697
|
+
state.target = { node: conv.node, nodeName: conv.nodeName, agent: conv.agent, agentName: conv.agentName, color: color };
|
|
15695
15698
|
showTarget(state.target);
|
|
15696
15699
|
remember('ax-chat-conv', conv.id);
|
|
15697
15700
|
remember('ax-chat-target', state.target);
|
|
@@ -15723,7 +15726,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15723
15726
|
var b = ev.target.closest('button[data-a]');
|
|
15724
15727
|
if (!b || !picker._data) return;
|
|
15725
15728
|
var n = picker._data[+b.getAttribute('data-n')], a = n.agents[+b.getAttribute('data-a')];
|
|
15726
|
-
state.target = { node: n.target, nodeName: n.name, agent: a.id, agentName: a.name };
|
|
15729
|
+
state.target = { node: n.target, nodeName: n.name, agent: a.id, agentName: a.name, color: a.color };
|
|
15727
15730
|
remember('ax-chat-target', state.target);
|
|
15728
15731
|
startNew();
|
|
15729
15732
|
toggle(picker, false);
|
|
@@ -15789,6 +15792,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15789
15792
|
stopBtn.hidden = !on;
|
|
15790
15793
|
newBtn.disabled = on;
|
|
15791
15794
|
log.setAttribute('aria-busy', on ? 'true' : 'false');
|
|
15795
|
+
emit('busy', { on: on });
|
|
15792
15796
|
}
|
|
15793
15797
|
function send(text) {
|
|
15794
15798
|
text = String(text || '').trim();
|
|
@@ -15827,6 +15831,8 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15827
15831
|
renderUi(el, ui);
|
|
15828
15832
|
setNote(el, note, bad);
|
|
15829
15833
|
scrollDown();
|
|
15834
|
+
// own: a turn this phone sent now, not one it came back to.
|
|
15835
|
+
emit('final', { own: !partial, ok: !note, content: content || '', conversationId: state.conv && state.conv.id });
|
|
15830
15836
|
}
|
|
15831
15837
|
setBusy(true);
|
|
15832
15838
|
scrollDown();
|
|
@@ -15880,12 +15886,14 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
15880
15886
|
newBtn.addEventListener('click', function () { startNew(); input.focus(); });
|
|
15881
15887
|
|
|
15882
15888
|
window.addEventListener('online', function () { if (state.conv && !state.busy) openConversation(state.conv.id); });
|
|
15889
|
+
window.AXChat = { send: send, busy: function () { return state.busy; }, target: function () { return state.target; },
|
|
15890
|
+
pick: function () { toggle(picker, true); loadPicker(); } };
|
|
15883
15891
|
state.target = recall('ax-chat-target');
|
|
15884
15892
|
showTarget(state.target);
|
|
15885
15893
|
var last = recall('ax-chat-conv');
|
|
15886
15894
|
if (last) openConversation(last);
|
|
15887
15895
|
})();
|
|
15888
|
-
`;var
|
|
15896
|
+
`;var Fr=`
|
|
15889
15897
|
window.AXChatView = (function () {
|
|
15890
15898
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
15891
15899
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -16046,14 +16054,14 @@ window.AXChatView = (function () {
|
|
|
16046
16054
|
return { NL: NL, esc: esc, httpUrl: httpUrl, md: md, preview: preview, setTools: setTools, renderUi: renderUi, readStream: readStream,
|
|
16047
16055
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
16048
16056
|
})();
|
|
16049
|
-
`;var
|
|
16057
|
+
`;var Wr=`
|
|
16050
16058
|
body { height: 100dvh; }
|
|
16051
16059
|
main { min-height: 0; }
|
|
16052
16060
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
16053
16061
|
.cx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
16054
16062
|
.cx { display: flex; flex-direction: column; flex: 1; gap: 10px; }
|
|
16055
16063
|
.cx-top {
|
|
16056
|
-
position: sticky; top: -16px; z-index: 1; display: grid; gap: 8px;
|
|
16064
|
+
position: sticky; top: -16px; z-index: 1; display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px;
|
|
16057
16065
|
margin: -16px 0 0; padding: 16px 0 8px; background: var(--ax-bg);
|
|
16058
16066
|
}
|
|
16059
16067
|
.cx-head { display: flex; gap: 8px; align-items: stretch; }
|
|
@@ -16129,7 +16137,465 @@ main { min-height: 0; }
|
|
|
16129
16137
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
16130
16138
|
}
|
|
16131
16139
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
16132
|
-
`;var
|
|
16140
|
+
`;var Gr=`
|
|
16141
|
+
window.AXOrb = (function () {
|
|
16142
|
+
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
16143
|
+
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
16144
|
+
var PALETTE = ['#7C3AED', '#DB2777', '#EA580C', '#0D9488', '#2563EB', '#65A30D', '#C026D3', '#0891B2'];
|
|
16145
|
+
var HEX = /^#[0-9a-fA-F]{6}$/;
|
|
16146
|
+
function colorFor(id, configured) {
|
|
16147
|
+
if (configured && HEX.test(configured)) return configured;
|
|
16148
|
+
var h = 0;
|
|
16149
|
+
Array.from(String(id || '')).forEach(function (c) { h = (h * 31 + c.charCodeAt(0)) >>> 0; });
|
|
16150
|
+
return PALETTE[h % PALETTE.length];
|
|
16151
|
+
}
|
|
16152
|
+
function hexToHsb(hex) {
|
|
16153
|
+
var v = parseInt(hex.slice(1), 16), r = (v >> 16 & 255) / 255, g = (v >> 8 & 255) / 255, b = (v & 255) / 255;
|
|
16154
|
+
var max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min, h = 0;
|
|
16155
|
+
if (d) {
|
|
16156
|
+
if (max === r) h = ((g - b) / d + 6) % 6;
|
|
16157
|
+
else if (max === g) h = (b - r) / d + 2;
|
|
16158
|
+
else h = (r - g) / d + 4;
|
|
16159
|
+
h /= 6;
|
|
16160
|
+
}
|
|
16161
|
+
return { h: h, s: max ? d / max : 0, b: max };
|
|
16162
|
+
}
|
|
16163
|
+
function hsb(h, s, b, a) {
|
|
16164
|
+
var i = Math.floor(h * 6), f = h * 6 - i, p = b * (1 - s), q = b * (1 - f * s), t = b * (1 - (1 - f) * s), rgb;
|
|
16165
|
+
rgb = [[b, t, p], [q, b, p], [p, b, t], [p, q, b], [t, p, b], [b, p, q]][((i % 6) + 6) % 6];
|
|
16166
|
+
return 'rgba(' + Math.round(rgb[0] * 255) + ',' + Math.round(rgb[1] * 255) + ',' + Math.round(rgb[2] * 255) + ',' + (a == null ? 1 : a) + ')';
|
|
16167
|
+
}
|
|
16168
|
+
function clamp(x) { return Math.min(1, Math.max(0, x)); }
|
|
16169
|
+
|
|
16170
|
+
// OrbMath: microphone RMS to 0..1, the speaking envelope, smoothing.
|
|
16171
|
+
function levelFromRms(rms) { return !(rms > 0.004) ? 0 : Math.min(1, Math.sqrt(rms - 0.004) * 3.2); }
|
|
16172
|
+
function speakingEnvelope(t) {
|
|
16173
|
+
var syllable = Math.abs(Math.sin(t * 15.7)), phrase = 0.55 + 0.45 * Math.sin(t * 1.9 + 0.7);
|
|
16174
|
+
var jitter = 0.5 + 0.5 * Math.sin(t * 37.3 + Math.sin(t * 3.1));
|
|
16175
|
+
return 0.15 + 0.85 * syllable * phrase * (0.7 + 0.3 * jitter);
|
|
16176
|
+
}
|
|
16177
|
+
function smooth(cur, target) { return target > cur ? cur + (target - cur) * 0.6 : cur + (target - cur) * 0.2; }
|
|
16178
|
+
|
|
16179
|
+
function create(canvas) {
|
|
16180
|
+
var ctx = canvas.getContext('2d');
|
|
16181
|
+
var reduce = window.matchMedia ? matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
16182
|
+
var o = { phase: 'idle', tint: PALETTE[3], level: 0, meter: null, raf: 0, last: 0 };
|
|
16183
|
+
function still() { return !!(reduce && reduce.matches); }
|
|
16184
|
+
function paused() { return still() || o.phase === 'idle' || document.hidden; }
|
|
16185
|
+
|
|
16186
|
+
function energy(t) {
|
|
16187
|
+
var s = still();
|
|
16188
|
+
if (o.phase === 'listening') return s ? 0.45 : 0.12 + 0.88 * o.level;
|
|
16189
|
+
if (o.phase === 'thinking') return s ? 0.2 : 0.22 + 0.08 * Math.sin(t * 2.2);
|
|
16190
|
+
if (o.phase === 'speaking') return s ? 0.7 : o.meter ? 0.15 + 0.85 * o.level : speakingEnvelope(t);
|
|
16191
|
+
return 0;
|
|
16192
|
+
}
|
|
16193
|
+
function speed() {
|
|
16194
|
+
return o.phase === 'listening' ? 0.5 + o.level * 1.5 : o.phase === 'thinking' ? 1.3 : o.phase === 'speaking' ? 0.9 : 0;
|
|
16195
|
+
}
|
|
16196
|
+
|
|
16197
|
+
function draw(t) {
|
|
16198
|
+
var dpr = window.devicePixelRatio || 1, css = canvas.clientWidth || 150;
|
|
16199
|
+
if (canvas.width !== Math.round(css * dpr)) { canvas.width = canvas.height = Math.round(css * dpr); }
|
|
16200
|
+
// The 96-point orb in a 160-point frame: room for the widest glow (74).
|
|
16201
|
+
var W = canvas.width, k = W / 160;
|
|
16202
|
+
ctx.setTransform(k, 0, 0, k, W / 2, W / 2);
|
|
16203
|
+
ctx.clearRect(-80, -80, 160, 160);
|
|
16204
|
+
var e = energy(t), sc = 0.78 + 0.22 * e, R = 48 * sc, base = hexToHsb(o.tint);
|
|
16205
|
+
var drift = o.phase === 'thinking' && !still() ? Math.sin(t * 0.8) * 0.04 : 0;
|
|
16206
|
+
function shade(dh, ds, db, a) { var h = (base.h + dh + drift) % 1; return hsb(h < 0 ? h + 1 : h, clamp(base.s + ds), clamp(base.b + db), a); }
|
|
16207
|
+
var core = 0.12 + 0.3 * e;
|
|
16208
|
+
var sh = [[0, 0, 0], [0.07, -0.05, 0.08], [-0.06, 0.05, -0.12], [0.13, -0.1, 0.02], [0.02, -0.7 * core, core]];
|
|
16209
|
+
|
|
16210
|
+
// Glow: a disc of the tint, blurred 10 + 12e points.
|
|
16211
|
+
var blur = 10 + 12 * e, gr = 48 * sc * 1.08, g = ctx.createRadialGradient(0, 0, Math.max(0, gr - blur), 0, 0, gr + blur);
|
|
16212
|
+
g.addColorStop(0, shade(0, 0, 0, 0.28 + 0.32 * e)); g.addColorStop(1, shade(0, 0, 0, 0));
|
|
16213
|
+
ctx.fillStyle = g; ctx.beginPath(); ctx.arc(0, 0, gr + blur, 0, Math.PI * 2); ctx.fill();
|
|
16214
|
+
|
|
16215
|
+
// The body: the mesh, clipped to the circle.
|
|
16216
|
+
ctx.save(); ctx.beginPath(); ctx.arc(0, 0, R, 0, Math.PI * 2); ctx.clip();
|
|
16217
|
+
ctx.fillStyle = shade(0, 0, 0); ctx.fillRect(-R, -R, 2 * R, 2 * R);
|
|
16218
|
+
var s = still() ? 0 : t * speed(), reach = 0.08 + 0.14 * e;
|
|
16219
|
+
function sway(p) { return Math.sin(s + p) * reach * 0.6; }
|
|
16220
|
+
var pts = [[0, 0, 0], [0.5 + sway(0.3), 0, 1], [1, 0, 2], [0, 0.5 + sway(1.1), 3], [1, 0.5 + sway(2.3), 1],
|
|
16221
|
+
[0, 1, 2], [0.5 + sway(3.7), 1, 3], [1, 1, 0], [0.5 + Math.cos(s * 1.3) * reach, 0.5 + Math.sin(s * 1.7) * reach, 4]];
|
|
16222
|
+
pts.forEach(function (p, i) {
|
|
16223
|
+
var x = (p[0] - 0.5) * 2 * R, y = (p[1] - 0.5) * 2 * R, rad = (i === 8 ? 0.95 : 1.05) * R, c = sh[p[2]];
|
|
16224
|
+
var bl = ctx.createRadialGradient(x, y, 0, x, y, rad);
|
|
16225
|
+
bl.addColorStop(0, shade(c[0], c[1], c[2], 1)); bl.addColorStop(1, shade(c[0], c[1], c[2], 0));
|
|
16226
|
+
ctx.fillStyle = bl; ctx.fillRect(-R, -R, 2 * R, 2 * R);
|
|
16227
|
+
});
|
|
16228
|
+
ctx.restore();
|
|
16229
|
+
|
|
16230
|
+
if (o.phase === 'thinking') {
|
|
16231
|
+
// A slow ring going round.
|
|
16232
|
+
var rot = still() ? -Math.PI / 2 : t * 3.1, rr = 48 * sc * 0.86;
|
|
16233
|
+
ctx.strokeStyle = 'rgba(255,255,255,0.75)'; ctx.lineWidth = 3.2; ctx.lineCap = 'round';
|
|
16234
|
+
ctx.beginPath(); ctx.arc(0, 0, rr, rot, rot + 0.28 * Math.PI * 2); ctx.stroke();
|
|
16235
|
+
} else {
|
|
16236
|
+
ctx.strokeStyle = 'rgba(255,255,255,' + (0.3 + 0.25 * e) + ')'; ctx.lineWidth = 1;
|
|
16237
|
+
ctx.beginPath(); ctx.arc(0, 0, R - 0.5, 0, Math.PI * 2); ctx.stroke();
|
|
16238
|
+
}
|
|
16239
|
+
}
|
|
16240
|
+
|
|
16241
|
+
function frame(now) {
|
|
16242
|
+
o.raf = 0;
|
|
16243
|
+
if (paused()) { draw(0); return; }
|
|
16244
|
+
if (now - o.last >= 32) {
|
|
16245
|
+
o.last = now;
|
|
16246
|
+
if (o.meter) o.level = smooth(o.level, levelFromRms(o.meter()));
|
|
16247
|
+
draw(now / 1000);
|
|
16248
|
+
}
|
|
16249
|
+
o.raf = requestAnimationFrame(frame);
|
|
16250
|
+
}
|
|
16251
|
+
function kick() { if (!o.raf) o.raf = requestAnimationFrame(frame); }
|
|
16252
|
+
if (reduce && reduce.addEventListener) reduce.addEventListener('change', kick);
|
|
16253
|
+
document.addEventListener('visibilitychange', kick);
|
|
16254
|
+
kick();
|
|
16255
|
+
|
|
16256
|
+
return {
|
|
16257
|
+
// phase: idle, listening, thinking or speaking. meter: a function
|
|
16258
|
+
// returning the RMS of what is heard or played, or null.
|
|
16259
|
+
show: function (phase, meter) {
|
|
16260
|
+
if (phase !== o.phase) { o.phase = phase; o.level = 0; }
|
|
16261
|
+
o.meter = meter || null;
|
|
16262
|
+
kick();
|
|
16263
|
+
},
|
|
16264
|
+
tint: function (hex) { if (hex && HEX.test(hex) && hex !== o.tint) { o.tint = hex; kick(); } },
|
|
16265
|
+
state: function () { return { phase: o.phase, tint: o.tint, still: still(), animating: !!o.raf && !paused() }; },
|
|
16266
|
+
};
|
|
16267
|
+
}
|
|
16268
|
+
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
16269
|
+
})();
|
|
16270
|
+
`;var Xr=`
|
|
16271
|
+
window.AXVoiceIO = (function () {
|
|
16272
|
+
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
16273
|
+
var ac = null, playing = null;
|
|
16274
|
+
|
|
16275
|
+
function mimeType() {
|
|
16276
|
+
if (!window.MediaRecorder) return null;
|
|
16277
|
+
if (!MediaRecorder.isTypeSupported) return '';
|
|
16278
|
+
for (var i = 0; i < TYPES.length; i++) if (MediaRecorder.isTypeSupported(TYPES[i])) return TYPES[i];
|
|
16279
|
+
return '';
|
|
16280
|
+
}
|
|
16281
|
+
function canRecord() {
|
|
16282
|
+
return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia && window.MediaRecorder && window.isSecureContext !== false);
|
|
16283
|
+
}
|
|
16284
|
+
function context() {
|
|
16285
|
+
var AC = window.AudioContext || window.webkitAudioContext;
|
|
16286
|
+
if (!ac && AC) { try { ac = new AC(); } catch (e) { ac = null; } }
|
|
16287
|
+
return ac;
|
|
16288
|
+
}
|
|
16289
|
+
// Inside a tap: wakes the AudioContext with a silent sound, and
|
|
16290
|
+
// speechSynthesis with an empty line, so both can speak later on their own.
|
|
16291
|
+
function unlock() {
|
|
16292
|
+
var c = context();
|
|
16293
|
+
if (c && c.state !== 'running') {
|
|
16294
|
+
if (c.resume) c.resume().catch(function () {});
|
|
16295
|
+
try { var src = c.createBufferSource(); src.buffer = c.createBuffer(1, 1, 22050); src.connect(c.destination); src.start(0); } catch (e) {}
|
|
16296
|
+
}
|
|
16297
|
+
if (window.speechSynthesis && !unlock.done) {
|
|
16298
|
+
unlock.done = true;
|
|
16299
|
+
try { var u = new SpeechSynthesisUtterance(''); u.volume = 0; speechSynthesis.speak(u); } catch (e) {}
|
|
16300
|
+
}
|
|
16301
|
+
}
|
|
16302
|
+
function rmsOf(an, buf) {
|
|
16303
|
+
an.getFloatTimeDomainData(buf);
|
|
16304
|
+
var sum = 0;
|
|
16305
|
+
for (var i = 0; i < buf.length; i++) sum += buf[i] * buf[i];
|
|
16306
|
+
return Math.sqrt(sum / buf.length);
|
|
16307
|
+
}
|
|
16308
|
+
function meterFor(node) {
|
|
16309
|
+
var c = context();
|
|
16310
|
+
if (!c || !c.createAnalyser) return null;
|
|
16311
|
+
var an = c.createAnalyser(); an.fftSize = 1024;
|
|
16312
|
+
node.connect(an);
|
|
16313
|
+
var buf = new Float32Array(an.fftSize);
|
|
16314
|
+
return { node: an, read: function () { return rmsOf(an, buf); } };
|
|
16315
|
+
}
|
|
16316
|
+
|
|
16317
|
+
// One recording. Resolves once the microphone is open; stop(keep) ends it
|
|
16318
|
+
// and resolves with the audio (keep) or null.
|
|
16319
|
+
function record() {
|
|
16320
|
+
var type = mimeType();
|
|
16321
|
+
return navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } }).then(function (stream) {
|
|
16322
|
+
var rec, chunks = [], started = Date.now(), src = null, meter = null;
|
|
16323
|
+
try { rec = type ? new MediaRecorder(stream, { mimeType: type }) : new MediaRecorder(stream); }
|
|
16324
|
+
catch (e) { stream.getTracks().forEach(function (t) { t.stop(); }); throw e; }
|
|
16325
|
+
rec.ondataavailable = function (ev) { if (ev.data && ev.data.size) chunks.push(ev.data); };
|
|
16326
|
+
var c = context();
|
|
16327
|
+
if (c) { try { src = c.createMediaStreamSource(stream); meter = meterFor(src); } catch (e) { meter = null; } }
|
|
16328
|
+
rec.start(250);
|
|
16329
|
+
function release() {
|
|
16330
|
+
stream.getTracks().forEach(function (t) { t.stop(); });
|
|
16331
|
+
try { if (src) src.disconnect(); } catch (e) {}
|
|
16332
|
+
}
|
|
16333
|
+
return {
|
|
16334
|
+
level: meter ? meter.read : null,
|
|
16335
|
+
stop: function (keep) {
|
|
16336
|
+
return new Promise(function (done) {
|
|
16337
|
+
var ms = Date.now() - started;
|
|
16338
|
+
rec.onstop = function () {
|
|
16339
|
+
release();
|
|
16340
|
+
var blobType = (rec.mimeType || type || 'audio/webm').split(';')[0];
|
|
16341
|
+
done(keep && chunks.length ? { blob: new Blob(chunks, { type: blobType }), ms: ms } : null);
|
|
16342
|
+
};
|
|
16343
|
+
try { rec.state === 'inactive' ? rec.onstop() : rec.stop(); } catch (e) { release(); done(null); }
|
|
16344
|
+
});
|
|
16345
|
+
},
|
|
16346
|
+
};
|
|
16347
|
+
});
|
|
16348
|
+
}
|
|
16349
|
+
|
|
16350
|
+
// Plays mp3 bytes through the AudioContext. Resolves when it ends or is
|
|
16351
|
+
// stopped. onStart gets a meter for the orb.
|
|
16352
|
+
function playAudio(bytes, onStart) {
|
|
16353
|
+
var c = context();
|
|
16354
|
+
if (!c) return Promise.reject(new Error('no audio'));
|
|
16355
|
+
if (c.state === 'suspended' && c.resume) c.resume().catch(function () {});
|
|
16356
|
+
return new Promise(function (resolve, reject) {
|
|
16357
|
+
c.decodeAudioData(bytes, function (buffer) {
|
|
16358
|
+
var src = c.createBufferSource(), meter = meterFor(src);
|
|
16359
|
+
src.buffer = buffer;
|
|
16360
|
+
(meter ? meter.node : src).connect(c.destination);
|
|
16361
|
+
src.onended = function () { if (playing && playing.src === src) playing = null; resolve(); };
|
|
16362
|
+
playing = { src: src, stop: function () { try { src.stop(); } catch (e) { resolve(); } } };
|
|
16363
|
+
src.start(0);
|
|
16364
|
+
onStart(meter ? meter.read : null);
|
|
16365
|
+
}, function () { reject(new Error('could not decode')); });
|
|
16366
|
+
});
|
|
16367
|
+
}
|
|
16368
|
+
// The phone's own voice, for an agent with no ElevenLabs voice.
|
|
16369
|
+
function speakText(text, onStart) {
|
|
16370
|
+
if (!window.speechSynthesis) return Promise.reject(new Error('no speech'));
|
|
16371
|
+
return new Promise(function (resolve) {
|
|
16372
|
+
var u = new SpeechSynthesisUtterance(text);
|
|
16373
|
+
u.onend = u.onerror = function () { if (playing && playing.u === u) playing = null; resolve(); };
|
|
16374
|
+
if (speechSynthesis.speaking) speechSynthesis.cancel();
|
|
16375
|
+
playing = { u: u, stop: function () { speechSynthesis.cancel(); resolve(); } };
|
|
16376
|
+
speechSynthesis.speak(u);
|
|
16377
|
+
onStart(null);
|
|
16378
|
+
});
|
|
16379
|
+
}
|
|
16380
|
+
function stopPlaying() { var p = playing; playing = null; if (p) p.stop(); }
|
|
16381
|
+
|
|
16382
|
+
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
16383
|
+
})();
|
|
16384
|
+
`;var Kr=`
|
|
16385
|
+
(function () {
|
|
16386
|
+
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
16387
|
+
if (!panel || !C || !IO || !O) return;
|
|
16388
|
+
var cx = panel.querySelector('.cx'), input = document.getElementById('cx-input'), empty = document.getElementById('cx-empty');
|
|
16389
|
+
var MAX_MS = 120000, MIN_MS = 350;
|
|
16390
|
+
var KEYS = '<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="2.5" y="6" width="19" height="12" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M6 10h1M9.5 10h1M13 10h1M16.5 10h1M8 14h8" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>';
|
|
16391
|
+
var SPK = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 9.5h3.5L12 5.5v13l-4.5-4H4z" fill="currentColor"/><path class="vx-waves" d="M15.5 9a4 4 0 0 1 0 6M18 6.5a7.5 7.5 0 0 1 0 11" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path class="vx-mute" d="M16 9.5l5 5M21 9.5l-5 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>';
|
|
16392
|
+
var bar = document.createElement('div');
|
|
16393
|
+
bar.className = 'vx';
|
|
16394
|
+
bar.innerHTML = '<p id="vx-status" class="vx-status" role="status" aria-live="polite"></p><div class="vx-row">' +
|
|
16395
|
+
'<button type="button" id="vx-keys" class="vx-side" aria-pressed="false" aria-label="Type a message">' + KEYS + '</button>' +
|
|
16396
|
+
'<button type="button" id="vx-orb" class="vx-orb" aria-describedby="vx-status"><canvas aria-hidden="true"></canvas><span class="cx-sr">Hold to talk</span></button>' +
|
|
16397
|
+
'<button type="button" id="vx-speaker" class="vx-side" aria-pressed="true" aria-label="Speak answers aloud">' + SPK + '</button></div>';
|
|
16398
|
+
cx.appendChild(bar);
|
|
16399
|
+
// The text box and Stop move into the bar, above the orb.
|
|
16400
|
+
bar.insertBefore(document.getElementById('cx-form'), bar.firstChild);
|
|
16401
|
+
var status = document.getElementById('vx-status'), orbBtn = document.getElementById('vx-orb');
|
|
16402
|
+
var keysBtn = document.getElementById('vx-keys'), spkBtn = document.getElementById('vx-speaker');
|
|
16403
|
+
var orb = O.create(orbBtn.querySelector('canvas'));
|
|
16404
|
+
empty.textContent = 'Pick an agent, then hold the orb and speak. Let go to send. Its answer appears here, and is read out when it is done.';
|
|
16405
|
+
|
|
16406
|
+
function recall(k, d) { try { var v = localStorage.getItem(k); return v == null ? d : v === '1'; } catch (e) { return d; } }
|
|
16407
|
+
function remember(k, on) { try { localStorage.setItem(k, on ? '1' : '0'); } catch (e) {} }
|
|
16408
|
+
var v = { state: 'idle', rec: null, pressed: false, cancel: false, t0: 0, timer: 0, speakOn: recall('ax-voice-speaker', true), typing: recall('ax-voice-typing', false) };
|
|
16409
|
+
|
|
16410
|
+
var TEXT = {
|
|
16411
|
+
idle: 'Hold to talk', arming: 'Opening the microphone\u2026', listening: 'Listening\u2026 let go to send, slide away to cancel',
|
|
16412
|
+
cancel: 'Let go to cancel', sending: 'Writing down what you said\u2026', thinking: 'Thinking\u2026', speaking: 'Speaking. Tap the orb to stop.',
|
|
16413
|
+
};
|
|
16414
|
+
var PHASE = { idle: 'idle', arming: 'listening', listening: 'listening', cancel: 'listening', sending: 'thinking', thinking: 'thinking', speaking: 'speaking' };
|
|
16415
|
+
// Every state change goes through here; tests and screenshots drive it too.
|
|
16416
|
+
function show(state, msg, bad, meter) {
|
|
16417
|
+
v.state = state;
|
|
16418
|
+
orb.show(PHASE[state] || 'idle', meter);
|
|
16419
|
+
bar.setAttribute('data-state', state);
|
|
16420
|
+
status.textContent = msg || (state === 'idle' && !C.target() ? 'Choose an agent, then hold to talk' : TEXT[state] || '');
|
|
16421
|
+
status.classList.toggle('vx-bad', !!bad);
|
|
16422
|
+
orbBtn.querySelector('.cx-sr').textContent = state === 'speaking' ? 'Stop speaking' : 'Hold to talk';
|
|
16423
|
+
}
|
|
16424
|
+
function idle(msg, bad) { show(C.busy() ? 'thinking' : 'idle', msg, bad); }
|
|
16425
|
+
function tint() { var t = C.target(); orb.tint(O.colorFor(t && t.agent, t && t.color)); }
|
|
16426
|
+
function buzz(ms) { try { if (navigator.vibrate) navigator.vibrate(ms); } catch (e) {} }
|
|
16427
|
+
|
|
16428
|
+
// --- Typing and the speaker ---
|
|
16429
|
+
function setTyping(on, focus) {
|
|
16430
|
+
v.typing = on; remember('ax-voice-typing', on);
|
|
16431
|
+
cx.classList.toggle('cx-typing-on', on);
|
|
16432
|
+
keysBtn.setAttribute('aria-pressed', on ? 'true' : 'false');
|
|
16433
|
+
keysBtn.setAttribute('aria-label', on ? 'Hide the keyboard' : 'Type a message');
|
|
16434
|
+
if (on && focus) input.focus();
|
|
16435
|
+
}
|
|
16436
|
+
function setSpeaker(on) {
|
|
16437
|
+
v.speakOn = on; remember('ax-voice-speaker', on);
|
|
16438
|
+
spkBtn.setAttribute('aria-pressed', on ? 'true' : 'false');
|
|
16439
|
+
spkBtn.setAttribute('aria-label', on ? 'Answers are read aloud. Tap to turn off.' : 'Answers are not read aloud. Tap to turn on.');
|
|
16440
|
+
spkBtn.classList.toggle('vx-off', !on);
|
|
16441
|
+
if (!on && v.state === 'speaking') stopSpeaking();
|
|
16442
|
+
}
|
|
16443
|
+
keysBtn.addEventListener('click', function () { setTyping(!v.typing, true); });
|
|
16444
|
+
spkBtn.addEventListener('click', function () { IO.unlock(); setSpeaker(!v.speakOn); });
|
|
16445
|
+
|
|
16446
|
+
// --- Hold to talk ---
|
|
16447
|
+
function press() {
|
|
16448
|
+
IO.unlock();
|
|
16449
|
+
if (v.state === 'speaking') { stopSpeaking(); return; }
|
|
16450
|
+
if (v.state === 'arming' || v.state === 'listening' || v.state === 'sending') return;
|
|
16451
|
+
if (!C.target()) { C.pick(); show('idle', 'Choose an agent first, then hold the orb to talk.'); return; }
|
|
16452
|
+
if (!IO.canRecord()) { show('idle', 'This browser can\u2019t record here. Tap the keyboard to type.', true); return; }
|
|
16453
|
+
v.pressed = true; v.cancel = false;
|
|
16454
|
+
show('arming');
|
|
16455
|
+
IO.record().then(function (rec) {
|
|
16456
|
+
if (!v.pressed) { rec.stop(false); idle('Hold the orb while you speak, then let go.'); return; }
|
|
16457
|
+
v.rec = rec; v.t0 = Date.now();
|
|
16458
|
+
buzz(12);
|
|
16459
|
+
show('listening', null, false, rec.level);
|
|
16460
|
+
v.timer = setTimeout(function () { release(true); }, MAX_MS);
|
|
16461
|
+
}).catch(function (e) {
|
|
16462
|
+
v.pressed = false;
|
|
16463
|
+
var denied = e && (e.name === 'NotAllowedError' || e.name === 'SecurityError');
|
|
16464
|
+
idle(denied ? 'The microphone is blocked. Allow it for this app in the phone\u2019s settings, or tap the keyboard to type.'
|
|
16465
|
+
: 'Could not open the microphone. Tap the keyboard to type.', true);
|
|
16466
|
+
});
|
|
16467
|
+
}
|
|
16468
|
+
function release(auto) {
|
|
16469
|
+
v.pressed = false;
|
|
16470
|
+
clearTimeout(v.timer);
|
|
16471
|
+
var rec = v.rec; v.rec = null;
|
|
16472
|
+
if (!rec) return;
|
|
16473
|
+
var keep = !v.cancel && (auto || Date.now() - v.t0 >= MIN_MS);
|
|
16474
|
+
rec.stop(keep).then(function (take) {
|
|
16475
|
+
if (!take) { buzz(8); idle(v.cancel ? 'Cancelled.' : 'Hold the orb while you speak, then let go.'); return; }
|
|
16476
|
+
buzz([10, 40, 10]);
|
|
16477
|
+
transcribe(take);
|
|
16478
|
+
});
|
|
16479
|
+
}
|
|
16480
|
+
function transcribe(take) {
|
|
16481
|
+
show('sending');
|
|
16482
|
+
fetch('/api/app/voice/transcribe', {
|
|
16483
|
+
method: 'POST', credentials: 'same-origin', body: take.blob,
|
|
16484
|
+
headers: { 'Content-Type': take.blob.type || 'audio/webm', 'X-Audio-Duration-Ms': String(take.ms) },
|
|
16485
|
+
}).then(function (r) {
|
|
16486
|
+
if (r.status === 401) { location.reload(); return null; }
|
|
16487
|
+
return r.json().catch(function () { return {}; }).then(function (j) { return { ok: r.ok, status: r.status, j: j }; });
|
|
16488
|
+
}).then(function (x) {
|
|
16489
|
+
if (!x) return;
|
|
16490
|
+
if (x.ok && x.j.text) { C.send(x.j.text); idle(); return; }
|
|
16491
|
+
if (x.status === 503 && x.j.hint) { idle(x.j.error + ' ' + x.j.hint + ' You can type instead.', true); setTyping(true, false); return; }
|
|
16492
|
+
idle(x.j.error || ('Speech to text failed (HTTP ' + x.status + ').'), true);
|
|
16493
|
+
}).catch(function () { idle('Could not reach AgentX. Check the connection and try again.', true); });
|
|
16494
|
+
}
|
|
16495
|
+
function inside(ev) {
|
|
16496
|
+
var r = orbBtn.getBoundingClientRect(), slack = 48;
|
|
16497
|
+
return ev.clientX > r.left - slack && ev.clientX < r.right + slack && ev.clientY > r.top - slack && ev.clientY < r.bottom + slack;
|
|
16498
|
+
}
|
|
16499
|
+
orbBtn.addEventListener('pointerdown', function (ev) {
|
|
16500
|
+
if (ev.button > 0) return;
|
|
16501
|
+
ev.preventDefault();
|
|
16502
|
+
try { orbBtn.setPointerCapture(ev.pointerId); } catch (e) {}
|
|
16503
|
+
press();
|
|
16504
|
+
});
|
|
16505
|
+
orbBtn.addEventListener('pointermove', function (ev) {
|
|
16506
|
+
if (v.state !== 'listening' && v.state !== 'cancel') return;
|
|
16507
|
+
var off = !inside(ev);
|
|
16508
|
+
if (off !== v.cancel) { v.cancel = off; buzz(6); show(off ? 'cancel' : 'listening', null, false, v.rec && v.rec.level); }
|
|
16509
|
+
});
|
|
16510
|
+
orbBtn.addEventListener('pointerup', function () { if (v.pressed || v.rec) release(false); });
|
|
16511
|
+
orbBtn.addEventListener('pointercancel', function () { v.cancel = true; if (v.pressed || v.rec) release(false); });
|
|
16512
|
+
orbBtn.addEventListener('contextmenu', function (ev) { ev.preventDefault(); });
|
|
16513
|
+
// Keyboard: hold Space or Enter to talk, Escape cancels.
|
|
16514
|
+
orbBtn.addEventListener('keydown', function (ev) {
|
|
16515
|
+
if ((ev.key === ' ' || ev.key === 'Enter') && !ev.repeat) { ev.preventDefault(); press(); }
|
|
16516
|
+
else if (ev.key === 'Escape' && v.rec) { v.cancel = true; release(false); }
|
|
16517
|
+
});
|
|
16518
|
+
orbBtn.addEventListener('keyup', function (ev) { if ((ev.key === ' ' || ev.key === 'Enter') && (v.pressed || v.rec)) release(false); });
|
|
16519
|
+
orbBtn.addEventListener('click', function (ev) { ev.preventDefault(); });
|
|
16520
|
+
document.addEventListener('visibilitychange', function () { if (document.hidden && v.rec) { v.cancel = true; release(false); } });
|
|
16521
|
+
|
|
16522
|
+
// --- Speaking the answer ---
|
|
16523
|
+
function stopSpeaking() { IO.stop(); idle(); }
|
|
16524
|
+
function speak(conversationId, text) {
|
|
16525
|
+
show('speaking', null, false, null);
|
|
16526
|
+
var began = function (meter) { if (v.state === 'speaking') show('speaking', null, false, meter); };
|
|
16527
|
+
var done = function () { if (v.state === 'speaking') idle(); };
|
|
16528
|
+
var fallback = function (t) { return IO.speakText(t, began).catch(function () {}); };
|
|
16529
|
+
fetch('/api/app/voice/speak', {
|
|
16530
|
+
method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' },
|
|
16531
|
+
body: JSON.stringify({ conversationId: conversationId, text: text }),
|
|
16532
|
+
}).then(function (r) {
|
|
16533
|
+
if (v.state !== 'speaking') return null;
|
|
16534
|
+
if (r.ok && (r.headers.get('content-type') || '').indexOf('audio/') === 0) {
|
|
16535
|
+
return r.arrayBuffer().then(function (buf) { return v.state === 'speaking' ? IO.playAudio(buf, began) : null; });
|
|
16536
|
+
}
|
|
16537
|
+
return r.json().catch(function () { return {}; }).then(function (j) { return j.text && v.state === 'speaking' ? fallback(j.text) : null; });
|
|
16538
|
+
}).catch(function () {}).then(done);
|
|
16539
|
+
}
|
|
16540
|
+
|
|
16541
|
+
document.addEventListener('ax-chat', function (ev) {
|
|
16542
|
+
var d = ev.detail || {};
|
|
16543
|
+
if (d.type === 'target') { tint(); if (v.state === 'idle') idle(); }
|
|
16544
|
+
else if (d.type === 'busy') {
|
|
16545
|
+
if (d.on && (v.state === 'idle' || v.state === 'sending')) show('thinking');
|
|
16546
|
+
else if (!d.on && v.state === 'thinking') idle();
|
|
16547
|
+
} else if (d.type === 'final') {
|
|
16548
|
+
// Answers to what this phone just sent, spoken or typed; not one it
|
|
16549
|
+
// came back to later.
|
|
16550
|
+
if (d.own && d.ok && d.content && d.conversationId && v.speakOn && v.state !== 'listening' && v.state !== 'cancel') speak(d.conversationId, d.content);
|
|
16551
|
+
}
|
|
16552
|
+
});
|
|
16553
|
+
// Any tap in Chat unlocks audio, so a typed message's answer can play too.
|
|
16554
|
+
panel.addEventListener('pointerdown', function () { IO.unlock(); });
|
|
16555
|
+
|
|
16556
|
+
setTyping(v.typing, false);
|
|
16557
|
+
setSpeaker(v.speakOn);
|
|
16558
|
+
tint();
|
|
16559
|
+
idle();
|
|
16560
|
+
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; } };
|
|
16561
|
+
})();
|
|
16562
|
+
`;var Jr=`
|
|
16563
|
+
.vx {
|
|
16564
|
+
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
16565
|
+
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
16566
|
+
}
|
|
16567
|
+
.vx .cx-composer { position: static; width: 100%; margin: 0; padding: 0 0 4px; background: transparent; }
|
|
16568
|
+
.cx:not(.cx-typing-on) .vx .cx-composer { justify-content: center; padding: 0; }
|
|
16569
|
+
.cx:not(.cx-typing-on) #cx-input, .cx:not(.cx-typing-on) #cx-send { display: none; }
|
|
16570
|
+
.vx-status {
|
|
16571
|
+
margin: 0; min-height: 1.5em; max-width: 34ch; text-align: center;
|
|
16572
|
+
font-size: var(--ax-fs-sm); color: var(--ax-text-2); line-height: 1.45;
|
|
16573
|
+
}
|
|
16574
|
+
.vx-status.vx-bad { color: var(--ax-red-ink); }
|
|
16575
|
+
.vx-row { display: flex; align-items: center; justify-content: center; gap: 12px; }
|
|
16576
|
+
.vx-side {
|
|
16577
|
+
width: 48px; height: 48px; display: grid; place-items: center; padding: 0; cursor: pointer;
|
|
16578
|
+
border: var(--ax-border-w) solid var(--ax-border); border-radius: 50%;
|
|
16579
|
+
background: var(--ax-surface); color: var(--ax-text-2);
|
|
16580
|
+
}
|
|
16581
|
+
.vx-side svg { width: 24px; height: 24px; }
|
|
16582
|
+
.vx-side[aria-pressed=true] { color: var(--ax-accent); border-color: color-mix(in oklch, var(--ax-accent) 50%, var(--ax-border)); }
|
|
16583
|
+
#vx-speaker .vx-mute { display: none; }
|
|
16584
|
+
#vx-speaker.vx-off { color: var(--ax-text-2); border-color: var(--ax-border); }
|
|
16585
|
+
#vx-speaker.vx-off .vx-waves { display: none; }
|
|
16586
|
+
#vx-speaker.vx-off .vx-mute { display: inline; }
|
|
16587
|
+
.vx-orb {
|
|
16588
|
+
width: 150px; height: 150px; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer;
|
|
16589
|
+
touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;
|
|
16590
|
+
transition: opacity 0.15s ease;
|
|
16591
|
+
}
|
|
16592
|
+
.vx-orb canvas { width: 100%; height: 100%; display: block; pointer-events: none; }
|
|
16593
|
+
.vx[data-state=cancel] .vx-orb { opacity: 0.4; }
|
|
16594
|
+
.vx[data-state=cancel] .vx-status { color: var(--ax-red-ink); }
|
|
16595
|
+
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
16596
|
+
.cx-typing-on .vx-row { gap: 16px; }
|
|
16597
|
+
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
16598
|
+
`;var Vr=`
|
|
16133
16599
|
<main class="card">
|
|
16134
16600
|
<h1>This phone isn't paired</h1>
|
|
16135
16601
|
<p>On the computer running AgentX, open a terminal in the folder that holds <code>agentx.json</code> and run <code>agentx app pair</code>. Type the code it shows here.</p>
|
|
@@ -16143,7 +16609,7 @@ main { min-height: 0; }
|
|
|
16143
16609
|
</form>
|
|
16144
16610
|
<p class="muted">Or scan the QR code it shows with this phone's camera. That pairs the browser; an app added to the home screen needs the code.</p>
|
|
16145
16611
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
16146
|
-
</main>`,
|
|
16612
|
+
</main>`,Yr=`
|
|
16147
16613
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
16148
16614
|
.pair-form label { font-weight: 600; }
|
|
16149
16615
|
.pair-form input {
|
|
@@ -16165,7 +16631,7 @@ main { min-height: 0; }
|
|
|
16165
16631
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
16166
16632
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
16167
16633
|
}
|
|
16168
|
-
`,
|
|
16634
|
+
`,Qr=`
|
|
16169
16635
|
(function () {
|
|
16170
16636
|
var form = document.getElementById('pair-form');
|
|
16171
16637
|
var input = document.getElementById('pair-code');
|
|
@@ -16212,7 +16678,7 @@ main { min-height: 0; }
|
|
|
16212
16678
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
16213
16679
|
}
|
|
16214
16680
|
})();
|
|
16215
|
-
`;var
|
|
16681
|
+
`;var Ft=`
|
|
16216
16682
|
var CACHE = 'agentx-app-v3';
|
|
16217
16683
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
16218
16684
|
self.addEventListener('install', function (e) {
|
|
@@ -16284,7 +16750,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
16284
16750
|
return self.clients.openWindow(target);
|
|
16285
16751
|
}));
|
|
16286
16752
|
});
|
|
16287
|
-
`;var
|
|
16753
|
+
`;var hd="<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 Wt(t){return`<meta charset="utf-8">
|
|
16288
16754
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
16289
16755
|
<meta name="theme-color" content="#2979FF">
|
|
16290
16756
|
<meta name="referrer" content="no-referrer">
|
|
@@ -16295,13 +16761,13 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
16295
16761
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
16296
16762
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
16297
16763
|
<title>${t}</title>
|
|
16298
|
-
${
|
|
16299
|
-
<style>${
|
|
16764
|
+
${hd}
|
|
16765
|
+
<style>${Ia}${vd}</style>`}var Zr=[{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 eo(){let t=Zr.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=Zr.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
16300
16766
|
<h2>${a.label}</h2>
|
|
16301
16767
|
<p class="soon">${a.soon}</p>
|
|
16302
16768
|
</section>`).join("");return`<!doctype html>
|
|
16303
16769
|
<html lang="en">
|
|
16304
|
-
<head>${
|
|
16770
|
+
<head>${Wt("AgentX")}<style>${bd}${zr}${Wr}${Jr}</style></head>
|
|
16305
16771
|
<body>
|
|
16306
16772
|
<header class="bar">
|
|
16307
16773
|
<div>
|
|
@@ -16313,28 +16779,29 @@ ${ad}
|
|
|
16313
16779
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
16314
16780
|
<main>${e}</main>
|
|
16315
16781
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
16316
|
-
<script>${
|
|
16317
|
-
<script>${
|
|
16318
|
-
<script>${
|
|
16319
|
-
<script>${
|
|
16782
|
+
<script>${gd}</script>
|
|
16783
|
+
<script>${Br}</script>
|
|
16784
|
+
<script>${qr}</script>
|
|
16785
|
+
<script>${me({markdownToHtml:$a})}${Fr}${Ur}</script>
|
|
16786
|
+
<script>${Gr}${Xr}${Kr}</script>
|
|
16320
16787
|
</body>
|
|
16321
|
-
</html>`}function
|
|
16788
|
+
</html>`}function to(){return`<!doctype html>
|
|
16322
16789
|
<html lang="en">
|
|
16323
|
-
<head>${
|
|
16790
|
+
<head>${Wt("Pair \xB7 AgentX")}</head>
|
|
16324
16791
|
<body>
|
|
16325
16792
|
<main class="card">
|
|
16326
16793
|
<h1>Pairing this phone\u2026</h1>
|
|
16327
16794
|
<p id="msg" role="status">One moment.</p>
|
|
16328
16795
|
</main>
|
|
16329
|
-
<script>${
|
|
16796
|
+
<script>${xd}</script>
|
|
16330
16797
|
</body>
|
|
16331
|
-
</html>`}function
|
|
16798
|
+
</html>`}function ao(){return`<!doctype html>
|
|
16332
16799
|
<html lang="en">
|
|
16333
|
-
<head>${
|
|
16334
|
-
<body>${
|
|
16335
|
-
<script>${
|
|
16800
|
+
<head>${Wt("Not paired \xB7 AgentX")}<style>${Yr}</style></head>
|
|
16801
|
+
<body>${Vr}
|
|
16802
|
+
<script>${Qr}</script>
|
|
16336
16803
|
</body>
|
|
16337
|
-
</html>`}function
|
|
16804
|
+
</html>`}function no(){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 gd=`
|
|
16338
16805
|
(function () {
|
|
16339
16806
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
16340
16807
|
function select(tab, focus) {
|
|
@@ -16400,7 +16867,7 @@ ${ad}
|
|
|
16400
16867
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
16401
16868
|
}
|
|
16402
16869
|
})();
|
|
16403
|
-
`,
|
|
16870
|
+
`,xd=`
|
|
16404
16871
|
(function () {
|
|
16405
16872
|
var msg = document.getElementById('msg');
|
|
16406
16873
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -16417,7 +16884,7 @@ ${ad}
|
|
|
16417
16884
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
16418
16885
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
16419
16886
|
})();
|
|
16420
|
-
`,
|
|
16887
|
+
`,vd=`
|
|
16421
16888
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
16422
16889
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
16423
16890
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -16429,7 +16896,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
16429
16896
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
16430
16897
|
.muted { color: var(--ax-text-2); }
|
|
16431
16898
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
16432
|
-
`,
|
|
16899
|
+
`,bd=`
|
|
16433
16900
|
body { display: flex; flex-direction: column; }
|
|
16434
16901
|
.bar {
|
|
16435
16902
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -16466,7 +16933,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
16466
16933
|
}
|
|
16467
16934
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
16468
16935
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
16469
|
-
`;var
|
|
16936
|
+
`;var oo="agentx_app",yd=400*86400,wd=new lt;async function so(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Z;if(n==="GET"){if(a==="/app/manifest.webmanifest")return he(e,200,"application/manifest+json",no());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),he(e,200,"text/javascript; charset=utf-8",Ft);if(a==="/app/icon-192.png")return he(e,200,"image/png",zt(192),"public, max-age=86400");if(a==="/app/icon-512.png")return he(e,200,"image/png",zt(512),"public, max-age=86400");if(a==="/app/pair")return he(e,200,"text/html; charset=utf-8",to())}if(n==="POST"&&a==="/api/app/session"){let i=Gt(Xt(t),o);return i?(e.setHeader("Set-Cookie",ro(Xt(t))),Me(e,200,{device:i.name})):Me(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Hr(t,{codes:r.pairCodes??new Ba,limiter:r.pairLimiter??wd,verify:l=>Gt(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",ro(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Me(e,i.status,i.body)}let s=Gt(kd(t),o);return s?n==="GET"&&a==="/app"?he(e,200,"text/html; charset=utf-8",eo()):n==="GET"&&a==="/api/app/me"?Me(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Ar(t,e,a,n,s.name,r.fleet)||r.push&&await Ir(t,e,a,n,s,r.push)||r.chat&&await jr(t,e,a,n,s,r.chat)||r.voice&&await Nr(t,e,a,n,s,r.voice)?!0:Me(e,404,{error:"not found"}):a==="/app"?he(e,401,"text/html; charset=utf-8",ao()):Me(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function Gt(t,e){if(!t)return null;let a=e.verify(t);return a&&xe(a,"app")?a:null}function ro(t){return`${oo}=${t}; Path=/; Max-Age=${yd}; HttpOnly; Secure; SameSite=Strict`}function kd(t){return Xt(t)??_d(t,oo)}function Xt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function _d(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function he(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Me(t,e,a){return he(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Sd}from"crypto";var Ie={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},Ed=/^c[a-z0-9]{8,32}$/;function Td(t){return Ed.test(t)}var Oe=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
16470
16937
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
16471
16938
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
16472
16939
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -16474,30 +16941,30 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
16474
16941
|
CREATE TABLE IF NOT EXISTS app_chat_messages (
|
|
16475
16942
|
id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id TEXT NOT NULL, role TEXT NOT NULL,
|
|
16476
16943
|
content TEXT NOT NULL, status TEXT, error TEXT, ui TEXT, tools TEXT, at INTEGER NOT NULL);
|
|
16477
|
-
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)}${
|
|
16478
|
-
(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(!
|
|
16944
|
+
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)}${Sd(4).toString("hex")}`,s={id:o,title:Ad(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
16945
|
+
(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(Cd);return{...io(n),messages:r}}list(e,a=Ie.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
16479
16946
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
16480
16947
|
(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
|
|
16481
|
-
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{...
|
|
16948
|
+
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{...io(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>Ie.content?n.content.slice(0,Ie.content)+`
|
|
16482
16949
|
|
|
16483
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,
|
|
16950
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,Ie.toolsPerMessage);return this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, at)
|
|
16484
16951
|
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
|
|
16485
|
-
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,
|
|
16486
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,
|
|
16487
|
-
Live dashboard: http://${
|
|
16952
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ie.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 = ?
|
|
16953
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ie.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 io(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 Cd(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 Ad(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function $f(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let b of a)try{s.set(b.id,Bd(b,t))}catch(w){console.error(` Board "${b.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?De(process.cwd(),t.workflows.dir):void 0,d=new ra(l?{baseDir:l}:void 0),p=new oa(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new sa(l?{baseDir:l}:void 0);Kn(t),ba({business:t.business?.enabled===!0}),Md(async(b,w)=>{try{await Od(b,w,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(T){y(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let b=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
16954
|
+
Live dashboard: http://${b}:${n}
|
|
16488
16955
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
16489
|
-
Kanban dashboard: http://${
|
|
16490
|
-
`),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 kd=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 _d(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(fa(t.headers)==="foreign"&&ha(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 Jr(t,e,r,o,{nodeName:a.config.node?.name,fleet:to(a.config),push:Ud(a.config),chat:Fd(a.config)}))return;if(o==="GET"&&kd.has(r)&&Da("page",r),o==="GET"&&r==="/"){let c=$a();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(Ot({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fr({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ot({peers:O(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(Ka({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({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(Ua({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,m=setTimeout(()=>c.abort(),8e3);try{let h=oa(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 ra(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(cr({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hr({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gr({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xr({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ia({}));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(vr({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: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(br({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){La(t,e);return}if(o==="POST"&&r==="/api/setup"){await ja(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ra(t,e);return}if(o==="GET"&&r==="/admin"){Za(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){un(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){sn(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}bn(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 Vd(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Rt(t,e,r,h=>no(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=Ne(M.url.replace(/\/+$/,""),a.config);if(A){await Qr(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=Ne(c,a.config);if(!m){b(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Qr(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await yn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Yd(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-YFA4ZSRH.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(En({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await _n(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Sn({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Tn({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 Md(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 Fn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Rt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Gn(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){Jn(t,e,d[1],O(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 en(t,e);return}if(r.startsWith("/api/admin/approvals")){await mn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await ln(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Vn(t,e,r);return}if(r.startsWith("/api/admin/")){await tn(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(Ja);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=Kd("web/"+c);try{let h=await Jd(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 Oe(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 Oe(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 pr(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 mr(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 ur(e,await he(a.config),c,h)}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Nd(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 Dd(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 zd(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 qd(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 Jt(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 Gd(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(!Hd(t,e,[`agent:${c}`]))return;await Bd(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 $d(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 Jt(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
|
|
16956
|
+
Kanban dashboard: http://${b}:${n}
|
|
16957
|
+
`),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 Pd=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 Od(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(xa(t.headers)==="foreign"&&va(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await so(t,e,r,o,{nodeName:a.config.node?.name,fleet:mo(a.config),push:ac(a.config),chat:nc(a.config),voice:rc(a.config)}))return;if(o==="GET"&&Pd.has(r)&&Ua("page",r),o==="GET"&&r==="/"){let c=Oa();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(Ht({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(br({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ht({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await ge(a.config);if(!c){y(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(""))}),g=await fetch(c.url+r,{method:"POST",headers:{"Content-Type":"application/json",...c.token?{Authorization:`Bearer ${c.token}`}:{}},body:m||"{}"});e.writeHead(g.status,{"Content-Type":"application/json"}),e.end(await g.text())}catch(c){y(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 ge(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),g=o==="POST"?await ue(t):void 0,x=g?.node??m,k=x?c.find(M=>M.url===x):c[0];if(!k){y(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({...g,node:void 0})}:{}});y(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(c){y(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 ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${g}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,k)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await ge(a.config);if(!c){y(e,200,{configured:!1,workflows:[]});return}let m=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});y(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Za({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qa({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(Ka({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,m=setTimeout(()=>c.abort(),8e3);try{let g=la(await ge(a.config,c.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(g.map(async A=>{try{let S=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!S.ok)throw new Error(`HTTP ${S.status}`);return{name:A.name,url:A.url,ok:!0,data:await S.json()}}catch(S){return{name:A.name,url:A.url,ok:!1,error:S.message}}}));y(e,200,{nodes:M});return}let x=g.find(M=>M.url===n.searchParams.get("node"));if(!x){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await ia(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}`}:{}}});y(e,_.status,await _.json())}catch(g){y(e,502,{error:g.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hr({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(yr({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wr({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pa({}));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(_r({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: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(Sr({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"){Da(t,e);return}if(o==="POST"&&r==="/api/setup"){await Na(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ha(t,e);return}if(o==="GET"&&r==="/admin"){rn(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){xn(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){un(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}Sn(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 cc(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Dt(t,e,r,g=>ho(g,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let g=decodeURIComponent(m[1]),x=g.indexOf("::");if(x>0){let k=g.slice(0,x),v=g.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=He(M.url.replace(/\/+$/,""),a.config);if(A){await co(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=He(c,a.config);if(!m){y(e,404,{error:`unknown peer: ${c}`});return}let g=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await co(t,e,m,r+(g==="?"?"":g));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await En(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await pc(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-YFA4ZSRH.js"),g=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:g});y(e,200,x)}catch(c){y(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(Mn({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await An(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(In({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($n({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 qd(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 Jn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Dt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Yn(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){er(t,e,d[1],O(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 g=new Z,x=m?g.verify(m):null;if(!x||!xe(x,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await on(t,e);return}if(r.startsWith("/api/admin/approvals")){await vn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await mn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await tr(t,e,r);return}if(r.startsWith("/api/admin/")){await sn(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(en);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){y(e,400,{error:"invalid asset name"});return}let m=lc("web/"+c);try{let g=await dc(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(g)}catch{y(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);y(e,200,c)}catch(c){y(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",g=await Ne(a.config,{date:c,timezone:m});y(e,200,g)}catch(c){y(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(m,g,x,k)=>{let v=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(v)?Math.max(x,Math.min(k,v)):g};try{let m=await ge(a.config);y(e,200,await gr(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){y(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)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(g,x,k,v)=>{let _=parseInt(n.searchParams.get(g)||"",10);return Number.isFinite(_)?Math.max(k,Math.min(v,_)):x};try{let g=await ge(a.config);y(e,200,await vr(g,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(g){y(e,502,{error:g.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let c=n.searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}let m=n.searchParams,g;if(r==="/api/mesh/thread"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){y(e,400,{error:"agent, channel, chat required"});return}g=`/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){y(e,400,{error:"kind and key required"});return}g=`/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){y(e,400,{error:"agent, channel, chat required"});return}g=`/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){y(e,400,{error:"task required"});return}g=`/analytics/run/${encodeURIComponent(x)}`}try{await xr(e,await ge(a.config),c,g)}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Vd(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"),g=c.searchParams.get("agent"),x=c.searchParams.get("task");if(!m||!g||!x){y(e,400,{error:"node, agent, task query params required"});return}await Yd(t,e,a,m,g,x);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),g=c.searchParams.get("agent"),x=c.searchParams.get("task"),k=c.searchParams.get("limit")||"50";if(!m||!g){y(e,400,{error:"node and agent query params required"});return}await ec(e,a,m,g,x,k);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),g=c.searchParams.get("task"),x=c.searchParams.get("kind");if(!m||!g||x!=="cancel"&&x!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await tc(t,e,a,m,g,x);return}if(o==="POST"&&r==="/api/voice/stop"){let c=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}await Qt(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 g=await m.json();y(e,200,g)}catch(c){y(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){y(e,m.status,{error:`HTTP ${m.status}`});return}y(e,200,await m.json())}catch(c){y(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await ue(t);try{let m=await sc(a.config,c);y(e,200,m)}catch(m){y(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(!Qd(t,e,[`agent:${c}`]))return;await Zd(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 g=new Z,x=m?g.verify(m):null;if(!x||!xe(x,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Fd(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let c=n.searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}await Qt(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 g=[{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
|
|
16491
16958
|
|
|
16492
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let _ of
|
|
16959
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let _ of g)(async()=>{let M={Accept:"text/event-stream"};_.token&&(M.Authorization=`Bearer ${_.token}`);let A=new AbortController;k.push(A);try{let S=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:A.signal});if(!S.ok||!S.body)return;let I=S.body.getReader(),R=new TextDecoder,j="";for(;!x.flag;){let{done:B,value:ae}=await I.read();if(B)break;j+=R.decode(ae,{stream:!0});let z;for(;(z=j.indexOf(`
|
|
16493
16960
|
|
|
16494
|
-
`))>=0;){let
|
|
16961
|
+
`))>=0;){let N=j.slice(0,z);if(j=j.slice(z+2),x.flag)break;try{e.write(N+`
|
|
16495
16962
|
|
|
16496
|
-
`)}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))),
|
|
16497
|
-
`;
|
|
16963
|
+
`)}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))),g=c.searchParams.get("workflowId")||void 0,x=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:m,workflowId:g}),v=`?limit=${m}${g?`&workflowId=${encodeURIComponent(g)}`:""}${x?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(R=>({url:R.url,token:R.token}))],M=await Promise.all(_.map(async R=>{let j={};R.token&&(j.Authorization=`Bearer ${R.token}`);try{let B=new AbortController,ae=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${R.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:j,signal:B.signal});if(!z.ok)return[];let N=await z.json();return Array.isArray(N.runs)?N.runs:[]}finally{clearTimeout(ae)}}catch{return[]}})),A=new Map;for(let R of k)A.set(R.id,R);for(let R of M)for(let j of R)A.set(j.id,j);let S=Array.from(A.values()).sort((R,j)=>R.updatedAt<j.updatedAt?1:-1).slice(0,m),I=x?S.map(R=>Hd(R)):S;y(e,200,{runs:I})}catch(c){y(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){y(e,200,{run:m});return}let g=[{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 g)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){y(e,200,await v.json());return}}catch{}y(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(/\/+$/,""),g=await fetch(`${m}/api/actions/builtin`,{headers:c}),x=await g.json().catch(()=>({error:`HTTP ${g.status}`}));y(e,g.status,x)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let b=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(b){try{let c=await ue(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${g}/workflows/${encodeURIComponent(b[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,k)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&Tr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,g,x)=>{if(a.token)return!0;let k=vt(m);if(!k)return!0;let v=new Z().verify(k);if(!v)return y(g,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!xe(v,_))return y(g,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(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){y(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];y(e,200,m)}catch(m){y(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){y(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let h=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(h&&o==="PATCH"){let[,c,m]=h,g=decodeURIComponent(m),x=a.boards.find(A=>A.id===c);if(!x){y(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){y(e,503,{error:`board "${c}" source unavailable`});return}let v=await ue(t),_=x.columns.find(A=>A.id===v.to),M=x.columns.find(A=>A.id===v.from);if(!_){y(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await Nd(k,g,M,_),Kt({actor:Jt(t),action:"move",boardId:c,itemId:g,payload:{from:v.from,to:v.to}}),y(e,200,{ok:!0})}catch(A){y(e,502,{error:A.message||"transition failed"})}return}if(E){let[,c,m]=E,g=m?decodeURIComponent(m):void 0,x=a.boards.find(v=>v.id===c);if(!x){y(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){y(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!g){let{columns:v,totals:_}=await Dd(x,k,n.searchParams);y(e,200,{columns:v,totals:_});return}if(o==="GET"&&g){try{let v=typeof k.getItem=="function"?await k.getItem(g):null;if(!v){y(e,404,{error:"not found"});return}y(e,200,v)}catch(v){y(e,502,{error:v.message})}return}if(o==="PATCH"&&g){let v=await ue(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(g,v):null;if(!_){y(e,501,{error:"update unsupported"});return}Kt({actor:Jt(t),action:"update",boardId:c,itemId:g,payload:v}),y(e,200,_)}catch(_){y(e,502,{error:_.message})}return}if(o==="POST"&&!g){let v=await ue(t);if(!v.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let _=await k.create({title:v.title,description:v.description,labels:v.labels,assigneeUsernames:v.assigneeUsernames,milestoneTitle:v.milestoneTitle,projectHint:v.projectHint});Kt({actor:Jt(t),action:"create",boardId:c,itemId:_.id,payload:{title:v.title}}),y(e,201,_)}catch(_){y(e,502,{error:_.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let c=r.replace(/^\/+|\/+$/g,""),g={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[c];if(g){e.writeHead(302,{Location:g}),e.end();return}}y(e,404,{error:"not found",path:r})}async function Dd(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"}):[],b=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 b)T&&w[T.id].push({...c,stage:T.id});let h=t.columns.filter(c=>c.kind!=="closed");for(let c of f){let m=ea(c,h);if(!m)continue;let g=w[m];g&&g.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,g)=>{let x=(m.priority??99)-(g.priority??99);return x!==0?x:(g.updatedAt||"").localeCompare(m.updatedAt||"")});let E=Object.fromEntries(Object.entries(w).map(([c,m])=>[c,m.length]));return{columns:w,totals:E}}async function Nd(t,e,a,n){let r=ta(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 Hd(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 Bd(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 _a(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Kt(t){try{let e=De(process.cwd(),".agentx");po(e)||$d(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
16964
|
+
`;Id(De(e,"board-audit.jsonl"),a)}catch{}}function Jt(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function zd(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,b,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(h=>({id:h.id,name:h.name,tier:h.tier,model:h.model,...typeof h.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(h.color)?{color:h.color}:{},skillCount:Number.isFinite(h.skillCount)?h.skillCount:void 0,active:h.active||0,total:h.total||0,errors:h.errors||0,lastActive:h.lastActive,lastSummary:h.lastSummary,hourlyTasks:Array.isArray(h.hourlyTasks)?h.hourlyTasks:void 0,runningTasks:Array.isArray(h.runningTasks)?h.runningTasks:[]})),i&&i.ok){let h=await i.json();o.uptimeSec=h.uptime,typeof h.inflight?.total=="number"&&(o.inflight=h.inflight.total),h.restart&&typeof h.restart.state=="string"&&(o.restart=h.restart),o.name=h.node?.name||h.node?.id||t,o.id=h.node?.id||t,h.usage&&(o.usage=h.usage)}if(p&&p.ok){let h=await p.json();o.crons=h.map(E=>({id:E.id,enabled:E.enabled===!0,schedule:String(E.schedule||""),timezone:E.timezone,agent:String(E.agent||""),kind:typeof E.command=="string"&&E.command.trim()?"command":"agent",model:E.model,nextRun:E.nextRun,retryPending:E.retryPending===!0,consecutiveErrors:Number(E.consecutiveErrors)||0}))}if(u&&u.ok){let h=await u.json();o.cronRuns=Array.isArray(h.runs)?h.runs:[]}if(b&&b.ok){let h=await b.json().catch(()=>null);h&&Array.isArray(h.routines)&&(o.routines=h.routines.slice(0,ua.routines))}if(f&&f.ok){let h=await f.json().catch(()=>null);h?.active&&h.kind==="lesson"&&(o.lesson={agentId:h.agentId??null,mode:String(h.mode||"teach"),goal:String(h.goal||""),step:Number(h.step)||0,saying:String(h.saying||""),startedAt:String(h.startedAt||"")})}if(w&&w.ok){let h=await w.json().catch(()=>null);h&&Array.isArray(h.sessions)&&Jd(o,h.sessions,h.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await Ud(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var dt=null;function qd(t){if(dt)return dt;let e=De(process.cwd(),".agentx/wiki");return dt=Ga({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),dt}var Vt=new WeakMap;async function Ud(t){if(Vt.has(t))return Vt.get(t);try{let e=t.ok?await t.json():null;return Vt.set(t,e),e}catch{return null}}async function pt(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 Fd(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||ne(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function ge(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=ne(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:ne(a,l)})}let s=await pt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:ne(a,i.url)});return[...o.values()]}var Wd=3e3,Gd=6e3,Xd=5*6e4,Yt=new Map,ct=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=ct.get(a);if(n)return n;let r=(async()=>{let o=await ge(t,AbortSignal.timeout(Wd)),s=await Promise.all(o.map(async i=>{let l=await zd(i.url,i.token,AbortSignal.timeout(Gd),e);return e?l:Kd(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ct.delete(a));return ct.set(a,r),r}function Kd(t,e,a=Date.now()){if(e.reachable&&!e.error)return Yt.set(t,{node:e,at:a}),e;let n=Yt.get(t);return!n||a-n.at>Xd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Lf(){Yt.clear(),ct.clear()}function Jd(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 Vd(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}
|
|
16498
16965
|
data: ${JSON.stringify(d)}
|
|
16499
16966
|
|
|
16500
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await
|
|
16967
|
+
`)},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 Yd(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 pt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=ne(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){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let 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 Qd(t,e,a){let n=vt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Z().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!xe(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Zd(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ue(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let 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){y(e,502,{error:d.message||"upstream call failed"})}}async function ec(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 pt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=ne(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){y(t,502,{error:u.message||"upstream fetch failed"})}}async function tc(t,e,a,n,r,o){await Qt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Qt(t,e,a,n,r){let o={};try{o=await ue(t)??{}}catch{}let s=await uo(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function uo(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 pt(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=ne(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 ac(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=ha(e.keysFile);return{store:()=>{let r=Be();return r?new Ma(r):null},publicKey:()=>ga(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function mo(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 uo(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=qe({root:process.cwd()}).items.map(lo)}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=He(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(lo)}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=_e(),p=await Ue({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=He(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 nc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=ne(t.dashboard,e),n=mo(t);return{store:()=>{let r=Be();return r?new Oe(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 rc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Be();return a?new Oe(a):null},daemon:{url:e,token:ne(t.dashboard,e)}}}function lo(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 oc=`
|
|
16501
16968
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
16502
16969
|
|
|
16503
16970
|
Title pattern:
|
|
@@ -16529,16 +16996,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
16529
16996
|
Shape:
|
|
16530
16997
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
16531
16998
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
16532
|
-
`;async function
|
|
16999
|
+
`;async function sc(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):
|
|
16533
17000
|
- ${r.knownLabels.slice(0,60).join(`
|
|
16534
17001
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
16535
|
-
`),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:
|
|
17002
|
+
`),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:oc}})});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=ic(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(b=>typeof b=="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 ic(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 lc(t){let e=jd(Rd(import.meta.url));return De(e,t)}async function dc(t){return Ld(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ue(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 fo(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function O(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:fo(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 cc(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await rt(await ho(r,a.config)))}async function ho(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ot(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=He(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 Xn(n)}async function pc(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),b=f.find(w=>po(w));if(!b){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",b]}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}
|
|
16536
17003
|
|
|
16537
17004
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
|
|
16538
|
-
`))>=0;){let
|
|
16539
|
-
data: ${
|
|
17005
|
+
`))>=0;){let b=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
|
|
17006
|
+
data: ${b.replace(/\n/g," ")}
|
|
16540
17007
|
|
|
16541
17008
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
|
|
16542
17009
|
|
|
16543
|
-
`)}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
|
|
16544
|
-
//# sourceMappingURL=board-dashboard-
|
|
17010
|
+
`)}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 co(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 b=[];t.on("data",w=>b.push(w)),t.on("end",()=>u(Buffer.concat(b))),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){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function He(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:fo(n),token:n.dashboardToken||n.token}:null}export{Jd as applyAttachSessions,Od as handleBoardRequest,Lf as resetLiveCaches,ge as resolveNodeTargets,$f as startBoardDashboard,Kd as withLastGood};
|
|
17011
|
+
//# sourceMappingURL=board-dashboard-C6AZHDHU.js.map
|