agentix-cli 0.43.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/mac-helper/Resources/AppIcon.png +0 -0
- package/apps/mac-helper/Sources/AgentXHelper/Notify.swift +51 -0
- package/apps/mac-helper/Sources/AgentXHelper/main.swift +15 -1
- package/apps/mac-helper/build.sh +25 -2
- package/dist/{App-HSRGG5VA.js → App-QTUGMHG7.js} +2 -2
- package/dist/{ChatApp-4FOU6Q3S.js → ChatApp-634FDG3W.js} +2 -2
- package/dist/{agent-54NUP2Z3.js → agent-3XDPLWMX.js} +2 -2
- package/dist/{board-dashboard-HLTVSSGW.js → board-dashboard-OYGL7Z7X.js} +455 -161
- package/dist/board-dashboard-OYGL7Z7X.js.map +1 -0
- package/dist/{chunk-H4MIYENA.js → chunk-6HMZ5TTM.js} +2 -2
- package/dist/{chunk-SJPLXXCI.js → chunk-7A7RC3R4.js} +2 -2
- package/dist/{chunk-2HNKBYQ6.js → chunk-7HHVZJO4.js} +192 -208
- package/dist/chunk-7HHVZJO4.js.map +1 -0
- package/dist/chunk-BIFJSQB5.js +123 -0
- package/dist/chunk-BIFJSQB5.js.map +1 -0
- package/dist/{chunk-WBGROLOX.js → chunk-BTGPZ6B7.js} +2 -2
- package/dist/{chunk-X763UOES.js → chunk-ICZPZYYR.js} +2 -2
- package/dist/{chunk-RCVGIKC2.js → chunk-MTVRYTLL.js} +2 -2
- package/dist/{chunk-B32HVIDN.js → chunk-NSYY5NCR.js} +3 -3
- package/dist/chunk-NSYY5NCR.js.map +1 -0
- package/dist/chunk-P2Y7DFFP.js +36 -0
- package/dist/chunk-P2Y7DFFP.js.map +1 -0
- package/dist/{chunk-XRPMP6A5.js → chunk-Q3Q6FTFY.js} +151 -148
- package/dist/chunk-Q3Q6FTFY.js.map +1 -0
- package/dist/chunk-QJANPP4C.js +15 -0
- package/dist/chunk-QJANPP4C.js.map +1 -0
- package/dist/{chunk-REPZID5M.js → chunk-SAFAI4AV.js} +43 -43
- package/dist/chunk-SAFAI4AV.js.map +1 -0
- package/dist/chunk-T76YTN34.js +178 -0
- package/dist/chunk-T76YTN34.js.map +1 -0
- package/dist/chunk-TCJ3SMOF.js +9 -0
- package/dist/chunk-TCJ3SMOF.js.map +1 -0
- package/dist/{chunk-RQKUQOFC.js → chunk-TNFOGJWZ.js} +2 -2
- package/dist/{chunk-FAJEBVZE.js → chunk-V5FZJUK4.js} +2 -2
- package/dist/chunk-WLVQDEOT.js +2 -0
- package/dist/chunk-WLVQDEOT.js.map +1 -0
- package/dist/{chunk-B5HKRYCU.js → chunk-YQVR2HQS.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-NTC667CA.js +2 -0
- package/dist/config-5V444ZFW.js +2 -0
- package/dist/config-mutator-E6NQLFWR.js +2 -0
- package/dist/doctor-5HDW5F66.js +2 -0
- package/dist/{editor-chat-OB7IQOB5.js → editor-chat-MOMQHMO4.js} +2 -2
- package/dist/editor-chat-MOMQHMO4.js.map +1 -0
- package/dist/index.d.ts +462 -46
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/program-HGI5C2MP.js +2 -0
- package/dist/query-6EMTLCHQ.js +2 -0
- package/dist/registry-5QOY65FS.js +2 -0
- package/dist/{request-planner-326NOKPZ.js → request-planner-KYQCJDAW.js} +2 -2
- package/dist/{review-candidates-LEOPEOEG.js → review-candidates-BFAWNDOR.js} +2 -2
- package/dist/routing-OC3QJI3W.js +2 -0
- package/dist/schedule-tool-VQCNMBJF.js +8 -0
- package/dist/schedule-tool-VQCNMBJF.js.map +1 -0
- package/dist/scheduler-NRXPVG7P.js +2 -0
- package/dist/seat-3WT3VJC2.js +2 -0
- package/dist/{select-L4VIYSFJ.js → select-KPQWIC22.js} +2 -2
- package/dist/web/activity-graph.global.js.map +1 -1
- package/dist/web/workflow-editor.global.js +1 -1
- package/dist/web/workflow-editor.global.js.map +1 -1
- package/dist/wiki-5JORBO4G.js +2 -0
- package/package.json +2 -1
- package/dist/board-dashboard-HLTVSSGW.js.map +0 -1
- package/dist/chunk-2HNKBYQ6.js.map +0 -1
- package/dist/chunk-B32HVIDN.js.map +0 -1
- package/dist/chunk-DIKZWTL5.js +0 -170
- package/dist/chunk-DIKZWTL5.js.map +0 -1
- package/dist/chunk-F6CNF7V3.js +0 -25
- package/dist/chunk-F6CNF7V3.js.map +0 -1
- package/dist/chunk-IAG6FI3Q.js +0 -13
- package/dist/chunk-IAG6FI3Q.js.map +0 -1
- package/dist/chunk-NZ6AQIKJ.js +0 -121
- package/dist/chunk-NZ6AQIKJ.js.map +0 -1
- package/dist/chunk-P7LNYB53.js +0 -9
- package/dist/chunk-P7LNYB53.js.map +0 -1
- package/dist/chunk-REPZID5M.js.map +0 -1
- package/dist/chunk-XRPMP6A5.js.map +0 -1
- package/dist/client-6BGTH2TT.js +0 -2
- package/dist/config-SRTXHGSK.js +0 -2
- package/dist/config-mutator-KJ5GEMVV.js +0 -2
- package/dist/doctor-J4FLV45L.js +0 -2
- package/dist/editor-chat-OB7IQOB5.js.map +0 -1
- package/dist/program-LYFTYF7E.js +0 -2
- package/dist/query-ZSUBNWOL.js +0 -2
- package/dist/registry-OMUDCBKM.js +0 -2
- package/dist/routing-AWIRBYGU.js +0 -2
- package/dist/scheduler-PGGYW5AB.js +0 -2
- package/dist/seat-XB4EGUKJ.js +0 -2
- package/dist/wiki-GBC6I7ZX.js +0 -2
- /package/dist/{App-HSRGG5VA.js.map → App-QTUGMHG7.js.map} +0 -0
- /package/dist/{ChatApp-4FOU6Q3S.js.map → ChatApp-634FDG3W.js.map} +0 -0
- /package/dist/{agent-54NUP2Z3.js.map → agent-3XDPLWMX.js.map} +0 -0
- /package/dist/{chunk-H4MIYENA.js.map → chunk-6HMZ5TTM.js.map} +0 -0
- /package/dist/{chunk-SJPLXXCI.js.map → chunk-7A7RC3R4.js.map} +0 -0
- /package/dist/{chunk-WBGROLOX.js.map → chunk-BTGPZ6B7.js.map} +0 -0
- /package/dist/{chunk-X763UOES.js.map → chunk-ICZPZYYR.js.map} +0 -0
- /package/dist/{chunk-RCVGIKC2.js.map → chunk-MTVRYTLL.js.map} +0 -0
- /package/dist/{chunk-RQKUQOFC.js.map → chunk-TNFOGJWZ.js.map} +0 -0
- /package/dist/{chunk-FAJEBVZE.js.map → chunk-V5FZJUK4.js.map} +0 -0
- /package/dist/{chunk-B5HKRYCU.js.map → chunk-YQVR2HQS.js.map} +0 -0
- /package/dist/{client-6BGTH2TT.js.map → client-NTC667CA.js.map} +0 -0
- /package/dist/{config-SRTXHGSK.js.map → config-5V444ZFW.js.map} +0 -0
- /package/dist/{config-mutator-KJ5GEMVV.js.map → config-mutator-E6NQLFWR.js.map} +0 -0
- /package/dist/{doctor-J4FLV45L.js.map → doctor-5HDW5F66.js.map} +0 -0
- /package/dist/{program-LYFTYF7E.js.map → program-HGI5C2MP.js.map} +0 -0
- /package/dist/{query-ZSUBNWOL.js.map → query-6EMTLCHQ.js.map} +0 -0
- /package/dist/{registry-OMUDCBKM.js.map → registry-5QOY65FS.js.map} +0 -0
- /package/dist/{request-planner-326NOKPZ.js.map → request-planner-KYQCJDAW.js.map} +0 -0
- /package/dist/{review-candidates-LEOPEOEG.js.map → review-candidates-BFAWNDOR.js.map} +0 -0
- /package/dist/{routing-AWIRBYGU.js.map → routing-OC3QJI3W.js.map} +0 -0
- /package/dist/{scheduler-PGGYW5AB.js.map → scheduler-NRXPVG7P.js.map} +0 -0
- /package/dist/{seat-XB4EGUKJ.js.map → seat-3WT3VJC2.js.map} +0 -0
- /package/dist/{select-L4VIYSFJ.js.map → select-KPQWIC22.js.map} +0 -0
- /package/dist/{wiki-GBC6I7ZX.js.map → wiki-5JORBO4G.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as Ft}from"./chunk-3RHPZXCR.js";import{a as C,b as Ut,c as Wt,d as Gt,e as Xt,f as ae,g as ve,h as Ke,i as Jt,j as Vt,k as Yt}from"./chunk-SAFAI4AV.js";import{a as Kt}from"./chunk-2TJ5L7CB.js";import{a as me,c as $,d as P,i as Me,j as Ie,k as J,l as q,m as $e,n as Bt,o as zt,p as qt}from"./chunk-7CVJ4JOE.js";import{B as Dt,D as ue,E as Ee,F as Se,G as Te,H as Ce,I as Ot,J as Ht,K as Nt,L as Ae,a as Mt,c as _e,d as Xe,e as It,i as $t,u as jt,w as Lt}from"./chunk-P2Y7DFFP.js";import{g as Ct,h as At}from"./chunk-V5FZJUK4.js";import{a as Rt,b as Pt}from"./chunk-V7FYSZSV.js";import{a as _t,b as We,c as Ge,g as Et,h as St,i as Tt}from"./chunk-TCJ3SMOF.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-BIFJSQB5.js";import"./chunk-AFRHKA7B.js";import"./chunk-NSYY5NCR.js";import{b as kt}from"./chunk-MTVRYTLL.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-6HMZ5TTM.js";import"./chunk-F4HZTZHW.js";import"./chunk-AJONZWLT.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import{a as yt,b as wt,c as Ln,l as K,o as Ue}from"./chunk-QJANPP4C.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";function Je(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 Qt(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Je(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var V={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"/>'},de=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",je=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+de(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Zt(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>
|
|
@@ -85,7 +85,7 @@ ${je(V.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:Rn,scripts:`<script>${me({decayOf:Je,rankByDecay:Qt})}const ICON = ${JSON.stringify(V)};${Pn}</script>`})}var Rn=`
|
|
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
|
+
}`,Pn=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 Ve(t,e=20*6e4,a=6){let n=[...t].sort((i,c)=>i.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let i of n){let c=i.startedAt+Math.max(i.durationMs||0,0),p=r[r.length-1];p&&i.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:i.startedAt,to:c,runs:1})}for(;r.length>a;){let i=0,c=1/0;for(let p=1;p<r.length;p++){let m=r[p].from-r[p-1].to;m<c&&(c=m,i=p)}r[i-1].to=r[i].to,r[i-1].runs+=r[i].runs,r.splice(i,1)}let o=r.reduce((i,c)=>i+c.runs,0)||1,s=r.map(i=>({from:i.from,to:Math.max(i.to,i.from+1),weight:i.runs/o,runs:i.runs})),l=r.slice(1).map((i,c)=>i.from-r[c].to);return{bands:s,gaps:l}}function Ye(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
|
|
779
|
+
})();`;function Ve(t,e=20*6e4,a=6){let n=[...t].sort((i,c)=>i.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let i of n){let c=i.startedAt+Math.max(i.durationMs||0,0),p=r[r.length-1];p&&i.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:i.startedAt,to:c,runs:1})}for(;r.length>a;){let i=0,c=1/0;for(let p=1;p<r.length;p++){let m=r[p].from-r[p-1].to;m<c&&(c=m,i=p)}r[i-1].to=r[i].to,r[i-1].runs+=r[i].runs,r.splice(i,1)}let o=r.reduce((i,c)=>i+c.runs,0)||1,s=r.map(i=>({from:i.from,to:Math.max(i.to,i.from+1),weight:i.runs/o,runs:i.runs})),l=r.slice(1).map((i,c)=>i.from-r[c].to);return{bands:s,gaps:l}}function Ye(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 ea(t,e=[],a){let{bands:n,gaps:r}=Ve(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let i of e){let c=o.get(i.runId);c?c.push(i):o.set(i.runId,[i])}let s=new Map;for(let i of t){let c=n.findIndex(k=>i.startedAt>=k.from&&i.startedAt<=k.to);if(c===-1)continue;let p=n[c],m=p.to-p.from||1,g=(i.startedAt-p.from)/m*100,_=Math.min(Math.max((i.durationMs||0)/m*100,1.2),100-g),S=s.get(i.laneKey)??{key:i.laneKey,label:i.laneLabel,sub:i.laneSub,tracks:1,runs:[]};S.runs.push({...i,band:c,track:0,left:g,width:_,marks:o.get(i.id)??[]}),s.set(i.laneKey,S)}let l=[...s.values()];for(let i of l)i.tracks=Math.max(...n.map((c,p)=>Ye(i.runs.filter(m=>m.band===p))),1);return l.sort((i,c)=>c.runs.length-i.runs.length||i.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:l,from:n[0].from,to:n[n.length-1].to}}import{createHash as Dn}from"crypto";import{readFileSync as On,statSync as Hn}from"fs";import{resolve as Nn,dirname as Bn}from"path";import{fileURLToPath as zn}from"url";var ta=new Map;function Le(t){let e=ta.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Bn(zn(import.meta.url)),r=Nn(n,"web",t),o=Hn(r),s=o.size<8e6?Dn("sha1").update(On(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return ta.set(t,a),a}var ee={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',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"/>'},Re=(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>",qn=[["agent","Agent",ee.bot],["client","Client",ee.user],["project","Project",ee.folder],["channel","Channel",ee.route],["node","Node",ee.mesh]],aa={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 na(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">${aa[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",ee.timeline],["map","Map",ee.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Re(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":""}>${Re(
|
|
794
|
+
<button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${Re(ee.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
|
+
${qn.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Re(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">${Re(
|
|
809
|
+
<span class="ac-k">${Re(ee.x,11)}canceled</span>
|
|
810
810
|
</div>
|
|
811
811
|
</div>
|
|
812
812
|
|
|
@@ -819,7 +819,7 @@ refresh();
|
|
|
819
819
|
<div id="ax-fleet-root" data-hours="24" data-src="${Le("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Fn,scripts:`<script>${me({computeBands:Ve,packTracks:Ye,buildTimeline:ea})}const ICON = ${JSON.stringify(ee)};const SUB = ${JSON.stringify(aa)};${Un}</script>`})}var Fn=`
|
|
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
|
+
`,Un=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 ra(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:Wn,scripts:`<script src="${Le("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Wn=`
|
|
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
|
-
`;Tn();import{createServer as Ws}from"http";import{appendFileSync as Gs,existsSync as yn,mkdirSync as Xs}from"fs";import{readFile as Ks}from"fs/promises";import{fileURLToPath as Js}from"url";import{dirname as Vs,resolve as ke}from"path";var ea='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Pe,readFileSync as aa,writeFileSync as na,rmSync as Fi,mkdirSync as Un,copyFileSync as Wn,readdirSync as Gn}from"fs";import{resolve as he}from"path";Ue();var Z={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 ta(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Me({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.`})+Ie([{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+Bn()+Ot,css:qn,scripts:`${e}<script>${Ht}
|
|
1047
|
-
${
|
|
1048
|
-
${
|
|
1049
|
-
${
|
|
1046
|
+
`;Ln();import{createServer as Zs}from"http";import{appendFileSync as ei,existsSync as Cn,mkdirSync as ti}from"fs";import{readFile as ai}from"fs/promises";import{fileURLToPath as ni}from"url";import{dirname as ri,resolve as ke}from"path";var oa='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Pe,readFileSync as ia,writeFileSync as la,rmSync as Yi,mkdirSync as Yn,copyFileSync as Qn,readdirSync as Zn}from"fs";import{resolve as he}from"path";Ue();var te={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function sa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Me({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.`})+Ie([{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+Xn()+Bt,css:Jn,scripts:`${e}<script>${zt}
|
|
1047
|
+
${qt}
|
|
1048
|
+
${Gn}
|
|
1049
|
+
${Vn}</script>`})}var Gn=`
|
|
1050
1050
|
(function(){
|
|
1051
1051
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1052
1052
|
async function refresh() {
|
|
@@ -1107,8 +1107,8 @@ ${Fn}</script>`})}var Nn=`
|
|
|
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 Xn(){let t=Pt().business?`<button data-tab="business">Business</button>
|
|
1111
|
+
`:"";return Kn.replace("__BUSINESS_TABS__",t)}var Kn=`
|
|
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,7 +1251,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1251
1251
|
<div id="global-msg" class="msg"></div>
|
|
1252
1252
|
|
|
1253
1253
|
<section id="tab-agents" class="tab active">
|
|
1254
|
-
${q({icon:
|
|
1254
|
+
${q({icon:te.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
|
|
1255
1255
|
${J({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">
|
|
@@ -1274,13 +1274,13 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1274
1274
|
</section>
|
|
1275
1275
|
|
|
1276
1276
|
<section id="tab-channels" class="tab">
|
|
1277
|
-
${q({icon:
|
|
1277
|
+
${q({icon:te.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
|
|
1278
1278
|
${J({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>
|
|
1282
1282
|
<div style="margin-top:10px">
|
|
1283
|
-
<p style="font-size:11px;color:var(--ax-muted);margin:0 0 10px">Where AgentX pings you when a task finishes, errors, or runs long. Mirrors <code>agentx notifications</code>.</p>
|
|
1283
|
+
<p style="font-size:11px;color:var(--ax-muted);margin:0 0 10px">Where AgentX pings you when a task finishes, errors, or runs long, and what <code>agentx notify</code> does on this Mac. Mirrors <code>agentx notifications</code>.</p>
|
|
1284
1284
|
<div id="notif-current" style="font-size:12px;margin-bottom:10px;padding:8px 10px;background:var(--ax-surface);border-radius:4px;color:var(--ax-muted)">\u2014</div>
|
|
1285
1285
|
<label>Channel<span class="hint">(telegram | whatsapp \u2014 leave blank to clear)</span></label>
|
|
1286
1286
|
<input id="notif-channel" placeholder="telegram" />
|
|
@@ -1296,6 +1296,27 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1296
1296
|
<label class="ax-inline" style="display:inline-flex;gap:6px;font-size:12px;margin-right:14px"><input type="checkbox" id="notif-on-error" /> task error</label>
|
|
1297
1297
|
<label class="ax-inline" style="display:inline-flex;gap:6px;font-size:12px"><input type="checkbox" id="notif-on-queued" /> task queued</label>
|
|
1298
1298
|
</fieldset>
|
|
1299
|
+
<fieldset style="margin-top:8px;border:1px solid var(--ax-border);border-radius:4px;padding:8px 10px">
|
|
1300
|
+
<legend style="font-size:11px;color:var(--ax-muted);padding:0 4px">On this Mac, when <code>agentx notify</code> delivers</legend>
|
|
1301
|
+
<label class="ax-inline" style="display:inline-flex;gap:6px;font-size:12px;margin-right:14px"><input type="checkbox" id="notif-local-banner" /> show a banner</label>
|
|
1302
|
+
<label class="ax-inline" style="display:inline-flex;gap:6px;font-size:12px"><input type="checkbox" id="notif-local-sound" /> play a sound</label>
|
|
1303
|
+
<label>Sound <span class="hint">(a name from /System/Library/Sounds, e.g. Glass, Ping, Tink)</span></label>
|
|
1304
|
+
<input id="notif-local-sound-name" placeholder="Glass" />
|
|
1305
|
+
<label>Volume <span class="hint">(0 to 1)</span></label>
|
|
1306
|
+
<input id="notif-local-volume" type="number" min="0" max="1" step="0.1" />
|
|
1307
|
+
<label>Banner icon <span class="hint">(full path to a .png, .jpg or .icns; blank for the AgentX logo; applies on the next <code>agentx desktop install</code>)</span></label>
|
|
1308
|
+
<input id="notif-local-icon" placeholder="AgentX logo" />
|
|
1309
|
+
</fieldset>
|
|
1310
|
+
<fieldset style="margin-top:8px;border:1px solid var(--ax-border);border-radius:4px;padding:8px 10px">
|
|
1311
|
+
<legend style="font-size:11px;color:var(--ax-muted);padding:0 4px">Phone push (ntfy) \u2014 used by <code>agentx notify</code>; restart the daemon after changing</legend>
|
|
1312
|
+
<label class="ax-inline" style="display:inline-flex;gap:6px;font-size:12px"><input type="checkbox" id="notif-ntfy-enabled" /> enabled</label>
|
|
1313
|
+
<label>Server</label>
|
|
1314
|
+
<input id="notif-ntfy-server" placeholder="https://ntfy.sh" />
|
|
1315
|
+
<label>Topic <span class="hint" id="notif-ntfy-topic-hint">(treat it as a password; blank keeps the current one)</span></label>
|
|
1316
|
+
<input id="notif-ntfy-topic" type="password" autocomplete="off" placeholder="\${NTFY_TOPIC}" />
|
|
1317
|
+
<label>Access token <span class="hint" id="notif-ntfy-token-hint">(optional; blank keeps the current one)</span></label>
|
|
1318
|
+
<input id="notif-ntfy-token" type="password" autocomplete="off" placeholder="\${NTFY_TOKEN}" />
|
|
1319
|
+
</fieldset>
|
|
1299
1320
|
<div class="actions" style="margin-top:10px">
|
|
1300
1321
|
<button class="primary" onclick="saveNotifications()">Save notifications</button>
|
|
1301
1322
|
<button class="ghost" onclick="clearNotificationsDestination()">Clear destination</button>
|
|
@@ -1325,7 +1346,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1325
1346
|
</section>
|
|
1326
1347
|
|
|
1327
1348
|
<section id="tab-crons" class="tab">
|
|
1328
|
-
${q({icon:
|
|
1349
|
+
${q({icon:te.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."})}
|
|
1329
1350
|
${J({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."})}
|
|
1330
1351
|
<div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
|
|
1331
1352
|
|
|
@@ -1423,7 +1444,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1423
1444
|
</section>
|
|
1424
1445
|
|
|
1425
1446
|
<section id="tab-webhooks" class="tab">
|
|
1426
|
-
${q({icon:
|
|
1447
|
+
${q({icon:te.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."})}
|
|
1427
1448
|
${J({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.`})}
|
|
1428
1449
|
<div id="webhook-list" class="ax-stack"></div>
|
|
1429
1450
|
<div class="add-form">
|
|
@@ -1443,7 +1464,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1443
1464
|
</section>
|
|
1444
1465
|
|
|
1445
1466
|
<section id="tab-mesh" class="tab">
|
|
1446
|
-
${q({icon:
|
|
1467
|
+
${q({icon:te.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."})}
|
|
1447
1468
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
1448
1469
|
${J({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."})}
|
|
1449
1470
|
${$e({label:"Connected peers"})}
|
|
@@ -1473,7 +1494,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1473
1494
|
</section>
|
|
1474
1495
|
|
|
1475
1496
|
<section id="tab-business" class="tab">
|
|
1476
|
-
${q({icon:
|
|
1497
|
+
${q({icon:te.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Mirrors <code>agentx business</code>."})}
|
|
1477
1498
|
${J({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.'})}
|
|
1478
1499
|
|
|
1479
1500
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -1561,7 +1582,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1561
1582
|
</section>
|
|
1562
1583
|
|
|
1563
1584
|
<section id="tab-boards-cfg" class="tab">
|
|
1564
|
-
${q({icon:
|
|
1585
|
+
${q({icon:te.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Mirrors <code>agentx board add/edit/remove</code> + <code>agentx board column</code>. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
|
|
1565
1586
|
${J({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.'})}
|
|
1566
1587
|
|
|
1567
1588
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -1586,7 +1607,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1586
1607
|
</section>
|
|
1587
1608
|
|
|
1588
1609
|
<section id="tab-actions" class="tab">
|
|
1589
|
-
${q({icon:
|
|
1610
|
+
${q({icon:te.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. Mirrors <code>agentx actions</code>."})}
|
|
1590
1611
|
${J({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."})}
|
|
1591
1612
|
|
|
1592
1613
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -1642,7 +1663,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1642
1663
|
</section>
|
|
1643
1664
|
|
|
1644
1665
|
<section id="tab-tokens" class="tab">
|
|
1645
|
-
${q({icon:
|
|
1666
|
+
${q({icon:te.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."})}
|
|
1646
1667
|
${J({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."})}
|
|
1647
1668
|
<div id="token-list" class="ax-stack"></div>
|
|
1648
1669
|
<div class="add-form">
|
|
@@ -1662,7 +1683,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1662
1683
|
</section>
|
|
1663
1684
|
|
|
1664
1685
|
<section id="tab-advanced" class="tab">
|
|
1665
|
-
${q({icon:
|
|
1686
|
+
${q({icon:te.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."})}
|
|
1666
1687
|
${J({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.`})}
|
|
1667
1688
|
|
|
1668
1689
|
<div class="ax-jv-toolbar">
|
|
@@ -1689,7 +1710,7 @@ ${Fn}</script>`})}var Nn=`
|
|
|
1689
1710
|
<div class="hint-block">The schema is documented at <code>docs/reference/config-schema.md</code>. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
|
|
1690
1711
|
</section>
|
|
1691
1712
|
</main>
|
|
1692
|
-
`,
|
|
1713
|
+
`,Jn=`
|
|
1693
1714
|
|
|
1694
1715
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
1695
1716
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -1897,7 +1918,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
1897
1918
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
1898
1919
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
1899
1920
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
1900
|
-
`,
|
|
1921
|
+
`,Vn=`
|
|
1901
1922
|
const $ = (id) => document.getElementById(id);
|
|
1902
1923
|
let state = null;
|
|
1903
1924
|
|
|
@@ -2523,6 +2544,19 @@ function renderNotifications() {
|
|
|
2523
2544
|
if ($('notif-on-complete')) $('notif-on-complete').checked = n.on?.taskComplete !== false;
|
|
2524
2545
|
if ($('notif-on-error')) $('notif-on-error').checked = n.on?.taskError !== false;
|
|
2525
2546
|
if ($('notif-on-queued')) $('notif-on-queued').checked = !!n.on?.taskQueued;
|
|
2547
|
+
const local = n.local || {};
|
|
2548
|
+
if ($('notif-local-banner')) $('notif-local-banner').checked = local.banner !== false;
|
|
2549
|
+
if ($('notif-local-sound')) $('notif-local-sound').checked = local.sound !== false;
|
|
2550
|
+
if ($('notif-local-sound-name')) $('notif-local-sound-name').value = local.soundName || 'Glass';
|
|
2551
|
+
if ($('notif-local-volume')) $('notif-local-volume').value = local.volume ?? 0.4;
|
|
2552
|
+
if ($('notif-local-icon')) $('notif-local-icon').value = local.icon || '';
|
|
2553
|
+
const ntfy = n.ntfy || {};
|
|
2554
|
+
if ($('notif-ntfy-enabled')) $('notif-ntfy-enabled').checked = !!ntfy.enabled;
|
|
2555
|
+
if ($('notif-ntfy-server')) $('notif-ntfy-server').value = ntfy.server || 'https://ntfy.sh';
|
|
2556
|
+
if ($('notif-ntfy-topic')) $('notif-ntfy-topic').value = '';
|
|
2557
|
+
if ($('notif-ntfy-token')) $('notif-ntfy-token').value = '';
|
|
2558
|
+
if ($('notif-ntfy-topic-hint')) $('notif-ntfy-topic-hint').textContent = ntfy.topicSet ? '(set; blank keeps it)' : '(not set; treat it as a password)';
|
|
2559
|
+
if ($('notif-ntfy-token-hint')) $('notif-ntfy-token-hint').textContent = ntfy.tokenSet ? '(set; blank keeps it)' : '(optional, for protected topics)';
|
|
2526
2560
|
}
|
|
2527
2561
|
|
|
2528
2562
|
window.saveNotifications = async function() {
|
|
@@ -2530,6 +2564,7 @@ window.saveNotifications = async function() {
|
|
|
2530
2564
|
const chatId = $('notif-chat-id').value.trim();
|
|
2531
2565
|
const accountId = $('notif-account-id').value.trim();
|
|
2532
2566
|
const threshold = parseInt($('notif-threshold').value, 10);
|
|
2567
|
+
const volume = parseFloat($('notif-local-volume').value);
|
|
2533
2568
|
const body = {
|
|
2534
2569
|
on: {
|
|
2535
2570
|
taskComplete: $('notif-on-complete').checked,
|
|
@@ -2537,7 +2572,27 @@ window.saveNotifications = async function() {
|
|
|
2537
2572
|
taskQueued: $('notif-on-queued').checked,
|
|
2538
2573
|
},
|
|
2539
2574
|
longTaskThreshold: Number.isFinite(threshold) ? threshold : 30,
|
|
2575
|
+
local: {
|
|
2576
|
+
banner: $('notif-local-banner').checked,
|
|
2577
|
+
sound: $('notif-local-sound').checked,
|
|
2578
|
+
soundName: $('notif-local-sound-name').value.trim() || 'Glass',
|
|
2579
|
+
volume: Number.isFinite(volume) ? volume : 0.4,
|
|
2580
|
+
icon: $('notif-local-icon').value.trim(),
|
|
2581
|
+
},
|
|
2540
2582
|
};
|
|
2583
|
+
// Only a real ntfy change is sent: any write to channels.* asks for a
|
|
2584
|
+
// daemon restart.
|
|
2585
|
+
const was = (state.notifications || {}).ntfy || {};
|
|
2586
|
+
const ntfy = {};
|
|
2587
|
+
const enabled = $('notif-ntfy-enabled').checked;
|
|
2588
|
+
const server = $('notif-ntfy-server').value.trim() || 'https://ntfy.sh';
|
|
2589
|
+
const topic = $('notif-ntfy-topic').value.trim();
|
|
2590
|
+
const token = $('notif-ntfy-token').value.trim();
|
|
2591
|
+
if (enabled !== !!was.enabled) ntfy.enabled = enabled;
|
|
2592
|
+
if (server !== (was.server || 'https://ntfy.sh')) ntfy.server = server;
|
|
2593
|
+
if (topic) ntfy.topic = topic;
|
|
2594
|
+
if (token) ntfy.token = token;
|
|
2595
|
+
if (Object.keys(ntfy).length) body.ntfy = ntfy;
|
|
2541
2596
|
if (channel && chatId) {
|
|
2542
2597
|
body.destination = { channel, chatId, ...(accountId ? { accountId } : {}) };
|
|
2543
2598
|
}
|
|
@@ -4619,11 +4674,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
4619
4674
|
})();
|
|
4620
4675
|
|
|
4621
4676
|
refresh();
|
|
4622
|
-
`;function ra(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ta({peers:a,localToken:n}))}async function oa(t,e){let a=et();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function sa(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await sr(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Xn(t),r={"GET /api/admin/state":()=>Jn(),"POST /api/admin/agents":()=>tr(n),"PATCH /api/admin/agents":()=>ar(n),"DELETE /api/admin/agents":()=>nr(n),"POST /api/admin/agents/access":()=>Vn(n),"POST /api/admin/channels/telegram":()=>rr(n),"DELETE /api/admin/channels/telegram":()=>Ar(n),"POST /api/admin/channels/telegram/toggle":()=>Mr(n),"POST /api/admin/crons":()=>Ir(n),"DELETE /api/admin/crons":()=>$r(n),"POST /api/admin/config/raw":()=>jr(n),"GET /api/admin/tokens":()=>Yn(),"POST /api/admin/tokens":()=>Qn(n),"DELETE /api/admin/tokens":()=>Zn(n),"POST /api/admin/agents/test":()=>er(n),"POST /api/admin/agents/integrations":()=>ur(n),"DELETE /api/admin/agents/integrations":()=>mr(n),"PATCH /api/admin/agents/integrations":()=>hr(n),"PATCH /api/admin/channels/telegram":()=>or(n),"POST /api/admin/channels/slack":()=>wr(n),"POST /api/admin/channels/slack/toggle":()=>kr(n),"POST /api/admin/channels/discord":()=>_r(n),"POST /api/admin/channels/discord/toggle":()=>Er(n),"POST /api/admin/channels/gitlab":()=>Sr(n),"POST /api/admin/channels/gitlab/toggle":()=>Tr(n),"GET /api/admin/channels/whatsapp/state":()=>be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>be("/webrtc/history"),"POST /api/admin/actions":()=>Wr(n),"DELETE /api/admin/actions":()=>Gr(n),"POST /api/admin/actions/run":()=>Xr(n),"GET /api/admin/channels/whatsapp/chats":()=>be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ne("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Cr(n),"POST /api/admin/webhooks":()=>gr(n),"PATCH /api/admin/webhooks":()=>fr(n),"DELETE /api/admin/webhooks":()=>yr(n),"POST /api/admin/mesh/peers":()=>xr(n),"DELETE /api/admin/mesh/peers":()=>vr(n),"POST /api/admin/mesh/toggle":()=>br(n),"GET /api/admin/files":()=>ir(t),"GET /api/admin/files/read":()=>lr(t),"PUT /api/admin/files":()=>dr(n),"POST /api/admin/files/skill":()=>cr(n),"DELETE /api/admin/files/skill":()=>pr(n),"POST /api/admin/business/orgchart":()=>Lr(n),"DELETE /api/admin/business/orgchart":()=>Rr(n),"POST /api/admin/business/project":()=>Pr(n),"DELETE /api/admin/business/project":()=>Hr(n),"POST /api/admin/business/client":()=>Dr(n),"DELETE /api/admin/business/client":()=>Or(n),"POST /api/admin/business/contact":()=>Nr(n),"DELETE /api/admin/business/contact":()=>Br(n),"POST /api/admin/boards":()=>zr(n),"DELETE /api/admin/boards":()=>qr(n),"POST /api/admin/boards/columns":()=>Fr(n),"DELETE /api/admin/boards/columns":()=>Ur(n),"POST /api/admin/notifications":()=>Jr(n),"POST /api/admin/webhooks/triggers":()=>Vr(n),"POST /api/admin/mesh/health":()=>Kr(n),"GET /api/admin/projects":()=>be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ne("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ne("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ne("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ne("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ne("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ne("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ne("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ne("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Qe(e,404,{error:`unknown admin endpoint: ${o}`});return}let l=await s();Qe(e,200,l)}catch(n){Qe(e,400,{error:n.message||"admin op failed"})}}function Qe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Xn(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 Kn(t){let e=he(process.cwd(),t);if(!Pe(e))return[];let a=[];for(let n of Gn(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(aa(he(e,n.name),"utf-8")))}catch{}return a}function et(){let t=he(process.cwd(),"agentx.json");return Pe(t)?JSON.parse(aa(t,"utf-8")):null}function Jn(){let t=et();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,u])=>({id:d,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(h=>{let f=h.credentials||{},y={};for(let[x,w]of Object.entries(f))typeof w=="string"&&/^[A-Z][A-Z0-9_]*$/.test(w)?y[x]=process.env[w]?"set":"unset":typeof w=="string"&&(y[x]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:f,credStatus:y,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,u])=>({id:d,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},l={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},i=Object.entries(t.crons||{}).map(([d,u])=>({id:d,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},m=t.dashboard?.daemonUrl||"http://localhost:18800",g=t.business||{},_={enabled:!!g.enabled,timezone:g.timezone||"UTC",orgChart:g.orgChart||{},projects:Array.isArray(g.projects)?g.projects:[],contactMap:Array.isArray(g.contactMap)?g.contactMap:[],clients:g.clients&&typeof g.clients=="object"?g.clients:{}},b=t.notifications||{},C={longTaskThreshold:b.longTaskThreshold??30,destination:b.destination||null,on:{taskComplete:b.on?.taskComplete!==!1,taskError:b.on?.taskError!==!1,taskQueued:!!b.on?.taskQueued}},E=[];try{E=Kn(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,h)=>u.id.localeCompare(h.id))}catch{}let S=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:l,crons:i,webhooks:c,mesh:p,daemonUrl:m,nodeName:t.node?.name,business:_,boards:S,notifications:C,actions:E}}function Vn(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=T(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function Yn(){return new ae().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 Qn(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 ae().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Zn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ae().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function er(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=K();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let l=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),i=await l.text(),c;try{c=JSON.parse(i)}catch{c={content:i}}if(!l.ok)throw new Error(c?.error||`daemon HTTP ${l.status}`);return{chatId:n,response:c}}function tr(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=la(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 l=he(process.cwd(),"agents",e),{summary:i}=T(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let m={name:a,workspace:l,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(m.model=o),s&&(m.systemPrompt=s.slice(0,400)),p.agents[e]=m,`added agent "${e}"`}),c=he(l,"CLAUDE.md");if(!Pe(c))try{Un(l,{recursive:!0}),na(c,`# ${a}
|
|
4677
|
+
`;function da(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sa({peers:a,localToken:n}))}async function ca(t,e){let a=et();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function pa(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await mr(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await er(t),r={"GET /api/admin/state":()=>ar(),"POST /api/admin/agents":()=>lr(n),"PATCH /api/admin/agents":()=>dr(n),"DELETE /api/admin/agents":()=>cr(n),"POST /api/admin/agents/access":()=>nr(n),"POST /api/admin/channels/telegram":()=>pr(n),"DELETE /api/admin/channels/telegram":()=>Pr(n),"POST /api/admin/channels/telegram/toggle":()=>Dr(n),"POST /api/admin/crons":()=>Or(n),"DELETE /api/admin/crons":()=>Hr(n),"POST /api/admin/config/raw":()=>Nr(n),"GET /api/admin/tokens":()=>rr(),"POST /api/admin/tokens":()=>or(n),"DELETE /api/admin/tokens":()=>sr(n),"POST /api/admin/agents/test":()=>ir(n),"POST /api/admin/agents/integrations":()=>br(n),"DELETE /api/admin/agents/integrations":()=>yr(n),"PATCH /api/admin/agents/integrations":()=>wr(n),"PATCH /api/admin/channels/telegram":()=>ur(n),"POST /api/admin/channels/slack":()=>Ar(n),"POST /api/admin/channels/slack/toggle":()=>Mr(n),"POST /api/admin/channels/discord":()=>Ir(n),"POST /api/admin/channels/discord/toggle":()=>$r(n),"POST /api/admin/channels/gitlab":()=>jr(n),"POST /api/admin/channels/gitlab/toggle":()=>Lr(n),"GET /api/admin/channels/whatsapp/state":()=>be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>be("/webrtc/history"),"POST /api/admin/actions":()=>Qr(n),"DELETE /api/admin/actions":()=>Zr(n),"POST /api/admin/actions/run":()=>eo(n),"GET /api/admin/channels/whatsapp/chats":()=>be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ne("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Rr(n),"POST /api/admin/webhooks":()=>kr(n),"PATCH /api/admin/webhooks":()=>_r(n),"DELETE /api/admin/webhooks":()=>Cr(n),"POST /api/admin/mesh/peers":()=>Er(n),"DELETE /api/admin/mesh/peers":()=>Sr(n),"POST /api/admin/mesh/toggle":()=>Tr(n),"GET /api/admin/files":()=>hr(t),"GET /api/admin/files/read":()=>gr(t),"PUT /api/admin/files":()=>fr(n),"POST /api/admin/files/skill":()=>xr(n),"DELETE /api/admin/files/skill":()=>vr(n),"POST /api/admin/business/orgchart":()=>Br(n),"DELETE /api/admin/business/orgchart":()=>zr(n),"POST /api/admin/business/project":()=>qr(n),"DELETE /api/admin/business/project":()=>Wr(n),"POST /api/admin/business/client":()=>Fr(n),"DELETE /api/admin/business/client":()=>Ur(n),"POST /api/admin/business/contact":()=>Gr(n),"DELETE /api/admin/business/contact":()=>Xr(n),"POST /api/admin/boards":()=>Kr(n),"DELETE /api/admin/boards":()=>Jr(n),"POST /api/admin/boards/columns":()=>Vr(n),"DELETE /api/admin/boards/columns":()=>Yr(n),"POST /api/admin/notifications":()=>ao(n),"POST /api/admin/webhooks/triggers":()=>no(n),"POST /api/admin/mesh/health":()=>to(n),"GET /api/admin/projects":()=>be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ne("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ne("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ne("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ne("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ne("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ne("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ne("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ne("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Qe(e,404,{error:`unknown admin endpoint: ${o}`});return}let l=await s();Qe(e,200,l)}catch(n){Qe(e,400,{error:n.message||"admin op failed"})}}function Qe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function er(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 tr(t){let e=he(process.cwd(),t);if(!Pe(e))return[];let a=[];for(let n of Zn(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(ia(he(e,n.name),"utf-8")))}catch{}return a}function et(){let t=he(process.cwd(),"agentx.json");return Pe(t)?JSON.parse(ia(t,"utf-8")):null}function ar(){let t=et();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,u])=>({id:d,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(h=>{let f=h.credentials||{},b={};for(let[x,y]of Object.entries(f))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?b[x]=process.env[y]?"set":"unset":typeof y=="string"&&(b[x]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:f,credStatus:b,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,u])=>({id:d,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},l={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},i=Object.entries(t.crons||{}).map(([d,u])=>({id:d,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},m=t.dashboard?.daemonUrl||"http://localhost:18800",g=t.business||{},_={enabled:!!g.enabled,timezone:g.timezone||"UTC",orgChart:g.orgChart||{},projects:Array.isArray(g.projects)?g.projects:[],contactMap:Array.isArray(g.contactMap)?g.contactMap:[],clients:g.clients&&typeof g.clients=="object"?g.clients:{}},S=t.notifications||{},k={longTaskThreshold:S.longTaskThreshold??30,destination:S.destination||null,on:{taskComplete:S.on?.taskComplete!==!1,taskError:S.on?.taskError!==!1,taskQueued:!!S.on?.taskQueued},local:jt(S.local),ntfy:Jt(t.channels?.ntfy)},E=[];try{E=tr(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,h)=>u.id.localeCompare(h.id))}catch{}let T=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:l,crons:i,webhooks:c,mesh:p,daemonUrl:m,nodeName:t.node?.name,business:_,boards:T,notifications:k,actions:E}}function nr(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 rr(){return new ae().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 or(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 ae().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function sr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ae().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function ir(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=K();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let l=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),i=await l.text(),c;try{c=JSON.parse(i)}catch{c={content:i}}if(!l.ok)throw new Error(c?.error||`daemon HTTP ${l.status}`);return{chatId:n,response:c}}function lr(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=ma(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 l=he(process.cwd(),"agents",e),{summary:i}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let m={name:a,workspace:l,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(m.model=o),s&&(m.systemPrompt=s.slice(0,400)),p.agents[e]=m,`added agent "${e}"`}),c=he(l,"CLAUDE.md");if(!Pe(c))try{Yn(l,{recursive:!0}),la(c,`# ${a}
|
|
4623
4678
|
|
|
4624
4679
|
${s||"You are "+a+"."}
|
|
4625
|
-
`)}catch{}return{summary:i}}function ar(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=T(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=la(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 nr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=T(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function rr(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=T(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function or(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=T(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function be(t){let{url:e,headers:a}=tt(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ne(t,e){let{url:a,headers:n}=tt(),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 sr(t,e){try{let{url:a,headers:n}=tt(),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 tt(){let t="http://127.0.0.1:18800",e={};try{let a=K();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ye(t){let a=et()?.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 Ze(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ir(t){let e=Ze(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ue(ye(e));return{agentId:e,...a}}function lr(t){let e=Ze(t,"agent").trim(),a=Ze(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ee(ye(e),a)}function dr(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=Se(ye(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function cr(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=Te(ye(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function pr(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=Ce(ye(e),a);return{summary:`removed skill "${a}"`,...n}}function ur(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 i of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[i];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${i} must be uppercase identifier (got "${c}")`);r[i]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[i,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[i]=c);let{summary:l}=T(i=>{if(!i.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(i.agents[e].integrations=Array.isArray(i.agents[e].integrations)?i.agents[e].integrations:[],i.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return i.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:l}}function mr(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=T(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let l=s.integrations||[],i=l.findIndex(c=>c.kind===a&&c.label===n);if(i===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return l.splice(i,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function hr(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=T(s=>{let l=s.agents?.[e];if(!l)throw new Error(`Unknown agent "${e}"`);let c=(l.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var ia=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function gr(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(!ia.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:l}=T(i=>{if(s){if(!(i.mesh?.peers||[]).find(m=>m.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!i.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(i.webhooks=Array.isArray(i.webhooks)?i.webhooks:[],i.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),i.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:l}}function fr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=T(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&ia.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 xr(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=T(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(l=>l.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 vr(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=T(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function br(t){let e=!!t?.enabled,{summary:a}=T(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function yr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=T(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function wr(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=T(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function kr(t){let e=!!t?.enabled,{summary:a}=T(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function _r(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=T(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Er(t){let e=!!t?.enabled,{summary:a}=T(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Sr(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=T(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function Tr(t){let e=!!t?.enabled,{summary:a}=T(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function Cr(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-PGGYW5AB.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(l){throw new Error(`Invalid cron: ${l.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let l=0;l<3;l++)s=a(e,s,r),o.push(s.toISOString())}catch(l){throw new Error(`Cron preview failed: ${l.message}`)}return{human:n,next:o,timezone:r}}function Ar(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=T(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function Mr(t){let e=!!t?.enabled,{summary:a}=T(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function Ir(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=T(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function $r(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=T(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function jr(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=he(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Pe(n))try{Wn(n,r)}catch{}na(n,JSON.stringify(a,null,2)+`
|
|
4626
|
-
`,"utf-8");try{let s=K().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function la(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Lr(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():"",l=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:i}=T(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:l},`orgChart "${e}" upserted`));return{summary:i}}async function Rr(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=T(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function Pr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=T(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(i=>i.id===e),l={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...l}:o.business.projects.push(l),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function Dr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=T(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let l=!!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},l?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function Or(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=T(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function Hr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=T(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function Nr(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=T(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function Br(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=T(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(l=>{for(let i of a)if(l[i]!==t[i])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 zr(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(i=>i.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:l}=T(i=>{i.boards=Array.isArray(i.boards)?i.boards:[];let c=i.boards.findIndex(m=>m.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let m=i.boards[c];return i.boards[c]={...m,...p,columns:m.columns,labels:m.labels},`board "${e}" updated`}return i.boards.push(p),`board "${e}" added`});return{summary:l}}async function qr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=T(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Fr(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=T(s=>{let i=(Array.isArray(s.boards)?s.boards:[]).find(m=>m.id===e);if(!i)throw new Error(`board "${e}" not found`);i.columns=Array.isArray(i.columns)?i.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=i.columns.findIndex(m=>m.id===a);return p>=0?(i.columns[p]={...i.columns[p],...c},`column "${a}" updated`):(i.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ur(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=T(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(i=>i.id===e);if(!s)throw new Error(`board "${e}" not found`);let l=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(i=>i.id!==a),s.columns.length===l)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Wr(t){let{ActionStore:e}=await import("./store-MCOA6N4F.js"),{actionSchema:a}=await import("./types-H5ENIUIT.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 Gr(t){let{ActionStore:e}=await import("./store-MCOA6N4F.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 Xr(t){let{ActionStore:e}=await import("./store-MCOA6N4F.js"),{runAction:a}=await import("./runner-YRBVNYTY.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 Kr(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=T(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function Jr(t){let{summary:e}=T(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function Vr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=T(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[l,i]of Object.entries(t.triggers))typeof i=="string"&&i.trim()&&(s[String(l)]=i.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}}Ue();import{resolve as Zr}from"path";function da(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
4680
|
+
`)}catch{}return{summary:i}}function dr(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=ma(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 cr(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 pr(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=C(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function ur(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function be(t){let{url:e,headers:a}=tt(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ne(t,e){let{url:a,headers:n}=tt(),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 mr(t,e){try{let{url:a,headers:n}=tt(),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 tt(){let t="http://127.0.0.1:18800",e={};try{let a=K();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ye(t){let a=et()?.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 Ze(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function hr(t){let e=Ze(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ue(ye(e));return{agentId:e,...a}}function gr(t){let e=Ze(t,"agent").trim(),a=Ze(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ee(ye(e),a)}function fr(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=Se(ye(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function xr(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=Te(ye(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function vr(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Ce(ye(e),a);return{summary:`removed skill "${a}"`,...n}}function br(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 i of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[i];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${i} must be uppercase identifier (got "${c}")`);r[i]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[i,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[i]=c);let{summary:l}=C(i=>{if(!i.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(i.agents[e].integrations=Array.isArray(i.agents[e].integrations)?i.agents[e].integrations:[],i.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return i.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:l}}function yr(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!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 l=s.integrations||[],i=l.findIndex(c=>c.kind===a&&c.label===n);if(i===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return l.splice(i,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function wr(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 l=s.agents?.[e];if(!l)throw new Error(`Unknown agent "${e}"`);let c=(l.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var ua=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function kr(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(!ua.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:l}=C(i=>{if(s){if(!(i.mesh?.peers||[]).find(m=>m.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!i.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(i.webhooks=Array.isArray(i.webhooks)?i.webhooks:[],i.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),i.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:l}}function _r(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"&&ua.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 Er(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(l=>l.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 Sr(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 Tr(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 Cr(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 Ar(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 Mr(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 Ir(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 $r(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 jr(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 Lr(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 Rr(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-NRXPVG7P.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(l){throw new Error(`Invalid cron: ${l.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let l=0;l<3;l++)s=a(e,s,r),o.push(s.toISOString())}catch(l){throw new Error(`Cron preview failed: ${l.message}`)}return{human:n,next:o,timezone:r}}function Pr(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 Dr(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 Or(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 Hr(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 Nr(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=he(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Pe(n))try{Qn(n,r)}catch{}la(n,JSON.stringify(a,null,2)+`
|
|
4681
|
+
`,"utf-8");try{let s=K().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function ma(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Br(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():"",l=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:i}=C(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:l},`orgChart "${e}" upserted`));return{summary:i}}async function zr(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 qr(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(i=>i.id===e),l={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...l}:o.business.projects.push(l),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function Fr(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 l=!!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},l?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function Ur(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 Wr(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 Gr(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 Xr(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(l=>{for(let i of a)if(l[i]!==t[i])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 Kr(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(i=>i.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:l}=C(i=>{i.boards=Array.isArray(i.boards)?i.boards:[];let c=i.boards.findIndex(m=>m.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let m=i.boards[c];return i.boards[c]={...m,...p,columns:m.columns,labels:m.labels},`board "${e}" updated`}return i.boards.push(p),`board "${e}" added`});return{summary:l}}async function Jr(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 Vr(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 i=(Array.isArray(s.boards)?s.boards:[]).find(m=>m.id===e);if(!i)throw new Error(`board "${e}" not found`);i.columns=Array.isArray(i.columns)?i.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=i.columns.findIndex(m=>m.id===a);return p>=0?(i.columns[p]={...i.columns[p],...c},`column "${a}" updated`):(i.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Yr(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(i=>i.id===e);if(!s)throw new Error(`board "${e}" not found`);let l=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(i=>i.id!==a),s.columns.length===l)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Qr(t){let{ActionStore:e}=await import("./store-MCOA6N4F.js"),{actionSchema:a}=await import("./types-H5ENIUIT.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 Zr(t){let{ActionStore:e}=await import("./store-MCOA6N4F.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 eo(t){let{ActionStore:e}=await import("./store-MCOA6N4F.js"),{runAction:a}=await import("./runner-YRBVNYTY.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 to(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 ao(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=Lt(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=Vt(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 no(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[l,i]of Object.entries(t.triggers))typeof i=="string"&&i.trim()&&(s[String(l)]=i.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}}Ue();import{resolve as so}from"path";function ha(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
4627
4682
|
|
|
4628
4683
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
4629
4684
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -4678,7 +4733,7 @@ ${s||"You are "+a+"."}
|
|
|
4678
4733
|
<h2>Recent classifications</h2>
|
|
4679
4734
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
4680
4735
|
<div id="recent"></div>
|
|
4681
|
-
</section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
4736
|
+
</section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ro,scripts:`${e}<script>${oo}</script>`})}var ro=`
|
|
4682
4737
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
4683
4738
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
4684
4739
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -4782,7 +4837,7 @@ details {
|
|
|
4782
4837
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
4783
4838
|
}
|
|
4784
4839
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
4785
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
4840
|
+
details[open] summary { margin-bottom: 8px; }`,oo=`
|
|
4786
4841
|
const $ = (id) => document.getElementById(id);
|
|
4787
4842
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
4788
4843
|
|
|
@@ -5002,7 +5057,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5002
5057
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5003
5058
|
|
|
5004
5059
|
refresh();
|
|
5005
|
-
`;function
|
|
5060
|
+
`;function fa(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ha({peers:a,localToken:n}))}async function xa(t,e,a){try{let n=t.method==="GET"?void 0:await fo(t),r=io(),o={"GET /api/admin/graph/state":()=>lo(r),"POST /api/admin/graph/classifications/approve":()=>co(r,n),"POST /api/admin/graph/classifications/reject":()=>po(r,n),"POST /api/admin/graph/nodes":()=>uo(r,n),"PATCH /api/admin/graph/nodes":()=>mo(r,n),"DELETE /api/admin/graph/nodes":()=>ho(r,n),"PUT /api/admin/graph/schema":()=>go(r,n)},s=`${t.method} ${a}`,l=o[s];if(!l){at(e,404,{error:`unknown graph endpoint: ${s}`});return}let i=await l();at(e,200,i)}catch(n){at(e,400,{error:n?.message||"graph op failed"})}}function io(){let t=K(),e=so(process.cwd(),t.graph.baseDir);return new kt({baseDir:e})}function lo(t){let e=K(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let i of r)s.has(i.msgHash)||s.set(i.msgHash,i);let l=[];for(let i of s.values())i.status==="pending"&&!o[i.msgHash]&&l.push(i);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:l,recent:r.slice(0,25),counts:{nodes:n.length,pending:l.length,fingerprints:Object.keys(o).length}}}function co(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=va(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=nt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function po(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=va(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function va(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 uo(t,e){let a=ga(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?ga(String(e.parentId)):null,o=nt({[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 mo(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=nt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function ho(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function go(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 nt(t){let e={};for(let[a,n]of Object.entries(t||{})){if(!n||typeof n!="object")continue;let r={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(r[o]=s);e[a]=r}return e}function ga(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function at(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function fo(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)})}import{resolve as bo}from"path";import{existsSync as yo}from"fs";import wo from"better-sqlite3";function ba(t={}){let e=`<div class="ax-obs">
|
|
5006
5061
|
<header class="ax-obs__head">
|
|
5007
5062
|
<h1>Health</h1>
|
|
5008
5063
|
<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>
|
|
@@ -5124,7 +5179,7 @@ refresh();
|
|
|
5124
5179
|
</div>
|
|
5125
5180
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
5126
5181
|
</section>
|
|
5127
|
-
</div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
5182
|
+
</div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:xo,scripts:`<script>${vo}</script>`})}var xo=`
|
|
5128
5183
|
.ax-obs { padding: 16px 24px; }
|
|
5129
5184
|
.ax-obs__head { margin-bottom: 16px; }
|
|
5130
5185
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -5241,7 +5296,7 @@ refresh();
|
|
|
5241
5296
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
5242
5297
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
5243
5298
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
5244
|
-
`,
|
|
5299
|
+
`,vo=`
|
|
5245
5300
|
(function(){
|
|
5246
5301
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
5247
5302
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -5625,7 +5680,7 @@ refresh();
|
|
|
5625
5680
|
|
|
5626
5681
|
load(current);
|
|
5627
5682
|
})();
|
|
5628
|
-
`;var
|
|
5683
|
+
`;var ka={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 _a(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function rt(t){let e=ka[_a(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 ko(){let t=bo(process.cwd(),".agentx/db.sqlite");if(!yo(t))return null;try{let e=new wo(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Ea(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ba({peers:a}))}function _o(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 re(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Sa(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=ko();if(!r)return re(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=_o(t);if(n==="routing"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
|
|
5629
5684
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
5630
5685
|
FROM route_traces
|
|
5631
5686
|
${l.length?"WHERE "+l.join(" AND "):""}
|
|
@@ -5640,8 +5695,8 @@ refresh();
|
|
|
5640
5695
|
FROM task_history
|
|
5641
5696
|
WHERE ${l.join(" AND ")}
|
|
5642
5697
|
ORDER BY started_at DESC LIMIT @limit
|
|
5643
|
-
`,m=r.db.prepare(c).all(i).map(g=>({...g,plain:
|
|
5644
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
5698
|
+
`,m=r.db.prepare(c).all(i).map(g=>({...g,plain:Ta(g.error)}));return re(e,200,{rows:m}),!0}if(n==="summary"||n==="overview")return re(e,200,Eo(r.db)),!0;if(n==="activity")return re(e,200,So(r.db,{agent:s})),!0;if(n==="cost"){let l=new URL(t.url||"/","http://_"),i=ya(l.searchParams.get("range"));return re(e,200,wa(r.db,i)),!0}if(n==="cost.csv"){let l=new URL(t.url||"/","http://_"),i=ya(l.searchParams.get("range")),c=wa(r.db,i),p=To(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${i||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return re(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return re(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Ta(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(`
|
|
5699
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Eo(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,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),m=y=>p.length?p[Math.min(p.length-1,Math.floor(p.length*y))].duration_ms:0,g=m(.5),_=m(.95),k=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((y,M)=>y+rt(M),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((y,M)=>y+rt(M),0),T=t.prepare(`
|
|
5645
5700
|
SELECT agent_id,
|
|
5646
5701
|
COUNT(*) AS tasks,
|
|
5647
5702
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -5659,12 +5714,12 @@ refresh();
|
|
|
5659
5714
|
WHERE started_at >= ?
|
|
5660
5715
|
GROUP BY channel
|
|
5661
5716
|
ORDER BY tasks DESC
|
|
5662
|
-
`).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(
|
|
5717
|
+
`).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(y=>y.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(y=>y.agent_id)),f=u.filter(y=>!h.has(y)),x=t.prepare(`
|
|
5663
5718
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
5664
5719
|
FROM task_history
|
|
5665
5720
|
WHERE status='error' AND started_at >= ?
|
|
5666
5721
|
ORDER BY started_at DESC LIMIT 5
|
|
5667
|
-
`).all(o).map(
|
|
5722
|
+
`).all(o).map(y=>({...y,plain:Ta(y.error)}));return{kpis:{tasksToday:s,tasksDelta:s-l,errorsToday:i,errorRate:s>0?i/s:0,avgDurationMs:Math.round(c),p50DurationMs:g,p95DurationMs:_,spendToday:k,spendDelta:k-E,idleAgentCount:f.length},perAgent:T,perChannel:d,idleAgents:f,recentErrors:x}}function So(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(`
|
|
5668
5723
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
5669
5724
|
COUNT(*) AS tasks,
|
|
5670
5725
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -5691,7 +5746,7 @@ refresh();
|
|
|
5691
5746
|
WHERE started_at >= @since
|
|
5692
5747
|
GROUP BY agent_id
|
|
5693
5748
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
5694
|
-
`).all({since:n,last24:a});return{hourly:s,daily:l,perAgent:i}}function
|
|
5749
|
+
`).all({since:n,last24:a});return{hourly:s,daily:l,perAgent:i}}function ya(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 wa(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
5695
5750
|
SELECT day, agent_id, model,
|
|
5696
5751
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
5697
5752
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -5699,15 +5754,15 @@ refresh();
|
|
|
5699
5754
|
FROM usage_daily
|
|
5700
5755
|
${a}
|
|
5701
5756
|
ORDER BY day
|
|
5702
|
-
`).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),l=new Date(Date.now()-14*864e5).toISOString().slice(0,10),i=0,c=0,p=0,m=0,g=0,_=0,
|
|
5757
|
+
`).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),l=new Date(Date.now()-14*864e5).toISOString().slice(0,10),i=0,c=0,p=0,m=0,g=0,_=0,S=0,k=0,E=0,T={},d={};for(let w of n){let I=rt(w),L=_a(w.model),R=ka[L],N=(w.tier2_input_tokens||0)/1e6*R.input*.5+(w.tier2_output_tokens||0)/1e6*R.output*.5+(w.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(w.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,Z=(w.input_tokens||0)+(w.tier2_input_tokens||0),B=(w.output_tokens||0)+(w.tier2_output_tokens||0),O=(w.cache_read_tokens||0)+(w.tier2_cache_read_tokens||0),H=(w.cache_create_tokens||0)+(w.tier2_cache_create_tokens||0);m+=I,w.day>=s&&(p+=I,S+=w.tasks||0),w.day>=l&&w.day<s&&(E+=I,k+=w.tasks||0),w.day===r&&(i+=I),w.day===o&&(c+=I),w.day===r&&(g+=N),w.day>=s&&(_+=N);let G=T[w.day]||(T[w.day]={date:w.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});G.tasks+=w.tasks||0,G.input+=Z,G.output+=B,G.cacheRead+=O,G.cacheCreate+=H,G.cost+=I,G.tier2+=N;let z=G.agents[w.agent_id]||(G.agents[w.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:w.model});z.tasks+=w.tasks||0,z.cost+=I,z.tier2+=N,z.input+=Z,z.output+=B,z.cacheRead+=O,z.cacheCreate+=H,w.model&&(z.model=w.model);let X=d[w.agent_id]||(d[w.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:w.model});X.tasks+=w.tasks||0,X.cost+=I,X.tier2+=N,X.input+=Z,X.output+=B,X.cacheRead+=O,X.cacheCreate+=H,w.model&&(X.model=w.model)}let u=Object.values(T).sort((w,I)=>w.date<I.date?-1:1),h=0,f=0,b=0,x=0,y=0,M=0;for(let w of u)h+=w.tasks,f+=w.input,b+=w.output,x+=w.cacheRead,y+=w.cacheCreate,M+=w.cost;let A=Object.entries(d).map(([w,I])=>({agent_id:w,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((w,I)=>I.cost-w.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:i,spendYesterday:c,spend7d:p,spend30d:m,tier2Today:g,tier2_7d:_,tier2PctToday:i>0?g/i:0,spendRange:M,avgDailyRange:u.length?M/u.length:0,tasksRange:h,tokensRange:f+b+x+y,cacheHitRange:x+f>0?x/(x+f):0,costPerTaskRange:h>0?M/h:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:k>0?(S-k)/k:0},days:u,perAgent:A}}function To(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+`
|
|
5703
5758
|
`+a.join(`
|
|
5704
5759
|
`)+`
|
|
5705
|
-
`}import{resolve as
|
|
5760
|
+
`}import{resolve as Co}from"path";import{existsSync as Ao}from"fs";import Mo from"better-sqlite3";function Io(){let t=Co(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ao(t))return null;try{let e=new Mo(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ca>6e4&&(Ca=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Ca=0;function ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $o(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 Aa(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Io();if(!r)return ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=$o(o.searchParams.get("since")),l=o.searchParams.get("source")||"",i=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let m=s!==void 0?"WHERE ts >= @since":"",g=s!==void 0?"WHERE decided_at >= @since":"",_=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${g}`).get({since:s}).n,k=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${g} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${m}`).get({since:s}).n,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
|
|
5706
5761
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
5707
5762
|
LEFT JOIN intent_resolutions r
|
|
5708
5763
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
5709
5764
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
5710
|
-
`).get().n;return ce(e,200,{since:s??null,eventsBySource:_,totalDecisions:
|
|
5765
|
+
`).get().n;return ce(e,200,{since:s??null,eventsBySource:_,totalDecisions:S,decisionsByOutcome:k,totalDivergences:E,divergencesBySource:T,inFlight:d}),!0}if(n==="events"){let m=[],g={limit:p};s!==void 0&&(m.push("ts >= @since"),g.since=s),l&&(m.push("source = @source"),g.source=l),i&&(m.push("project = @project"),g.project=i);let _=`
|
|
5711
5766
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
5712
5767
|
FROM intent_events
|
|
5713
5768
|
${m.length?"WHERE "+m.join(" AND "):""}
|
|
@@ -5729,7 +5784,7 @@ refresh();
|
|
|
5729
5784
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
5730
5785
|
WHERE ${m.join(" AND ")}
|
|
5731
5786
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
5732
|
-
`;return ce(e,200,{rows:r.db.prepare(_).all(g)}),!0}return ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function
|
|
5787
|
+
`;return ce(e,200,{rows:r.db.prepare(_).all(g)}),!0}return ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Ma(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
5733
5788
|
<header class="ax-led__head">
|
|
5734
5789
|
<h1>Intent ledger</h1>
|
|
5735
5790
|
<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>
|
|
@@ -5934,7 +5989,7 @@ refresh();
|
|
|
5934
5989
|
}
|
|
5935
5990
|
load();
|
|
5936
5991
|
})();
|
|
5937
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
5992
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Ia(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
5938
5993
|
<header class="ax-cost__head">
|
|
5939
5994
|
<div>
|
|
5940
5995
|
<h1>Cost</h1>
|
|
@@ -6507,7 +6562,7 @@ refresh();
|
|
|
6507
6562
|
load();
|
|
6508
6563
|
setInterval(load, 30000);
|
|
6509
6564
|
})();
|
|
6510
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
6565
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function $a(t={}){let e=`<div class="ax-pj__root">
|
|
6511
6566
|
<aside class="ax-pj__list">
|
|
6512
6567
|
<header>
|
|
6513
6568
|
<h2>Projects</h2>
|
|
@@ -6534,7 +6589,7 @@ refresh();
|
|
|
6534
6589
|
</header>
|
|
6535
6590
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
6536
6591
|
</section>
|
|
6537
|
-
</div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6592
|
+
</div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:jo,scripts:`<script>${Lo}</script>`})}var jo=`
|
|
6538
6593
|
.ax-pj__root {
|
|
6539
6594
|
display: grid;
|
|
6540
6595
|
grid-template-columns: 360px 1fr;
|
|
@@ -6721,7 +6776,7 @@ refresh();
|
|
|
6721
6776
|
}
|
|
6722
6777
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
6723
6778
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
6724
|
-
`,
|
|
6779
|
+
`,Lo=`
|
|
6725
6780
|
(function(){
|
|
6726
6781
|
const $ = (sel) => document.querySelector(sel);
|
|
6727
6782
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -7371,20 +7426,20 @@ refresh();
|
|
|
7371
7426
|
load();
|
|
7372
7427
|
});
|
|
7373
7428
|
})();
|
|
7374
|
-
`;import{resolve as it,join as
|
|
7429
|
+
`;import{resolve as it,join as Xo}from"path";import{existsSync as lt,readdirSync as Ko,readFileSync as Jo}from"fs";import Vo from"better-sqlite3";var La=String.raw`[\w.-]+(?:/[\w.-]+)+`,Ro=new RegExp(`^(?:chat:)?(${La}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Po=new RegExp(`^\\[(?:GitLab|GitHub) (${La}) `);function ja(t){if(!t)return null;let e=t.match(Ro);return e?e[1]:null}function ot(t){if(!t)return null;let e=t.trimStart().match(Po);return e?e[1]:null}function De(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():ja(typeof n?.chatId=="string"?n.chatId:null)??ja(e)??ot(a)}function Do(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Oe(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Oo=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Ho=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,No=t=>/^issue/i.test(t)?"issue":"mr";function Bo(t){let e=t.subject.match(Oo)??t.inputPreview.trimStart().match(Ho);return e?{kind:No(e[1]),n:Number(e[2])}:null}function zo(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 Ra(t){if(!Do(t.projectId))return[];let e=Bo(t);return e?[e]:zo(t.inputPreview)}var qo=6e4,Fo=5*6e4,Uo=40,Pa=6,Da=new Map;function Oa(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 Ra(n)){let s=Oe(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Uo)return[...e.values()]}}return[...e.values()]}async function Ha(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let l=Oe(s.project,s.ref),i=Da.get(l);i&&n-i.at<(s.github?Fo:qo)?i.item&&(r[l]=i.item):o.push(s)}for(let s=0;s<o.length;s+=Pa)await Promise.all(o.slice(s,s+Pa).map(async l=>{let i=Oe(l.project,l.ref),c=null;try{c=l.github?await Go(l,e,a):await Wo(l,e,a)}catch{}Da.set(i,{at:n,item:c}),c&&(r[i]=c)}));return r}async function Na(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 Wo(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 Na(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let l=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:l&&typeof l.status=="string"?{status:l.status,url:String(l.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function Go(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 Na(`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 dt(){let t=it(process.cwd(),".agentx/intent/ledger.sqlite");if(!lt(t))return null;try{let e=new Vo(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ba>6e4&&(Ba=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Ba=0;function oe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var ge={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 Yo(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in ge)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in ge)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in ge)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 ge)return s}return"workflow"}return t}function Fa(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 Qo(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 Ua(t,e,a){return It(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 Zo(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 i=o.slice(6);if(i&&!st(i))return{id:i,name:i,avatar:F(i),kind:"a2a"}}let l=o||r||s;if(l&&!st(r||o||"")){let i=r||o||s,c=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:i,name:o||r||i,avatar:F(l),kind:c}}}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,l=typeof s.username=="string"?s.username:null,i=typeof s.name=="string"?s.name:null,c=l||(s.id!=null?String(s.id):null)||i;if(c&&!st(l||i||"")){let p=typeof n.channel=="string"?n.channel:"",m=za(p);return{id:c,name:i||l||c,avatar:F(i||l||c),kind:m}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let i=s.username||s.name,c=s.name||s.username;return{id:i,name:c,avatar:F(c),kind:"gitlab"}}let l=o.sender;if(l?.login)return{id:l.login,name:l.login,avatar:F(l.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 l=o||r||s;return{id:s,name:l,avatar:F(l),kind:za(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 za(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function st(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 Wa(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}
|
|
7375
7430
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
7376
|
-
${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
|
|
7431
|
+
${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 es(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 Ga(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
7377
7432
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
7378
7433
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
7379
|
-
`).all(r),s=new Map,l=new Map;if(o.length>0){let x=o.map(I=>I.id),
|
|
7434
|
+
`).all(r),s=new Map,l=new Map;if(o.length>0){let x=o.map(I=>I.id),y=x.map((I,L)=>`@id${L}`).join(","),M=Object.fromEntries(x.map((I,L)=>[`id${L}`,I])),A=t.prepare(`
|
|
7380
7435
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
7381
|
-
FROM intent_decisions WHERE event_id IN (${
|
|
7382
|
-
`).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
|
|
7436
|
+
FROM intent_decisions WHERE event_id IN (${y}) ORDER BY decided_at ASC
|
|
7437
|
+
`).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 w=t.prepare(`
|
|
7383
7438
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
7384
|
-
FROM intent_resolutions WHERE decision_event_id IN (${
|
|
7385
|
-
`).all(M);for(let I of
|
|
7439
|
+
FROM intent_resolutions WHERE decision_event_id IN (${y})
|
|
7440
|
+
`).all(M);for(let I of w)l.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let i=new Map,c=new Map,p=new Map,m=new Map,g=[],_=e?.business?.projects??[],S=e?.business?.contactMap??[],k=Xe(e?.business??{});for(let x of o){let y=null;try{y=JSON.parse(x.raw_json)}catch{}let M=Ua(x.source,y,S),A=Wa(x.source,y),w=x.project??De(y,x.subject,A),I=null,L=null;M?(I=M.client,L=M.project||`${M.client}/_chat`):w&&(I=_e(w,_),L=w);let R=Yo(x.source,x.intent||"",y),N=ge[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:N.label,color:N.color});let Z="__system",B,O=Zo(x.source,x.intent||"",y);if(O){Z=O.id,B=O.kind;let H=M?.displayName||O.name;(!m.has(O.id)||M?.displayName)&&m.set(O.id,{id:O.id,name:H,avatar:F(H),kind:O.kind})}else m.has("__system")||m.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(x.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let G=`${x.id}|${H.decided_by}`,z=l.get(G),X=H.decided_at,bt=z?.resolved_at??null,qe=bt===null,$n=z?.duration_ms??(qe?n-X:0),jn=qe?"active":z?.status==="error"||z?.status==="fail"?"error":"completed",W,xe;if(I)W=I,xe=L;else{let Fe=k.get(H.agent_id);Fe?(W=Fe,xe=`${Fe}/_${x.source}`):(W="unmapped",xe=`unmapped/_${x.source}`)}i.has(W)||i.set(W,{id:W,name:W,color:Fa(W),projects:[]}),c.has(W)||c.set(W,new Set),c.get(W).add(xe),g.push({id:`${x.id}|${H.decided_by}`,agentId:H.agent_id,clientId:W,projectId:xe,channelId:R,initiatorId:Z,initiatorKind:B,subject:es(x.subject),intent:x.intent||"",startedAt:X,resolvedAt:bt,duration:$n,active:qe,outcome:jn,tokens:0,inputPreview:A,system:Qo(H.agent_id,e)})}}let E=[...i.values()].map(x=>({...x,projects:[...c.get(x.id)||[]].sort()})).sort((x,y)=>x.id.localeCompare(y.id)),T=[],d=new Set;if(e){let x=e.business??{},y=M=>{let A=x.orgChart?.[M]?.role,w=A?x.roles?.[A]?.title:void 0;return typeof w=="string"&&w.trim()?w.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let w={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:y(M)};T.push(w),d.add(M)}}for(let x of g)d.has(x.agentId)||(T.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),d.add(x.agentId));T.sort((x,y)=>x.id.localeCompare(y.id));let u=[],h=new Set;for(let[x,y]of Object.entries(ge))u.push({id:x,label:y.label,color:y.color}),h.add(x);for(let x of p.values())h.has(x.id)||u.push(x);let f=[...m.values()];f.find(x=>x.id==="__system")||f.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let b=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:T,channels:u,initiators:f,dispatches:g,forges:{gitlab:typeof b=="string"?b:void 0,github:"https://github.com"}}}function ct(t){let e=dt();if(!e)return null;try{return Ga(e.db,ie,t)}finally{e.close()}}function Xa(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,l=0,i={};for(let{nodeId:c,snap:p}of t){i.gitlab??=p.forges?.gitlab,i.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>l&&(l=p.windowH);for(let m of p.clients){let g=e.get(m.id);if(!g)e.set(m.id,{...m,projects:[...m.projects]});else{let _=Array.from(new Set([...g.projects,...m.projects])).sort();e.set(m.id,{...g,projects:_})}}for(let m of p.agents)a.has(m.id)||a.set(m.id,m);for(let m of p.channels)n.has(m.id)||n.set(m.id,m);for(let m of p.initiators)r.has(m.id)||r.set(m.id,m);for(let m of p.dispatches){let g=ts(m);if(g.clientId!==m.clientId&&!e.has(g.clientId)&&e.set(g.clientId,{id:g.clientId,name:g.clientId,color:Fa(g.clientId),projects:[]}),g.projectId!==m.projectId){let _=e.get(g.clientId);_.projects.includes(g.projectId)||e.set(g.clientId,{..._,projects:[..._.projects,g.projectId].sort()})}o.push({...g,nodeId:c,id:`${c}::${g.id}`})}}return{now:s||Date.now(),windowH:l||6,localNodeId:t[0]?.nodeId,forges:i,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function ts(t){if(t.clientId!=="unmapped")return t;let e=ot(t.inputPreview);if(!e)return t;let a=ie?.business?.projects??[];return{...t,projectId:e,clientId:_e(e,a)}}async function He(t){let e=ie?.channels?.gitlab,a=await Ha(Oa(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 ie=null;function Ka(t){ie=t}async function Ja(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=dt();if(!n)return oe(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Va(parseInt(r.searchParams.get("hours")||"6",10));oe(e,200,await He(Ga(n.db,ie,o)))}catch(r){oe(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var as=5e3;async function pt(t,e,a,n=ct){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
|
|
7386
7441
|
|
|
7387
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
7442
|
+
`);let r=new URL(t.url||"/","http://_"),o=Va(parseInt(r.searchParams.get("hours")||"6",10)),s=!1,l=()=>{s=!0};t.on("close",l),t.on("error",l),e.on("close",l),e.on("error",l);let i=setInterval(()=>{if(!s)try{e.write(`: hb
|
|
7388
7443
|
|
|
7389
7444
|
`)}catch{l()}},25e3);try{for(;!s;){try{let p=await n(o),m=p&&await He(p);if(s)break;m?(e.write(`event: snapshot
|
|
7390
7445
|
`),e.write(`data: ${JSON.stringify(m)}
|
|
@@ -7395,7 +7450,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
7395
7450
|
`)}catch(p){e.write(`event: error
|
|
7396
7451
|
data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
7397
7452
|
|
|
7398
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
7453
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<as;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(i);try{e.end()}catch{}}return!0}function Va(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function ns(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=it(process.cwd(),".agentx/task-history",t,n);if(!lt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=it(process.cwd(),".agentx/task-history",t,o);return lt(s)?qa(s,e,a):null}return qa(r,e,a)}function qa(t,e,a){let n=null,r=1/0;for(let o of Ko(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Jo(Xo(t,o),"utf-8"))}catch{continue}let l=s.startedAt,i;if(typeof l=="number")i=l;else if(typeof l=="string"){let p=Date.parse(l);if(!Number.isFinite(p))continue;i=p}else continue;let c=Math.abs(i-e);c<r&&c<=a&&(n=s,r=c)}return n}async function Ya(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 oe(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),l=r.slice(o+1),i=dt();if(!i)return oe(e,503,{error:"ledger not available"}),!0;try{let c=i.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return oe(e,404,{error:"event not found"}),!0;let p=i.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,l);if(!p)return oe(e,404,{error:"decision not found"}),!0;let m=i.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,l),g=null;try{g=JSON.parse(c.raw_json)}catch{}let _=Wa(c.source,g),S=g&&typeof g=="object"&&(g.text||g.message?.text||g.message?.caption||g.object_attributes?.note||g.object_attributes?.description||g.comment?.body||g.issue?.body||(typeof g.message=="string"?g.message:null)||(typeof g.prompt=="string"?g.prompt:null)||null)||_,k=null,E=null;if(p.agent_id){let b=ns(p.agent_id,p.decided_at);if(b){typeof b.responseText=="string"&&(k=b.responseText);let x=b.transcript;Array.isArray(x)&&(E=x.length)}}let T=ie?.business?.projects??[],d=ie?.business?.contactMap??[],u=Xe(ie?.business??{}),h={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},f=Ua(c.source,g,d);if(f)h={client:f.client,project:f.project||`${f.client}/_chat`,via:`contactMap (channel=${f.channel??"*"}${f.username?` username=${f.username}`:""}${f.chatId?` chatId=${f.chatId}`:""})`};else if(c.project||De(g,c.subject,_)){let b=c.project||De(g,c.subject,_);h={client:_e(b,T),project:b,via:c.project?`project namespace prefix (${b})`:`forge path in chat id / message (${b})`}}else if(p.agent_id){let b=u.get(p.agent_id);b&&(h={client:b,project:`${b}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${b})`})}oe(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:m?.resolved_at??null,durationMs:m?.duration_ms??null,input:S,response:k,transcriptLen:E,resolutionStatus:m?.status??null,resultSummary:m?.result_summary??null,attribution:h})}catch(c){oe(e,500,{error:c?.message??String(c)})}finally{i.close()}return!0}import{existsSync as is,readFileSync as ls}from"fs";import{resolve as Za}from"path";Ue();function Qa(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=rs.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:os,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>${ss}</script>`})}var rs=`
|
|
7399
7454
|
<!-- Breadcrumb -->
|
|
7400
7455
|
<div class="ax-crumb">
|
|
7401
7456
|
<a href="/admin">Settings</a>
|
|
@@ -7984,7 +8039,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
|
7984
8039
|
</div>
|
|
7985
8040
|
</div>
|
|
7986
8041
|
</div>
|
|
7987
|
-
`,
|
|
8042
|
+
`,os=`
|
|
7988
8043
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
7989
8044
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
7990
8045
|
* primitives live in components.css.ts. */
|
|
@@ -8103,7 +8158,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
8103
8158
|
|
|
8104
8159
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
8105
8160
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
8106
|
-
`,
|
|
8161
|
+
`,ss=`
|
|
8107
8162
|
const $ = (id) => document.getElementById(id);
|
|
8108
8163
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
8109
8164
|
|
|
@@ -8957,15 +9012,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
8957
9012
|
/* ===== Boot ===== */
|
|
8958
9013
|
initOptsToggles();
|
|
8959
9014
|
loadAgent();
|
|
8960
|
-
`;function
|
|
8961
|
-
`);return
|
|
8962
|
-
`);return
|
|
9015
|
+
`;function en(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qa({agentId:a,peers:n,localToken:r}))}async function tn(t,e,a){try{let n=t.method==="GET"?void 0:await Is(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){Ne(e,404,{error:`unknown agent endpoint: ${a}`});return}let l=s[1],i=s[2]||"",c=`${t.method} ${i}`,m={"GET ":()=>we(l),"PATCH ":()=>ds(l,n),"PATCH capability":()=>us(l,n),"POST mcp":()=>cs(l,n),"DELETE mcp":()=>ps(l,n),"GET identity":()=>ms(l),"GET identity/file":()=>hs(l,String(o.path||"")),"PUT identity/file":()=>gs(l,n),"GET skills":()=>fs(l),"POST skills":()=>xs(l,n),"DELETE skills":()=>vs(l,n),"GET skills/tree":()=>bs(l,String(o.slug||"")),"GET skills/file":()=>ys(l,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>ws(l,n),"GET skills/deps":()=>ks(l,String(o.slug||"")),"POST skills/install":()=>_s(l,n,t),"POST skills/deps":()=>Es(l,n,t),"GET channels":()=>Ss(l),"GET activity":()=>Ts(l,t),"GET handovers":()=>Cs(l),"POST handovers":()=>As(l,n),"DELETE handovers":()=>Ms(n)}[c];if(!m){Ne(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let g=await m();Ne(e,200,g)}catch(n){Ne(e,400,{error:n?.message||"agent op failed"})}}function an(){let t=Za(process.cwd(),"agentx.json");return is(t)?JSON.parse(ls(t,"utf-8")):null}function U(t){let e=an();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 we(t){let{def:e,cfg:a}=U(t),n=e.workspace?ue(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 ds(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:we(t)}}function cs(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(l=>String(l)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[l,i]of Object.entries(e.env))typeof i=="string"&&(o[l]=i);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(l=>{if(!l.agents?.[t])throw new Error(`Agent "${t}" not found`);return l.agents[t].mcp=l.agents[t].mcp||{},l.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:we(t)}}function ps(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:we(t)}}function us(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,l]of Object.entries(a))l===void 0?delete o[s]:o[s]=l;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:we(t)}}function ms(t){let{def:e}=U(t);return ue(e.workspace)}function hs(t,e){if(!e)throw new Error("path query param required");let{def:a}=U(t);return Ee(a.workspace,e)}function gs(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=U(t);return Se(n.workspace,a,String(e?.content??""))}function fs(t){let{def:e}=U(t),a=ue(e.workspace);return{skills:a.skills,workspace:a.workspace}}function xs(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=U(t);return Te(n.workspace,a,{title:e?.title,content:e?.content})}function vs(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=U(t);return Ce(n.workspace,a)}function bs(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t),n=Ot(a.workspace,e),r=Ae(a.workspace,e);return{slug:e,tree:n,deps:r}}function ys(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=U(t);return Ht(n.workspace,e,a)}function ws(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=U(t);return Nt(r.workspace,a,n,String(e?.content??""))}function ks(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t);return Ae(a.workspace,e)}async function _s(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=nn(e?.worker),{def:o}=U(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
|
|
9016
|
+
`);return rn(a,r,s,`install-${n}:${Date.now()}`)}async function Es(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=nn(e?.worker),{def:o}=U(t),s=Ae(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 l=Za(o.workspace,".claude","skills",n),i=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${l}`,`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(`
|
|
9017
|
+
`);return rn(a,r,i,`deps-${t}-${n}:${Date.now()}`)}function nn(t){if(t&&typeof t=="string")return t;let e=K();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function rn(t,e,a,n){let r=K(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},l=t.headers.authorization;l?s.Authorization=String(l):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let i=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await i.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!i.ok)throw new Error(p?.error||`daemon /task HTTP ${i.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Ss(t){let e=an(),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 Ts(t,e){try{let n=(K().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(l=>l.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 ut(){return new _t}function Cs(t){let e=ut(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function As(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,l=e?.summary?String(e.summary):void 0,i=e?.expiresAt?String(e.expiresAt):void 0,c=ut().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:l,expiresAt:i,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function Ms(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:ut().remove(e,a,n)?"Released":"No active handover for that chat"}}function Ne(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Is(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 pe={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 on=[{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 mt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(pe)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
8963
9018
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
8964
9019
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
8965
9020
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
8966
9021
|
<main id="grid" class="ax-live__body"></main>
|
|
8967
9022
|
</div>
|
|
8968
|
-
`;return $({title:`${pe.brand} \xB7 ${pe.subtitle}`,activeTab:"live",subtitle:pe.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css
|
|
9023
|
+
`;return $({title:`${pe.brand} \xB7 ${pe.subtitle}`,activeTab:"live",subtitle:pe.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:$s,scripts:e+`<script>${js}</script>`,headExtras:`<script>
|
|
8969
9024
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
8970
9025
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
8971
9026
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -8976,7 +9031,7 @@ loadAgent();
|
|
|
8976
9031
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
8977
9032
|
right.insertBefore(extras, right.firstChild);
|
|
8978
9033
|
});
|
|
8979
|
-
</script>`})}var
|
|
9034
|
+
</script>`})}var $s=`
|
|
8980
9035
|
/* --- Page frame --- */
|
|
8981
9036
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
8982
9037
|
|
|
@@ -9177,7 +9232,7 @@ loadAgent();
|
|
|
9177
9232
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
9178
9233
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
9179
9234
|
}
|
|
9180
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
9235
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,js=`
|
|
9181
9236
|
'use strict';
|
|
9182
9237
|
|
|
9183
9238
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -9680,7 +9735,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
9680
9735
|
});
|
|
9681
9736
|
}
|
|
9682
9737
|
|
|
9683
|
-
`;var
|
|
9738
|
+
`;var sn=`
|
|
9684
9739
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
9685
9740
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
9686
9741
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -9818,6 +9873,10 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
9818
9873
|
.mx-empty{padding:28px 18px;text-align:center;color:var(--ax-muted);font-size:12px;border:1px dashed var(--ax-border-2);border-radius:var(--ax-radius-lg);background:var(--ax-surface)}
|
|
9819
9874
|
.mx-link{display:inline-block;margin-top:14px;color:var(--ax-accent);font-size:12px;font-weight:600;text-decoration:none}
|
|
9820
9875
|
.mx-link:hover{text-decoration:underline}
|
|
9876
|
+
.mx-run-links{list-style:none;margin:0;padding:0;display:grid;gap:6px;font-size:12px}
|
|
9877
|
+
.mx-run-links li{display:flex;align-items:center;gap:10px}
|
|
9878
|
+
.mx-run-links li span:first-child{font-family:var(--ax-mono);color:var(--ax-muted);min-width:84px}
|
|
9879
|
+
.mx-run-links .mx-link{margin:0 0 0 auto}
|
|
9821
9880
|
.mx-scrim{position:fixed;inset:0;background:color-mix(in oklch,var(--ax-bg) 55%,black);z-index:29}
|
|
9822
9881
|
.mx-drawer{position:fixed;z-index:30;top:0;right:0;width:min(520px,calc(100vw - 20px));height:100vh;box-sizing:border-box;background:var(--ax-surface);border-left:var(--ax-border-w) solid var(--ax-border-2);transform:translateX(102%);transition:transform 180ms ease;overflow:auto;box-shadow:-12px 0 36px rgba(0,0,0,.2)}
|
|
9823
9882
|
.mx-drawer.is-open{transform:translateX(0)}
|
|
@@ -9850,7 +9909,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
9850
9909
|
.mx-summary{max-width:56vw}
|
|
9851
9910
|
}
|
|
9852
9911
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
9853
|
-
`;var
|
|
9912
|
+
`;var ln=`<script>
|
|
9854
9913
|
window.MX=(function(){
|
|
9855
9914
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
9856
9915
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -9959,7 +10018,7 @@ window.MX=(function(){
|
|
|
9959
10018
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
9960
10019
|
setHealth:setHealth,get:get};
|
|
9961
10020
|
})();
|
|
9962
|
-
</script>`;var
|
|
10021
|
+
</script>`;var dn=`<script>
|
|
9963
10022
|
window.MXD=(function(){
|
|
9964
10023
|
function el(id){return document.getElementById(id)}
|
|
9965
10024
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -10173,7 +10232,7 @@ window.MXD=(function(){
|
|
|
10173
10232
|
|
|
10174
10233
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
10175
10234
|
})();
|
|
10176
|
-
</script>`;var
|
|
10235
|
+
</script>`;var cn=`<script>
|
|
10177
10236
|
(function(){
|
|
10178
10237
|
var LANES=[
|
|
10179
10238
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -10489,13 +10548,13 @@ window.MXD=(function(){
|
|
|
10489
10548
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
10490
10549
|
load();
|
|
10491
10550
|
})();
|
|
10492
|
-
</script>`;var
|
|
10551
|
+
</script>`;var pn=`<script>
|
|
10493
10552
|
(function(){
|
|
10494
10553
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
10495
10554
|
var esc=MX.esc;
|
|
10496
10555
|
function initials(v){return String(v||'?').split(/[-_ ]+/).slice(0,2).map(function(x){return x.charAt(0)}).join('').toUpperCase()}
|
|
10497
10556
|
function badge(status){
|
|
10498
|
-
var kind=(status==='success'||status==='active'||status==='online')?'ax-badge--live'
|
|
10557
|
+
var kind=(status==='success'||status==='active'||status==='online'||status==='running')?'ax-badge--live'
|
|
10499
10558
|
:(status==='failed'||status==='timeout'||status==='offline')?'ax-badge--err'
|
|
10500
10559
|
:status==='retrying'?'ax-badge--warn':'ax-badge--ghost';
|
|
10501
10560
|
return '<span class="ax-badge '+kind+'">'+esc(status)+'</span>';
|
|
@@ -10513,6 +10572,35 @@ window.MXD=(function(){
|
|
|
10513
10572
|
function detail(data){
|
|
10514
10573
|
return '<div class="mx-detail">'+MX.fields(data.fields)+(data.note?'<pre>'+esc(data.note)+'</pre>':'')+'</div>';
|
|
10515
10574
|
}
|
|
10575
|
+
// A cron run opens on the node's Task page: live while it runs (SSE,
|
|
10576
|
+
// follow-up, stop), archived once done (Send resumes its cron chat).
|
|
10577
|
+
// Command jobs never reach an agent, so their runs have no task to open.
|
|
10578
|
+
var RUN_LINK_LIMIT=10;
|
|
10579
|
+
function runHref(x,taskId,archived){
|
|
10580
|
+
return '/tasks/'+encodeURIComponent(taskId)+'?node='+encodeURIComponent(x.node.url)
|
|
10581
|
+
+'&agent='+encodeURIComponent(x.job.agent)
|
|
10582
|
+
+'&name='+encodeURIComponent((x.agent&&x.agent.name)||x.job.agent)
|
|
10583
|
+
+'&channel=cron'+(archived?'&archived=1':'');
|
|
10584
|
+
}
|
|
10585
|
+
/** The in-flight run of a job: the agent's running task in its cron chat. */
|
|
10586
|
+
function liveRun(n,job){
|
|
10587
|
+
var agent=(n.agents||[]).find(function(a){return a.id===job.agent});
|
|
10588
|
+
return ((agent&&agent.runningTasks)||[]).find(function(t){
|
|
10589
|
+
return t.channel==='cron'&&t.chatId==='cron:'+job.id});
|
|
10590
|
+
}
|
|
10591
|
+
function runLinks(x){
|
|
10592
|
+
if(x.job.kind==='command')return '';
|
|
10593
|
+
var html='';
|
|
10594
|
+
if(x.live)html+='<a class="mx-link" href="'+runHref(x,x.live.id,false)+'">Watch live run</a>';
|
|
10595
|
+
var linked=x.history.filter(function(r){return r.taskId}).slice(0,RUN_LINK_LIMIT);
|
|
10596
|
+
if(linked.length){
|
|
10597
|
+
html+=MX.section('Runs today','<ul class="mx-run-links">'+linked.map(function(r){
|
|
10598
|
+
return '<li><span>'+esc(new Date(r.startedAt).toLocaleTimeString())+'</span>'+badge(r.status)
|
|
10599
|
+
+'<a class="mx-link" href="'+runHref(x,r.taskId,true)+'">Open</a></li>'}).join('')+'</ul>'
|
|
10600
|
+
+(x.history.length>linked.length?'<p class="mx-note">Only the latest '+RUN_LINK_LIMIT+' runs with a task are listed. Runs recorded before this node linked tasks have none.</p>':''));
|
|
10601
|
+
}
|
|
10602
|
+
return html;
|
|
10603
|
+
}
|
|
10516
10604
|
showAll.addEventListener('click',function(){
|
|
10517
10605
|
expanded=!expanded;
|
|
10518
10606
|
document.querySelectorAll('#mx-runs .mx-item').forEach(function(el,i){el.hidden=!expanded&&i>=8});
|
|
@@ -10539,11 +10627,13 @@ window.MXD=(function(){
|
|
|
10539
10627
|
var cards=[];
|
|
10540
10628
|
nodes.forEach(function(n){(n.crons||[]).forEach(function(job){
|
|
10541
10629
|
var history=(n.cronRuns||[]).filter(function(r){return r.jobId===job.id}),latest=history[0];
|
|
10542
|
-
var
|
|
10543
|
-
var
|
|
10630
|
+
var live=job.kind==='command'?null:liveRun(n,job);
|
|
10631
|
+
var status=live?'running':!job.enabled?'disabled':latest?latest.status:job.retryPending?'retrying':'waiting';
|
|
10632
|
+
var summary=live?'Running now, started '+MX.age(live.startedAt)
|
|
10633
|
+
:latest?(latest.errorSummary||latest.responseSummary||'No summary')
|
|
10544
10634
|
:(job.enabled?'No attempt persisted today':'Schedule disabled');
|
|
10545
10635
|
var agent=(n.agents||[]).find(function(a){return a.id===job.agent});
|
|
10546
|
-
cards.push({node:n,job:job,run:latest,status:status,summary:summary,agent:agent});
|
|
10636
|
+
cards.push({node:n,job:job,run:latest,history:history,live:live,status:status,summary:summary,agent:agent});
|
|
10547
10637
|
})});
|
|
10548
10638
|
var root=document.getElementById('mx-runs');
|
|
10549
10639
|
document.getElementById('mx-run-count').textContent=cards.length+' schedules';
|
|
@@ -10552,7 +10642,7 @@ window.MXD=(function(){
|
|
|
10552
10642
|
root.innerHTML=cards.map(function(x,i){
|
|
10553
10643
|
var sub='<code>'+esc(x.job.agent)+'</code><span>'+esc(x.job.schedule)+'</span>'
|
|
10554
10644
|
+'<span class="mx-summary">'+esc(x.summary)+'</span>';
|
|
10555
|
-
var variant=x.status==='success'?'teal':(x.status==='failed'||x.status==='timeout')?'coral':'plain';
|
|
10645
|
+
var variant=x.status==='running'?'blue':x.status==='success'?'teal':(x.status==='failed'||x.status==='timeout')?'coral':'plain';
|
|
10556
10646
|
return item({title:x.job.id,slug:x.node.name,sub:sub},badge(x.status),
|
|
10557
10647
|
'data-run="'+i+'"'+(!expanded&&i>=8?' hidden':''),variant);
|
|
10558
10648
|
}).join('');
|
|
@@ -10568,7 +10658,7 @@ window.MXD=(function(){
|
|
|
10568
10658
|
['Duration',x.run?MX.dur(x.run.duration):'-'],
|
|
10569
10659
|
['Retry',x.run&&x.run.isRetry?'Attempt '+x.run.retryAttempt:'No'],
|
|
10570
10660
|
['Task ID',(x.run&&x.run.taskId)||'-'],['Session ID',(x.run&&x.run.sessionId)||'-']
|
|
10571
|
-
],note:x.summary}));
|
|
10661
|
+
],note:x.summary})+runLinks(x));
|
|
10572
10662
|
});
|
|
10573
10663
|
});
|
|
10574
10664
|
}
|
|
@@ -10631,22 +10721,190 @@ window.MXD=(function(){
|
|
|
10631
10721
|
var date=new Date().toLocaleDateString('en-CA');
|
|
10632
10722
|
var tz=Intl.DateTimeFormat().resolvedOptions().timeZone||'UTC';
|
|
10633
10723
|
MX.get('/api/mesh?date='+encodeURIComponent(date)+'&timezone='+encodeURIComponent(tz))
|
|
10634
|
-
.then(render)
|
|
10724
|
+
.then(function(s){render(s);document.dispatchEvent(new CustomEvent('mx:snapshot',{detail:s}))})
|
|
10635
10725
|
.catch(function(e){document.getElementById('mx-updated').textContent='Fleet snapshot unavailable: '+e.message});
|
|
10636
10726
|
}
|
|
10637
10727
|
load();setInterval(load,5000);
|
|
10638
10728
|
})();
|
|
10639
|
-
</script>`;var
|
|
10729
|
+
</script>`;var un=`
|
|
10730
|
+
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
10731
|
+
.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}
|
|
10732
|
+
.mx-rt-wrap > .mx-empty{border:0}
|
|
10733
|
+
.mx-rt{width:100%;border-collapse:collapse;font-size:12px}
|
|
10734
|
+
.mx-rt th,.mx-rt td{padding:8px 10px;text-align:left;vertical-align:top;border-bottom:1px solid var(--ax-border)}
|
|
10735
|
+
.mx-rt thead th{font:600 10px var(--ax-mono);letter-spacing:.05em;text-transform:uppercase;color:var(--ax-muted);background:var(--ax-surface-2)}
|
|
10736
|
+
.mx-rt tbody:last-child tr:last-child td{border-bottom:0}
|
|
10737
|
+
.mx-rt-node th{background:var(--ax-surface-2);font-size:12px;font-weight:600}
|
|
10738
|
+
.mx-rt-node small{margin-left:8px;font:400 10px var(--ax-mono);color:var(--ax-muted)}
|
|
10739
|
+
.mx-rt-node[data-offline="1"] th{color:var(--mx-crit)}
|
|
10740
|
+
.mx-rt-msg td{color:var(--ax-muted);font-size:11px}
|
|
10741
|
+
.mx-rt-name{display:block;max-width:240px;padding:0;border:0;background:none;color:var(--ax-text);font:600 12px var(--ax-font);text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
10742
|
+
.mx-rt-name:hover{color:var(--ax-accent)}
|
|
10743
|
+
.mx-rt-name:focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:2px}
|
|
10744
|
+
.mx-rt-sub{display:block;font:10px var(--ax-mono);color:var(--ax-muted)}
|
|
10745
|
+
.mx-rt code{font:11px var(--ax-mono);color:var(--ax-text-2);word-break:break-word}
|
|
10746
|
+
.mx-rt-muted{color:var(--ax-muted)}
|
|
10747
|
+
.mx-rt tr[data-attn="critical"] td:first-child{box-shadow:inset 3px 0 0 var(--mx-crit)}
|
|
10748
|
+
.mx-rt tr[data-attn="warning"] td:first-child{box-shadow:inset 3px 0 0 var(--mx-warn)}
|
|
10749
|
+
.mx-rt tr[data-attn="info"] td:first-child{box-shadow:inset 3px 0 0 var(--ax-border-2)}
|
|
10750
|
+
.mx-rt tr[data-enabled="0"] td{color:var(--ax-muted)}
|
|
10751
|
+
.mx-flags{display:flex;flex-wrap:wrap;gap:4px}
|
|
10752
|
+
.mx-flag{display:inline-flex;align-items:center;gap:5px;padding:1px 7px;border:1px solid var(--ax-border-2);border-radius:var(--ax-radius-pill);font:600 10px var(--ax-mono);color:var(--ax-text-2);white-space:nowrap}
|
|
10753
|
+
.mx-flag i{width:8px;height:8px;font-style:normal;flex:0 0 auto}
|
|
10754
|
+
.mx-flag--critical i{background:var(--mx-crit);border-radius:1px;transform:rotate(45deg)}
|
|
10755
|
+
.mx-flag--warning i{background:var(--mx-warn);clip-path:polygon(50% 0,100% 100%,0 100%)}
|
|
10756
|
+
.mx-flag--info i{border:1.5px solid var(--ax-muted);border-radius:50%;box-sizing:border-box}
|
|
10757
|
+
.mx-flag--ok i{background:var(--mx-good);border-radius:50%}
|
|
10758
|
+
.mx-rt-cap{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
|
|
10759
|
+
.mx-rt-why{margin:0;padding:0;list-style:none;display:grid;gap:8px;font-size:12px}
|
|
10760
|
+
@media(max-width:860px){
|
|
10761
|
+
.mx-rt thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
|
|
10762
|
+
.mx-rt,.mx-rt tbody,.mx-rt tr,.mx-rt td,.mx-rt th{display:block;width:100%;box-sizing:border-box}
|
|
10763
|
+
.mx-rt tr{border-bottom:1px solid var(--ax-border);padding:6px 0}
|
|
10764
|
+
.mx-rt td{border:0;padding:3px 12px;display:grid;grid-template-columns:84px minmax(0,1fr);gap:8px}
|
|
10765
|
+
.mx-rt td::before{content:attr(data-label);font:10px var(--ax-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--ax-muted)}
|
|
10766
|
+
.mx-rt td:first-child{display:block}.mx-rt td:first-child::before{content:none}
|
|
10767
|
+
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
10768
|
+
.mx-rt-name{max-width:100%}
|
|
10769
|
+
}
|
|
10770
|
+
`,mn=`<script>
|
|
10771
|
+
(function(){
|
|
10772
|
+
var root=document.getElementById('mx-routines');
|
|
10773
|
+
var bar=document.getElementById('mx-rt-filter');
|
|
10774
|
+
var count=document.getElementById('mx-rt-count');
|
|
10775
|
+
if(!root||!bar)return;
|
|
10776
|
+
var esc=MX.esc,rows=[],last=null,filter='all';
|
|
10777
|
+
try{filter=localStorage.getItem('mx-rt-filter')||'all'}catch(e){}
|
|
10778
|
+
var LABEL={failing:'Failing','overdue':'Overdue','dormant':'Dormant','never-ran':'Never ran','disabled-long':'Disabled long'};
|
|
10779
|
+
var SEVERITY={failing:'critical','overdue':'warning','dormant':'warning','never-ran':'warning','disabled-long':'info'};
|
|
10780
|
+
|
|
10781
|
+
function until(iso){
|
|
10782
|
+
if(!iso)return '-';var s=(new Date(iso).getTime()-Date.now())/1000;
|
|
10783
|
+
if(s<=0)return 'due';if(s<3600)return 'in '+Math.ceil(s/60)+'m';
|
|
10784
|
+
if(s<86400)return 'in '+Math.round(s/3600)+'h';return 'in '+Math.round(s/86400)+'d';
|
|
10785
|
+
}
|
|
10786
|
+
function flagChip(f,r){
|
|
10787
|
+
var sev=SEVERITY[f.reason]||'info';
|
|
10788
|
+
var text=LABEL[f.reason]||f.reason;
|
|
10789
|
+
if(f.reason==='failing')text+=' x'+r.consecutiveFailures;
|
|
10790
|
+
return '<span class="mx-flag mx-flag--'+sev+'" title="'+esc(f.detail)+'"><i aria-hidden="true"></i>'+esc(text)+'</span>';
|
|
10791
|
+
}
|
|
10792
|
+
function health(r){
|
|
10793
|
+
if(r.flags&&r.flags.length)return '<span class="mx-flags">'+r.flags.map(function(f){return flagChip(f,r)}).join('')+'</span>';
|
|
10794
|
+
return r.enabled?'<span class="mx-flag mx-flag--ok"><i aria-hidden="true"></i>OK</span>':'<span class="mx-rt-muted">-</span>';
|
|
10795
|
+
}
|
|
10796
|
+
function trigger(r){
|
|
10797
|
+
var t=r.trigger||{};
|
|
10798
|
+
if(r.kind==='schedule')return '<code>'+esc(t.schedule||'?')+'</code>'+(t.timezone&&t.timezone!=='UTC'?' <span class="mx-rt-sub">'+esc(t.timezone)+'</span>':'');
|
|
10799
|
+
var f=(t.filters||[]);
|
|
10800
|
+
return '<code>'+esc(t.event||'?')+'</code>'+(f.length?'<span class="mx-rt-sub">'+esc(f.join(' \xB7 '))+'</span>':'');
|
|
10801
|
+
}
|
|
10802
|
+
function lastRun(r){
|
|
10803
|
+
if(!r.lastRun)return '<span class="mx-rt-muted">never</span>';
|
|
10804
|
+
return esc(r.lastRun.status)+' <span class="mx-rt-sub">'+esc(MX.age(r.lastRun.at))+'</span>';
|
|
10805
|
+
}
|
|
10806
|
+
function matches(r){
|
|
10807
|
+
if(filter==='attention')return !!r.attention;
|
|
10808
|
+
if(filter==='schedule'||filter==='event')return r.kind===filter;
|
|
10809
|
+
return true;
|
|
10810
|
+
}
|
|
10811
|
+
function cell(label,html){return '<td data-label="'+label+'">'+html+'</td>'}
|
|
10812
|
+
|
|
10813
|
+
function render(s){
|
|
10814
|
+
last=s;rows=[];
|
|
10815
|
+
var nodes=s.nodes||[],total=0,attention=0,html='';
|
|
10816
|
+
nodes.forEach(function(n){
|
|
10817
|
+
var list=n.reachable&&Array.isArray(n.routines)?n.routines:[];
|
|
10818
|
+
total+=list.length;
|
|
10819
|
+
attention+=list.filter(function(r){return r.attention==='critical'||r.attention==='warning'}).length;
|
|
10820
|
+
var shown=list.filter(matches);
|
|
10821
|
+
var needs=list.filter(function(r){return !!r.attention}).length;
|
|
10822
|
+
var headNote=!n.reachable?'unreachable':!Array.isArray(n.routines)?'not reported'
|
|
10823
|
+
:MX.plural(list.length,'routine')+(needs?' \xB7 '+needs+' flagged':'');
|
|
10824
|
+
html+='<tbody><tr class="mx-rt-node"'+(n.reachable?'':' data-offline="1"')+'><th colspan="8" scope="rowgroup">'
|
|
10825
|
+
+esc(n.name)+'<small>'+esc(headNote)+'</small></th></tr>';
|
|
10826
|
+
if(!n.reachable){
|
|
10827
|
+
html+='<tr class="mx-rt-msg"><td colspan="8">Routines unknown while this node is unreachable'+(n.error?' ('+esc(n.error)+')':'')+'.</td></tr>';
|
|
10828
|
+
}else if(!Array.isArray(n.routines)){
|
|
10829
|
+
html+='<tr class="mx-rt-msg"><td colspan="8">This node does not report routines yet. Its schedules still appear under Today's automations.</td></tr>';
|
|
10830
|
+
}else if(!shown.length){
|
|
10831
|
+
html+='<tr class="mx-rt-msg"><td colspan="8">'+(list.length?'Nothing matches this filter.':'No schedules or triggered workflows.')+'</td></tr>';
|
|
10832
|
+
}
|
|
10833
|
+
shown.forEach(function(r){
|
|
10834
|
+
var i=rows.push({node:n,routine:r})-1;
|
|
10835
|
+
html+='<tr'+(r.attention?' data-attn="'+r.attention+'"':'')+' data-enabled="'+(r.enabled?1:0)+'">'
|
|
10836
|
+
+'<td><button type="button" class="mx-rt-name" data-rt="'+i+'" title="'+esc(r.name)+'">'+esc(r.name)+'</button>'
|
|
10837
|
+
+'<span class="mx-rt-sub">'+esc(r.source==='cron'?'cron job':'workflow')+'</span></td>'
|
|
10838
|
+
+cell('Kind',esc(r.kind))
|
|
10839
|
+
+cell('Trigger',trigger(r))
|
|
10840
|
+
+cell('Agent',r.agent?'<code>'+esc(r.agent)+'</code>':'<span class="mx-rt-muted">-</span>')
|
|
10841
|
+
+cell('State',esc(r.state))
|
|
10842
|
+
+cell('Next',r.kind==='schedule'?esc(until(r.nextRunAt)):'<span class="mx-rt-muted">on event</span>')
|
|
10843
|
+
+cell('Last run',lastRun(r))
|
|
10844
|
+
+cell('Health',health(r))
|
|
10845
|
+
+'</tr>';
|
|
10846
|
+
});
|
|
10847
|
+
html+='</tbody>';
|
|
10848
|
+
});
|
|
10849
|
+
count.textContent=MX.plural(total,'routine');
|
|
10850
|
+
count.textContent+=attention?' \xB7 '+attention+' flagged':'';
|
|
10851
|
+
root.innerHTML=nodes.length
|
|
10852
|
+
?'<table class="mx-rt"><caption class="mx-rt-cap">Routines by node</caption><thead><tr>'
|
|
10853
|
+
+'<th scope="col">Routine</th><th scope="col">Kind</th><th scope="col">Trigger</th><th scope="col">Agent</th>'
|
|
10854
|
+
+'<th scope="col">State</th><th scope="col">Next</th><th scope="col">Last run</th><th scope="col">Health</th>'
|
|
10855
|
+
+'</tr></thead>'+html+'</table>'
|
|
10856
|
+
:'<div class="mx-empty">No nodes in the fleet snapshot.</div>';
|
|
10857
|
+
}
|
|
10858
|
+
|
|
10859
|
+
function openRoutine(x){
|
|
10860
|
+
var r=x.routine,t=r.trigger||{};
|
|
10861
|
+
var fields=[['Node',x.node.name],['Routine ID',r.id],['Source',r.source==='cron'?'Cron job':'Workflow'],
|
|
10862
|
+
['Kind',r.kind],['State',r.state],['Agent',r.agent||'-']];
|
|
10863
|
+
if(r.kind==='schedule')fields.push(['Schedule',t.schedule||'-'],['Timezone',t.timezone||'UTC'],
|
|
10864
|
+
['Next fire',r.nextRunAt?new Date(r.nextRunAt).toLocaleString():'-']);
|
|
10865
|
+
else fields.push(['Event',t.event||'-'],['Filters',(t.filters||[]).join(', ')||'none']);
|
|
10866
|
+
fields.push(['Last run',r.lastRun?r.lastRun.status+', '+new Date(r.lastRun.at).toLocaleString():'Never'],
|
|
10867
|
+
['Last success',r.lastSuccessAt?new Date(r.lastSuccessAt).toLocaleString():'-'],
|
|
10868
|
+
['Failures in a row',r.consecutiveFailures],['Runs inspected',r.sampledRuns]);
|
|
10869
|
+
var flags=(r.flags||[]).length
|
|
10870
|
+
?'<ul class="mx-rt-why">'+r.flags.map(function(f){return '<li>'+flagChip(f,r)+' '+esc(f.detail)+'</li>'}).join('')+'</ul>'
|
|
10871
|
+
:'<p class="mx-note">No staleness signal.</p>';
|
|
10872
|
+
MX.open('Routine',r.name,'<div class="mx-detail">'+MX.fields(fields)
|
|
10873
|
+
+MX.section('Signals',flags)
|
|
10874
|
+
+(r.lastRun&&r.lastRun.summary?MX.section('Last error',
|
|
10875
|
+
'<pre>'+esc(r.lastRun.summary)+'</pre>'):'')+'</div>');
|
|
10876
|
+
}
|
|
10877
|
+
|
|
10878
|
+
root.addEventListener('click',function(e){
|
|
10879
|
+
var el=e.target.closest?e.target.closest('[data-rt]'):null;
|
|
10880
|
+
if(el&&rows[Number(el.dataset.rt)])openRoutine(rows[Number(el.dataset.rt)]);
|
|
10881
|
+
});
|
|
10882
|
+
function syncBar(){
|
|
10883
|
+
bar.querySelectorAll('[data-rt-filter]').forEach(function(b){
|
|
10884
|
+
b.setAttribute('aria-pressed',String(b.dataset.rtFilter===filter))});
|
|
10885
|
+
}
|
|
10886
|
+
bar.addEventListener('click',function(e){
|
|
10887
|
+
var b=e.target.closest?e.target.closest('[data-rt-filter]'):null;
|
|
10888
|
+
if(!b)return;
|
|
10889
|
+
filter=b.dataset.rtFilter;syncBar();
|
|
10890
|
+
try{localStorage.setItem('mx-rt-filter',filter)}catch(err){}
|
|
10891
|
+
if(last)render(last);
|
|
10892
|
+
});
|
|
10893
|
+
if(!bar.querySelector('[data-rt-filter="'+filter+'"]'))filter='all';
|
|
10894
|
+
syncBar();
|
|
10895
|
+
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
10896
|
+
})();
|
|
10897
|
+
</script>`;var Y={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function Q(t,e,a,n,r=""){return q({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Ls=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Rs=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Ps=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function hn(t){let e=Me({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Ie([{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">
|
|
10640
10898
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
10641
|
-
${
|
|
10899
|
+
${Rs.map((l,i)=>`<button class="mx-tab" type="button" role="tab" id="mx-tab-${l.id}" aria-controls="mx-view-${l.id}" aria-selected="${i===0}" data-view="${l.id}">${l.label}</button>`).join("")}
|
|
10642
10900
|
</div>
|
|
10643
10901
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
10644
|
-
${
|
|
10902
|
+
${Ps.map(l=>`<button type="button" data-days="${l.days}" aria-pressed="${l.days===30}">${l.label}</button>`).join("")}
|
|
10645
10903
|
</div>
|
|
10646
10904
|
</div>
|
|
10647
10905
|
<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">
|
|
10648
10906
|
<section class="mx-section" aria-labelledby="mx-lanes-title">
|
|
10649
|
-
${
|
|
10907
|
+
${Q(Y.activity,"What ran","One lane per origin. Each lane is scaled to its own peak so a quiet channel stays readable next to a busy one. Select a column for the day behind it.","mx-lanes-title")}
|
|
10650
10908
|
<div id="mx-lanes"><div class="mx-empty">Loading activity...</div></div>
|
|
10651
10909
|
<div class="mx-axis" id="mx-axis"></div>
|
|
10652
10910
|
<p class="mx-note">Coloured bars are runs that finished; the red cap on a column is the failures inside that day. Select any column for what ran that day, down to a single conversation.</p>
|
|
@@ -10654,32 +10912,32 @@ window.MXD=(function(){
|
|
|
10654
10912
|
|
|
10655
10913
|
<div class="mx-two">
|
|
10656
10914
|
<section class="mx-section" aria-labelledby="mx-origins-title">
|
|
10657
|
-
${
|
|
10915
|
+
${Q(Y.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
|
|
10658
10916
|
<div class="mx-bars" id="mx-origins"><div class="mx-empty">Loading...</div></div>
|
|
10659
10917
|
</section>
|
|
10660
10918
|
<section class="mx-section" aria-labelledby="mx-causes-title">
|
|
10661
|
-
${
|
|
10919
|
+
${Q(Y.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
|
|
10662
10920
|
<div class="mx-bars" id="mx-causes"><div class="mx-empty">Loading...</div></div>
|
|
10663
10921
|
<p class="mx-note" id="mx-cause-note"></p>
|
|
10664
10922
|
</section>
|
|
10665
10923
|
</div>
|
|
10666
10924
|
|
|
10667
10925
|
<section class="mx-section" aria-labelledby="mx-scatter-title">
|
|
10668
|
-
${
|
|
10926
|
+
${Q(Y.effort,"Effort against output","Every recurring job, plotted as runtime spent against tokens produced on its successful runs. Both axes are logarithmic.","mx-scatter-title")}
|
|
10669
10927
|
<div class="mx-scatter" id="mx-scatter"><div class="mx-empty">Loading jobs...</div></div>
|
|
10670
10928
|
<div class="mx-legend" id="mx-scatter-legend"></div>
|
|
10671
10929
|
<p class="mx-note">Bubble size is the number of runs. Anything not healthy is labelled on the chart; select it for the attempt history behind the verdict.</p>
|
|
10672
10930
|
</section>
|
|
10673
10931
|
</div>`,r=`<div class="mx-view" id="mx-view-lifetime" role="tabpanel" aria-labelledby="mx-tab-lifetime" hidden>
|
|
10674
10932
|
<section class="mx-section" aria-labelledby="mx-threads-title">
|
|
10675
|
-
${
|
|
10933
|
+
${Q(Y.lifetime,"Thread lifetimes","A thread is one agent talking on one channel in one conversation. The bar is its real first-to-last span; each tick is a session cut. Select one for its turns, tokens and time.","mx-threads-title")}
|
|
10676
10934
|
<div class="mx-chips" id="mx-thread-chips"></div>
|
|
10677
10935
|
<div id="mx-threads"><div class="mx-empty">Loading threads...</div></div>
|
|
10678
10936
|
<p class="mx-note">Select a thread to walk its runs, then a run to see which tools it touched. Grey ticks are stale cuts, amber ticks are context-full cuts.</p>
|
|
10679
10937
|
</section>
|
|
10680
10938
|
|
|
10681
10939
|
<section class="mx-section" aria-labelledby="mx-rot-title">
|
|
10682
|
-
${
|
|
10940
|
+
${Q(Y.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
|
|
10683
10941
|
<div class="mx-bars" id="mx-rotations"><div class="mx-empty">Loading...</div></div>
|
|
10684
10942
|
<p class="mx-note" id="mx-rot-note"></p>
|
|
10685
10943
|
</section>
|
|
@@ -10687,23 +10945,31 @@ window.MXD=(function(){
|
|
|
10687
10945
|
<p id="mx-updated" class="mx-updated" aria-live="polite">Connecting to the fleet...</p>
|
|
10688
10946
|
|
|
10689
10947
|
<section class="mx-section" aria-labelledby="mx-auto-title">
|
|
10690
|
-
${
|
|
10948
|
+
${Q(Y.schedules,"Today's automations","Persisted attempts are authoritative. Select a schedule to inspect its latest result and runtime.","mx-auto-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-run-count">0 schedules</span><button class="ax-btn ax-btn--ghost mx-show-all" id="mx-show-all" type="button" hidden>Show all</button></div>')}
|
|
10691
10949
|
<div class="ax-stack" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
|
|
10692
10950
|
</section>
|
|
10693
10951
|
|
|
10952
|
+
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
10953
|
+
${Q(Y.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>')}
|
|
10954
|
+
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
10955
|
+
${Ls.map(l=>`<button class="mx-chip" type="button" data-rt-filter="${l.id}" aria-pressed="${l.id==="all"}">${l.label}</button>`).join("")}
|
|
10956
|
+
</div>
|
|
10957
|
+
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
10958
|
+
</section>
|
|
10959
|
+
|
|
10694
10960
|
<div class="mx-columns">
|
|
10695
10961
|
<section class="mx-section" aria-labelledby="mx-active-title">
|
|
10696
|
-
${
|
|
10962
|
+
${Q(Y.activity,"Activity provenance","Who initiated current work and where it is running.","mx-active-title",'<span class="ax-tab-count" id="mx-active-count">0 active</span>')}
|
|
10697
10963
|
<div class="ax-stack" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
|
|
10698
10964
|
</section>
|
|
10699
10965
|
<section class="mx-section" aria-labelledby="mx-nodes-title">
|
|
10700
|
-
${
|
|
10966
|
+
${Q(Y.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
|
|
10701
10967
|
<div class="ax-stack" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
|
|
10702
10968
|
</section>
|
|
10703
10969
|
</div>
|
|
10704
10970
|
|
|
10705
10971
|
<section class="mx-section" aria-labelledby="mx-agents-title">
|
|
10706
|
-
${
|
|
10972
|
+
${Q(Y.agents,"Agents and skills","Runtime, model, installed skills, and task totals by node.","mx-agents-title",'<span class="ax-tab-count" id="mx-agent-count">0 agents</span>')}
|
|
10707
10973
|
<div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
|
|
10708
10974
|
</section>
|
|
10709
10975
|
</div>`,s=`${e}<main class="mx-content">
|
|
@@ -10719,7 +10985,7 @@ window.MXD=(function(){
|
|
|
10719
10985
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
10720
10986
|
</header>
|
|
10721
10987
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
10722
|
-
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
10988
|
+
</aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:sn+un,scripts:ln+Ds+dn+cn+mn+pn})}var Ds=`<script>
|
|
10723
10989
|
(function(){
|
|
10724
10990
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
10725
10991
|
var range=document.getElementById('mx-range');
|
|
@@ -10747,7 +11013,7 @@ window.MXD=(function(){
|
|
|
10747
11013
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
10748
11014
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
10749
11015
|
})();
|
|
10750
|
-
</script>`;async function
|
|
11016
|
+
</script>`;async function gn(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 l=>{let i={Accept:"application/json"};l.token&&(i.Authorization=`Bearer ${l.token}`);try{let c=await fetch(l.url+"/analytics/mesh"+o,{headers:i,signal:n.signal});return c.ok?{node:l,data:await c.json()}:{node:l,error:`HTTP ${c.status}`}}catch(c){return{node:l,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Os(s,e.days)}function Os(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,l=[],i=[],c=0,p=0,m=0,g=0,_=0,S=0;for(let{node:E,data:T}of t)if(T){a.runs+=T.totals.runs,a.errors+=T.totals.errors,a.hours+=T.totals.hours,a.agents+=T.totals.agents,a.threads+=T.totals.threads;for(let d of T.days){let u=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])u[h][0]+=d[h]?.[0]||0,u[h][1]+=d[h]?.[1]||0;n.set(d.day,u)}for(let d of T.origins){let u=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};u.runs+=d.runs,u.errors+=d.errors,u.hours+=d.hours,r.set(d.channel,u)}for(let d of T.causes){let u=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};u.count+=d.count;for(let h of d.agents)u.agents.includes(h)||u.agents.push(h);u.example||(u.example=d.example),o.set(d.cause,u)}for(let d of T.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=T.rotations.total,p+=T.rotations.tokenSum||0,m+=T.rotations.tokenSamples||0,g=Math.max(g,T.rotations.maxTokens),_+=T.retention.traces,S+=T.retention.tracesWithSteps;for(let d of T.jobs)l.push({...d,node:E.name,nodeUrl:E.url});for(let d of T.threads)i.push({...d,node:E.name,nodeUrl:E.url})}let k=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:k.length?Math.min(...k):Date.now()-e*864e5,nodes:t.map(E=>({name:E.node.name,url:E.node.url,ok:!!E.data,error:E.error,runs:E.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((E,T)=>E.day.localeCompare(T.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,T)=>T.runs-E.runs),causes:[...o.values()].sort((E,T)=>T.count-E.count),jobs:l.sort((E,T)=>T.hours-E.hours),threads:i.sort((E,T)=>T.lastAt-T.firstAt-(E.lastAt-E.firstAt)||T.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,T])=>({reason:E,count:T})).sort((E,T)=>T.count-E.count),tokenSum:p,tokenSamples:m,maxTokens:g},retention:{traces:_,tracesWithSteps:S}}}async function fn(t,e,a,n){let r=a.replace(/\/+$/,""),o=e.find(l=>l.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 l=await fetch(r+n,{headers:s}),i=await l.text();t.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8"}),t.end(i)}catch(l){t.writeHead(502,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:l?.message||"upstream fetch failed"}))}}async function xn(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 l=>{let i={Accept:"application/json"};l.token&&(i.Authorization=`Bearer ${l.token}`);try{let c=await fetch(l.url+"/analytics/day"+o,{headers:i,signal:n.signal});return c.ok?{node:l,data:await c.json()}:{node:l,error:`HTTP ${c.status}`}}catch(c){return{node:l,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Hs(s,e.day)}function Hs(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:l}of t)if(l){a.runs+=l.totals.runs,a.errors+=l.totals.errors,a.ms+=l.totals.ms,a.inputTokens+=l.totals.inputTokens,a.outputTokens+=l.totals.outputTokens;for(let i of l.origins){let c=n.get(i.channel)||{channel:i.channel,runs:0,errors:0,ms:0};c.runs+=i.runs,c.errors+=i.errors,c.ms+=i.ms,n.set(i.channel,c)}for(let i of l.causes)r.set(i.cause,(r.get(i.cause)||0)+i.count);for(let i of l.conversations)o.push({...i,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,l)=>l.runs-s.runs),causes:[...r.entries()].map(([s,l])=>({cause:s,count:l})).sort((s,l)=>l.count-s.count),conversations:o.sort((s,l)=>l.ms-s.ms||l.turns-s.turns)}}function vn(t={}){let e=`
|
|
10751
11017
|
<select id="boardPicker" title="Switch board"></select>
|
|
10752
11018
|
<div class="search">
|
|
10753
11019
|
<span class="icon">\u2315</span>
|
|
@@ -10848,7 +11114,7 @@ window.MXD=(function(){
|
|
|
10848
11114
|
</footer>
|
|
10849
11115
|
</div>
|
|
10850
11116
|
</div>
|
|
10851
|
-
<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
|
|
11117
|
+
<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:Ns,scripts:`<script>${Bs}</script>`,headExtras:`<script>
|
|
10852
11118
|
// The boards page has its own connection dot + wants body height:100%
|
|
10853
11119
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
10854
11120
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -10864,7 +11130,7 @@ window.MXD=(function(){
|
|
|
10864
11130
|
right.insertBefore(dot, right.firstChild);
|
|
10865
11131
|
}
|
|
10866
11132
|
});
|
|
10867
|
-
</script>`})}var
|
|
11133
|
+
</script>`})}var Ns=`
|
|
10868
11134
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
10869
11135
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
10870
11136
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -11117,7 +11383,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
11117
11383
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
11118
11384
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
11119
11385
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
11120
|
-
`,
|
|
11386
|
+
`,Bs=`
|
|
11121
11387
|
'use strict';
|
|
11122
11388
|
const state = {
|
|
11123
11389
|
boards: [], current: null, items: {},
|
|
@@ -12176,9 +12442,9 @@ function appendEvents(events) {
|
|
|
12176
12442
|
}
|
|
12177
12443
|
|
|
12178
12444
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
12179
|
-
`;function
|
|
12445
|
+
`;function bn(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
12180
12446
|
<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>
|
|
12181
|
-
${
|
|
12447
|
+
${on.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:`${pe.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:zs})}var zs=`
|
|
12182
12448
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
12183
12449
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
12184
12450
|
.lead {
|
|
@@ -12208,7 +12474,7 @@ article.term .alias {
|
|
|
12208
12474
|
}
|
|
12209
12475
|
article.term p {
|
|
12210
12476
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
12211
|
-
}`;function
|
|
12477
|
+
}`;function yn(t={}){let e=`<div class="ax-wf__root">
|
|
12212
12478
|
<aside class="ax-wf__list">
|
|
12213
12479
|
<header>
|
|
12214
12480
|
<h2>Workflows</h2>
|
|
@@ -12285,7 +12551,7 @@ article.term p {
|
|
|
12285
12551
|
</aside>
|
|
12286
12552
|
</div>
|
|
12287
12553
|
|
|
12288
|
-
<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:
|
|
12554
|
+
<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:qs,scripts:`<script>${me({workflowHealth:Mt})}${Fs}</script>`})}var qs=`
|
|
12289
12555
|
.ax-wf__root {
|
|
12290
12556
|
display: grid;
|
|
12291
12557
|
grid-template-columns: 340px 1fr;
|
|
@@ -12669,7 +12935,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12669
12935
|
font-size: 12px; z-index: 50;
|
|
12670
12936
|
}
|
|
12671
12937
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
12672
|
-
`,
|
|
12938
|
+
`,Fs=`
|
|
12673
12939
|
(() => {
|
|
12674
12940
|
const $ = (sel) => document.querySelector(sel)
|
|
12675
12941
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -13110,7 +13376,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13110
13376
|
description: { type: "string", description: "Issue body markdown" },
|
|
13111
13377
|
action: { type: "string", enum: ["open", "reopen", "update", "close"] },
|
|
13112
13378
|
labels: { type: "array", description: "Current labels (array of strings)" },
|
|
13113
|
-
author: { type: "string", description: "
|
|
13379
|
+
author: { type: "string", description: "Username that triggered the event" },
|
|
13114
13380
|
url: { type: "string", description: "GitLab URL of the issue" },
|
|
13115
13381
|
project: { type: "string", description: "org/repo path" },
|
|
13116
13382
|
},
|
|
@@ -13126,6 +13392,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13126
13392
|
source_branch: { type: "string" },
|
|
13127
13393
|
target_branch: { type: "string" },
|
|
13128
13394
|
labels: { type: "array" },
|
|
13395
|
+
author: { type: "string", description: "Username that triggered the event" },
|
|
13129
13396
|
url: { type: "string" },
|
|
13130
13397
|
project: { type: "string" },
|
|
13131
13398
|
},
|
|
@@ -13457,7 +13724,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13457
13724
|
setInterval(refresh, 15000)
|
|
13458
13725
|
})
|
|
13459
13726
|
})();
|
|
13460
|
-
`;function
|
|
13727
|
+
`;function wn(t={}){let e=`<div class="ax-proc__root">
|
|
13461
13728
|
<header class="ax-proc__header">
|
|
13462
13729
|
<h1>Procedures</h1>
|
|
13463
13730
|
<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>
|
|
@@ -13501,7 +13768,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13501
13768
|
<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>
|
|
13502
13769
|
<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>
|
|
13503
13770
|
</section>
|
|
13504
|
-
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
13771
|
+
</div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Us,scripts:`<script>${Ws}</script>`})}var Us=`
|
|
13505
13772
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
13506
13773
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
13507
13774
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -13527,7 +13794,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13527
13794
|
.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); }
|
|
13528
13795
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
13529
13796
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
13530
|
-
`,
|
|
13797
|
+
`,Ws=`
|
|
13531
13798
|
(function(){
|
|
13532
13799
|
function $(sel){ return document.querySelector(sel) }
|
|
13533
13800
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -13627,7 +13894,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13627
13894
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
13628
13895
|
else bootAll()
|
|
13629
13896
|
})();
|
|
13630
|
-
`;function
|
|
13897
|
+
`;function kn(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
13631
13898
|
data-task-id="${P(t.taskId)}"
|
|
13632
13899
|
data-agent-id="${P(t.agentId)}"
|
|
13633
13900
|
data-node-url="${P(t.nodeUrl)}"
|
|
@@ -13670,7 +13937,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13670
13937
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
13671
13938
|
</div>
|
|
13672
13939
|
</footer>
|
|
13673
|
-
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
13940
|
+
</div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Gs,scripts:`<script>${Xs}</script>`})}var Gs=`
|
|
13674
13941
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
13675
13942
|
the sticky topbar. Breathe. */
|
|
13676
13943
|
.ax-task-page {
|
|
@@ -13812,7 +14079,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13812
14079
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
13813
14080
|
}
|
|
13814
14081
|
|
|
13815
|
-
`,
|
|
14082
|
+
`,Xs=`
|
|
13816
14083
|
(function () {
|
|
13817
14084
|
var root = document.querySelector('.ax-task-page');
|
|
13818
14085
|
if (!root) return;
|
|
@@ -13827,6 +14094,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13827
14094
|
var hintEl = document.getElementById('task-hint');
|
|
13828
14095
|
var sendBtn = document.getElementById('task-send');
|
|
13829
14096
|
var stopBtn = document.getElementById('task-stop');
|
|
14097
|
+
var composeEl = root.querySelector('.ax-task-page__compose');
|
|
13830
14098
|
|
|
13831
14099
|
var buffer = '';
|
|
13832
14100
|
var raf = 0;
|
|
@@ -14072,6 +14340,59 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14072
14340
|
var seededAsk = root.getAttribute('data-ask');
|
|
14073
14341
|
if (seededAsk) showAsk(seededAsk, '', root.getAttribute('data-ask-at'));
|
|
14074
14342
|
|
|
14343
|
+
function action(kind, message) {
|
|
14344
|
+
var q = '/api/task/action?node=' + encodeURIComponent(nodeUrl)
|
|
14345
|
+
+ '&task=' + encodeURIComponent(taskId) + '&kind=' + encodeURIComponent(kind);
|
|
14346
|
+
// agent lets the daemon find the stored record when the task has
|
|
14347
|
+
// already finished, so a follow-up on a scheduled run resumes its chat.
|
|
14348
|
+
var payload = message ? { message: message, agent: agentId } : {};
|
|
14349
|
+
return fetch(q, {
|
|
14350
|
+
method: 'POST',
|
|
14351
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14352
|
+
body: JSON.stringify(payload)
|
|
14353
|
+
}).then(function (r) { return r.json().catch(function () { return {}; }); });
|
|
14354
|
+
}
|
|
14355
|
+
|
|
14356
|
+
/** The Task page for another run of the same agent on this node. */
|
|
14357
|
+
function taskHref(id, channel) {
|
|
14358
|
+
var q = new URLSearchParams(location.search);
|
|
14359
|
+
q.set('agent', agentId);
|
|
14360
|
+
q.set('node', nodeUrl);
|
|
14361
|
+
if (channel) q.set('channel', channel);
|
|
14362
|
+
q.delete('archived'); q.delete('ask'); q.delete('at');
|
|
14363
|
+
return '/tasks/' + encodeURIComponent(id) + '?' + q.toString();
|
|
14364
|
+
}
|
|
14365
|
+
|
|
14366
|
+
sendBtn.addEventListener('click', function () {
|
|
14367
|
+
var text = (inputEl.value || '').trim();
|
|
14368
|
+
if (!text) { inputEl.focus(); return; }
|
|
14369
|
+
sendBtn.disabled = true;
|
|
14370
|
+
hintEl.textContent = 'queuing\u2026';
|
|
14371
|
+
action('followup', text).then(function (r) {
|
|
14372
|
+
sendBtn.disabled = false;
|
|
14373
|
+
if (r && r.error) { hintEl.textContent = 'failed: ' + r.error; return; }
|
|
14374
|
+
inputEl.value = '';
|
|
14375
|
+
// A finished scheduled run was continued as a new turn in its chat.
|
|
14376
|
+
// Follow that turn: it is where the reply will appear.
|
|
14377
|
+
if (r && r.resumed && r.taskId) { location.href = taskHref(r.taskId, r.channel); return; }
|
|
14378
|
+
if (r && r.resumed) { hintEl.textContent = 'agent busy \u2014 queued as the next turn in this chat'; return; }
|
|
14379
|
+
hintEl.textContent = 'queued \u2014 dispatches as the next turn';
|
|
14380
|
+
});
|
|
14381
|
+
});
|
|
14382
|
+
|
|
14383
|
+
stopBtn.addEventListener('click', function () {
|
|
14384
|
+
stopBtn.disabled = true;
|
|
14385
|
+
hintEl.textContent = 'stopping\u2026';
|
|
14386
|
+
action('cancel').then(function (r) {
|
|
14387
|
+
stopBtn.disabled = false;
|
|
14388
|
+
hintEl.textContent = (r && r.error) ? 'failed: ' + r.error : 'stop requested';
|
|
14389
|
+
});
|
|
14390
|
+
});
|
|
14391
|
+
|
|
14392
|
+
inputEl.addEventListener('keydown', function (e) {
|
|
14393
|
+
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') { e.preventDefault(); sendBtn.click(); }
|
|
14394
|
+
});
|
|
14395
|
+
|
|
14075
14396
|
// Archived: one fetch of the stored record, no SSE. Opening a stream for a
|
|
14076
14397
|
// task that ended hours ago would sit "connecting\u2026" forever and then report
|
|
14077
14398
|
// a disconnect, which reads as breakage rather than as history.
|
|
@@ -14086,6 +14407,14 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14086
14407
|
.then(function (rec) {
|
|
14087
14408
|
setStatus(rec.ok ? 'archived' : 'failed', rec.ok ? 'done' : 'err');
|
|
14088
14409
|
showAsk(rec.message, rec.sender, rec.startedAt);
|
|
14410
|
+
// A scheduled run's chat has nobody on the other end, so this page is
|
|
14411
|
+
// where it continues: Send resumes the cron session with a new turn.
|
|
14412
|
+
// Other channels stay read-only \u2014 their replies belong in their chat.
|
|
14413
|
+
if (rec.channel === 'cron') {
|
|
14414
|
+
composeEl.hidden = false;
|
|
14415
|
+
stopBtn.style.display = 'none'; // nothing is running to stop
|
|
14416
|
+
inputEl.placeholder = 'Continue this scheduled run \u2014 your message starts a new turn in the same session. \u2318/Ctrl+Enter to send.';
|
|
14417
|
+
}
|
|
14089
14418
|
var tx = rec.transcript || '';
|
|
14090
14419
|
if (tx) append(tx);
|
|
14091
14420
|
// Only append the final reply when the transcript didn't already
|
|
@@ -14132,43 +14461,8 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14132
14461
|
if (!finished) setStatus('disconnected', 'err');
|
|
14133
14462
|
});
|
|
14134
14463
|
|
|
14135
|
-
function action(kind, message) {
|
|
14136
|
-
var q = '/api/task/action?node=' + encodeURIComponent(nodeUrl)
|
|
14137
|
-
+ '&task=' + encodeURIComponent(taskId) + '&kind=' + encodeURIComponent(kind);
|
|
14138
|
-
return fetch(q, {
|
|
14139
|
-
method: 'POST',
|
|
14140
|
-
headers: { 'Content-Type': 'application/json' },
|
|
14141
|
-
body: JSON.stringify(message ? { message: message } : {})
|
|
14142
|
-
}).then(function (r) { return r.json().catch(function () { return {}; }); });
|
|
14143
|
-
}
|
|
14144
|
-
|
|
14145
|
-
sendBtn.addEventListener('click', function () {
|
|
14146
|
-
var text = (inputEl.value || '').trim();
|
|
14147
|
-
if (!text) { inputEl.focus(); return; }
|
|
14148
|
-
sendBtn.disabled = true;
|
|
14149
|
-
hintEl.textContent = 'queuing\u2026';
|
|
14150
|
-
action('followup', text).then(function (r) {
|
|
14151
|
-
sendBtn.disabled = false;
|
|
14152
|
-
if (r && r.error) { hintEl.textContent = 'failed: ' + r.error; return; }
|
|
14153
|
-
inputEl.value = '';
|
|
14154
|
-
hintEl.textContent = 'queued \u2014 dispatches as the next turn';
|
|
14155
|
-
});
|
|
14156
|
-
});
|
|
14157
|
-
|
|
14158
|
-
stopBtn.addEventListener('click', function () {
|
|
14159
|
-
stopBtn.disabled = true;
|
|
14160
|
-
hintEl.textContent = 'stopping\u2026';
|
|
14161
|
-
action('cancel').then(function (r) {
|
|
14162
|
-
stopBtn.disabled = false;
|
|
14163
|
-
hintEl.textContent = (r && r.error) ? 'failed: ' + r.error : 'stop requested';
|
|
14164
|
-
});
|
|
14165
|
-
});
|
|
14166
|
-
|
|
14167
|
-
inputEl.addEventListener('keydown', function (e) {
|
|
14168
|
-
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') { e.preventDefault(); sendBtn.click(); }
|
|
14169
|
-
});
|
|
14170
14464
|
})();
|
|
14171
|
-
`;function
|
|
14465
|
+
`;function _n(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
14172
14466
|
data-agent-id="${P(t.agentId)}"
|
|
14173
14467
|
data-agent-name="${P(e)}"
|
|
14174
14468
|
data-node-url="${P(t.nodeUrl)}">
|
|
@@ -14197,7 +14491,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14197
14491
|
<div class="ax-history__list" id="hist-list">
|
|
14198
14492
|
<div class="ax-history__empty">loading\u2026</div>
|
|
14199
14493
|
</div>
|
|
14200
|
-
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
14494
|
+
</div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ks,scripts:`<script>${Js}</script>`})}var Ks=`
|
|
14201
14495
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
14202
14496
|
flush against the sticky topbar. */
|
|
14203
14497
|
.ax-history {
|
|
@@ -14249,7 +14543,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14249
14543
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
14250
14544
|
}
|
|
14251
14545
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
14252
|
-
`,
|
|
14546
|
+
`,Js=`
|
|
14253
14547
|
(function () {
|
|
14254
14548
|
var root = document.querySelector('.ax-history');
|
|
14255
14549
|
if (!root) return;
|
|
@@ -14349,25 +14643,25 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14349
14643
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
14350
14644
|
});
|
|
14351
14645
|
})();
|
|
14352
|
-
`;function
|
|
14646
|
+
`;function Sn(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?j(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,l=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return fe(t,e,i=>En(e,a,i,{mode:"create",convertFromYaml:l}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Ys(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return j(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return j(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?fe(t,e,l=>{let i=l,c=a.dispatcher.emitSignal({name:s,scope:i?.scope,workflowId:i?.workflowId,payload:i?.payload});return j(e,200,{ok:!0,emission:c})}):j(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),l=o[2];if(l==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?j(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?fe(t,e,i=>{try{let c=a.layouts.save(s,i);return j(e,200,{layout:c})}catch(c){return j(e,400,{error:"invalid layout",message:c.message})}}):!0}if(l==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?fe(t,e,i=>{let c=We.safeParse(i);if(!c.success)return j(e,200,{ok:!1,issues:c.error.issues.map(m=>({path:m.path.join("."),message:m.message}))});let p=Ge(c.data).map(m=>({path:"",message:m}));return j(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!l){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let i=a.store.get(s);return i?j(e,200,{workflow:i}):j(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=new URL(n,"http://_").searchParams,c=i.get("convertFromYaml")==="true"||i.get("convertFromYaml")==="1";return fe(t,e,p=>En(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=a.store.delete(s);return a.layouts.delete(s),j(e,i?200:404,i?{ok:!0}:{error:"workflow not found"})}}}return j(e,404,{error:"unknown workflows endpoint",path:n})}var Vs=["mesh"];function En(t,e,a,n){let r=We.safeParse(a);if(!r.success)return j(t,400,{error:"invalid workflow",issues:r.error.issues.map(i=>({path:i.path.join("."),message:i.message}))});let o=r.data,s=Ge(o);if(s.length>0)return j(t,400,{error:"lint errors",issues:s.map(i=>({path:"",message:i}))});if(n.mode==="update"&&o.id!==n.id)return j(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return j(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let i=a,c=e.store.get(n.id);if(c)for(let p of Vs)!(p in i)&&p in c&&(o[p]=c[p])}let l;try{l=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(i){let c=i?.message||String(i),p=i?.yamlPath,m=!!p||/yaml round-trip failed/.test(c);return j(t,m?409:500,{error:m?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:m?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(l.id,l.nodes.map(i=>i.id)),j(t,200,{workflow:l})}function Ys(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let i=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",m=a.runs.list({workflowId:c,limit:i});if(!p)return j(e,200,{runs:m});let g=m.map(_=>({id:_.id,workflowId:_.workflowId,workflowVersion:_.workflowVersion,homeNode:_.homeNode,status:_.status,pending:_.pending,entityRef:_.entityRef,history:(_.history||[]).slice(-5),parentRunId:_.parentRunId,parentNodeId:_.parentNodeId,rootRunId:_.rootRunId,depth:_.depth,createdAt:_.createdAt,updatedAt:_.updatedAt}));return j(e,200,{runs:g})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return j(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=decodeURIComponent(s[1]);return fe(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?j(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(i,p)?j(e,200,{ok:!0,runId:i,status:p}):j(e,404,{error:"run not found"})})}let l=o.match(/^\/([^\/?]+)(\/stream)?$/);if(l){let i=decodeURIComponent(l[1]);if(l[2])return Qs(t,e,a,i);let c=a.runs.get(i);return c?j(e,200,{run:c}):j(e,404,{error:"run not found"})}return j(e,404,{error:"unknown runs endpoint"})}function Qs(t,e,a,n){let r=a.runs.get(n);if(!r)return j(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
|
|
14353
14647
|
|
|
14354
14648
|
`);let o=!1,s=()=>{o=!0,i?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let l=m=>{if(!o)try{e.write(`data: ${JSON.stringify(m)}
|
|
14355
14649
|
|
|
14356
|
-
`)}catch{s()}},i=a.runEvents?.subscribe(n,l),c=r.updatedAt,p=setInterval(()=>{if(o)return;let m=a.runs.get(n);m&&m.updatedAt!==c&&(c=m.updatedAt,l(m))},2e3);return!0}function fe(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){j(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{j(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{j(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>j(e,400,{error:"body read failed",message:r.message})),!0}function j(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}function
|
|
14650
|
+
`)}catch{s()}},i=a.runEvents?.subscribe(n,l),c=r.updatedAt,p=setInterval(()=>{if(o)return;let m=a.runs.get(n);m&&m.updatedAt!==c&&(c=m.updatedAt,l(m))},2e3);return!0}function fe(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){j(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{j(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{j(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>j(e,400,{error:"body read failed",message:r.message})),!0}function j(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}function _c(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let _ of a)try{s.set(_.id,ci(_,t))}catch(S){console.error(` Board "${_.id}" failed to initialize: ${S.message}`)}let l=t.node?.id||"local",i=t.workflows?.dir?ke(process.cwd(),t.workflows.dir):void 0,c=new Et(i?{baseDir:i}:void 0),p=new St(i?{baseDir:i,nodeId:l}:{nodeId:l}),m=new Tt(i?{baseDir:i}:void 0);Ka(t),Rt({business:t.business?.enabled===!0}),Zs(async(_,S)=>{try{await si(_,S,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:m})}catch(k){v(S,500,{error:k.message||"internal error"})}}).listen(n,r,()=>{let _=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
14357
14651
|
Live dashboard: http://${_}:${n}
|
|
14358
14652
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
14359
14653
|
Kanban dashboard: http://${_}:${n}
|
|
14360
|
-
`),console.log(` Boards: ${a.map(b=>b.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 Ys=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Qs(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"),o==="OPTIONS"){e.writeHead(204),e.end();return}if(o==="GET"&&Ys.has(r)&&Wt("page",r),o==="GET"&&r==="/"){let d=zt();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mt({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mt({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await le(a.config);if(!d){v(e,503,{error:"no node available"});return}let u=await new Promise(f=>{let y="";t.on("data",x=>y+=x),t.on("end",()=>f(y)),t.on("error",()=>f(""))}),h=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:u||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(d){v(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await le(a.config),u=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await se(t):void 0,f=h?.node??u,y=f?d.find(M=>M.url===f):d[0];if(!y){v(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",w=await fetch(y.url+r+x,{method:o,headers:{"Content-Type":"application/json",...y.token?{Authorization:`Bearer ${y.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});v(e,w.status,await w.json().catch(()=>({error:`HTTP ${w.status}`})))}catch(d){v(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await se(t),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:u,body:JSON.stringify(d??{})}),y=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,y)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await le(a.config);if(!d){v(e,200,{configured:!1,workflows:[]});return}let u=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});v(e,u.status,await u.json().catch(()=>({configured:!1,workflows:[]})))}catch{v(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zt({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qt({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Kt({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,u=setTimeout(()=>d.abort(),8e3);try{let h=At(await le(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(h.map(async A=>{try{let k=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:d.signal});if(!k.ok)throw new Error(`HTTP ${k.status}`);return{name:A.name,url:A.url,ok:!0,data:await k.json()}}catch(k){return{name:A.name,url:A.url,ok:!1,error:k.message}}}));v(e,200,{nodes:M});return}let f=h.find(M=>M.url===n.searchParams.get("node"));if(!f){v(e,400,{error:"Select a known node"});return}let y=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(y)||o==="POST"&&["register","ended","action","retry","clear"].includes(y))){v(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Ct(t)):void 0,w=await fetch(f.url+"/monitor/"+y+(y==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):y==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:d.signal,headers:{"Content-Type":"application/json",...f.token?{Authorization:`Bearer ${f.token}`}:{}}});v(e,w.status,await w.json())}catch(h){v(e,502,{error:h.message})}finally{clearTimeout(u)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sn({peers:D(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(un({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mn({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hn({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bt({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let d=n.searchParams.get("agent")||"",u=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gn({taskId:decodeURIComponent(l[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:u,peers:D(a.config)}));return}let i=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(i){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fn({agentId:decodeURIComponent(i[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){qt(t,e);return}if(o==="POST"&&r==="/api/setup"){await Ft(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ut(t,e);return}if(o==="GET"&&r==="/admin"){ra(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){pa(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}ba(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await xi(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await pt(t,e,r,h=>_n(h,a.config));return}let u=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(u){let h=decodeURIComponent(u[1]),f=h.indexOf("::");if(f>0){let y=h.slice(0,f),x=h.slice(f+2),w=a.config.node?.id||a.config.node?.name||"local";if(y===w)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===y);if(M){let A=vt(M.url.replace(/\/+$/,""),a.config);if(A){await bn(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}v(e,404,{error:`unknown node "${y}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let u=vt(d,a.config);if(!u){v(e,404,{error:`unknown peer: ${d}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,y=>y.startsWith("?")?"?":"");await bn(t,e,u,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await ya(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await vi(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-J4FLV45L.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",f=await d({running:h});v(e,200,f)}catch(d){v(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ea({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await _a(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Sa({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ta({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await ri(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 Ua(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await pt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ga(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Ja(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",u=d.startsWith("Bearer ")?d.slice(7):"";if(u!==a.token){let h=new ae,f=u?h.verify(u):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await oa(t,e);return}if(r.startsWith("/api/admin/graph/")){await ua(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Va(t,e,r);return}if(r.startsWith("/api/admin/")){await sa(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(ea);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){v(e,400,{error:"invalid asset name"});return}let u=gi("web/"+d);try{let h=await fi(u),f=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",y=n.searchParams.has("v");e.writeHead(200,{"Content-Type":f,"Cache-Control":y?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{v(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await xt(a.config);v(e,200,d)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),u=n.searchParams.get("timezone")||"UTC",h=await xt(a.config,{date:d,timezone:u});v(e,200,h)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(u,h,f,y)=>{let x=parseInt(n.searchParams.get(u)||"",10);return Number.isFinite(x)?Math.max(f,Math.min(y,x)):h};try{let u=await le(a.config);v(e,200,await ln(u,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(u){v(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){v(e,400,{error:"day=YYYY-MM-DD query param required"});return}let u=(h,f,y,x)=>{let w=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(w)?Math.max(y,Math.min(x,w)):f};try{let h=await le(a.config);v(e,200,await cn(h,{day:d,tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",40,1,200)}))}catch(h){v(e,502,{error:h.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){v(e,400,{error:"node query param required"});return}let u=n.searchParams,h;if(r==="/api/mesh/thread"){let[f,y,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!f||!y||!x){v(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(y)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[f,y]=[u.get("kind"),u.get("key")];if(!f||!y){v(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(f)}&key=${encodeURIComponent(y)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[f,y,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!f||!y||!x){v(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(y)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(u.get("tzOffset")||"0")}`}else{let f=u.get("task");if(!f){v(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(f)}`}try{await dn(e,await le(a.config),d,h)}catch(f){v(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/live/stream"){si(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),h=d.searchParams.get("agent"),f=d.searchParams.get("task");if(!u||!h||!f){v(e,400,{error:"node, agent, task query params required"});return}await ii(t,e,a,u,h,f);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),h=d.searchParams.get("agent"),f=d.searchParams.get("task"),y=d.searchParams.get("limit")||"50";if(!u||!h){v(e,400,{error:"node and agent query params required"});return}await ci(e,a,u,h,f,y);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),h=d.searchParams.get("task"),f=d.searchParams.get("kind");if(!u||!h||f!=="cancel"&&f!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await pi(t,e,a,u,h,f);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){v(e,400,{error:"node query param required"});return}await wn(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!u.ok)throw new Error(`HTTP ${u.status}`);let h=await u.json();v(e,200,h)}catch(d){v(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await se(t);try{let u=await mi(a.config,d);v(e,200,u)}catch(u){v(e,502,{error:u.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!li(t,e,[`agent:${d}`]))return;await di(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",u=d.startsWith("Bearer ")?d.slice(7):"";if(u!==a.token){let h=new ae,f=u?h.verify(u):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){v(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="GET"&&r==="/events"){let u=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(w=>({name:w.name,url:w.url,token:w.token}))],f={flag:!1},y=[];t.on("close",()=>{f.flag=!0;for(let w of y)try{w.abort()}catch{}});let x=setInterval(()=>{if(!f.flag)try{e.write(`: ping
|
|
14654
|
+
`),console.log(` Boards: ${a.map(S=>S.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var oi=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function si(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"),o==="OPTIONS"){e.writeHead(204),e.end();return}if(o==="GET"&&oi.has(r)&&Kt("page",r),o==="GET"&&r==="/"){let d=Ut();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mt({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(vn({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mt({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await le(a.config);if(!d){v(e,503,{error:"no node available"});return}let u=await new Promise(f=>{let b="";t.on("data",x=>b+=x),t.on("end",()=>f(b)),t.on("error",()=>f(""))}),h=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:u||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(d){v(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await le(a.config),u=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await se(t):void 0,f=h?.node??u,b=f?d.find(M=>M.url===f):d[0];if(!b){v(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(b.url+r+x,{method:o,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});v(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){v(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await se(t),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:u,body:JSON.stringify(d??{})}),b=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,b)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await le(a.config);if(!d){v(e,200,{configured:!1,workflows:[]});return}let u=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});v(e,u.status,await u.json().catch(()=>({configured:!1,workflows:[]})))}catch{v(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ra({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(na({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zt({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,u=setTimeout(()=>d.abort(),8e3);try{let h=At(await le(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(h.map(async A=>{try{let w=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:d.signal});if(!w.ok)throw new Error(`HTTP ${w.status}`);return{name:A.name,url:A.url,ok:!0,data:await w.json()}}catch(w){return{name:A.name,url:A.url,ok:!1,error:w.message}}}));v(e,200,{nodes:M});return}let f=h.find(M=>M.url===n.searchParams.get("node"));if(!f){v(e,400,{error:"Select a known node"});return}let b=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(b)||o==="POST"&&["register","ended","action","retry","clear"].includes(b))){v(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Ct(t)):void 0,y=await fetch(f.url+"/monitor/"+b+(b==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):b==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:d.signal,headers:{"Content-Type":"application/json",...f.token?{Authorization:`Bearer ${f.token}`}:{}}});v(e,y.status,await y.json())}catch(h){v(e,502,{error:h.message})}finally{clearTimeout(u)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hn({peers:D(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(bn({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(yn({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wn({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ft({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let d=n.searchParams.get("agent")||"",u=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kn({taskId:decodeURIComponent(l[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:u,peers:D(a.config)}));return}let i=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(i){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({agentId:decodeURIComponent(i[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Wt(t,e);return}if(o==="POST"&&r==="/api/setup"){await Gt(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Xt(t,e);return}if(o==="GET"&&r==="/admin"){da(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){fa(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Ea(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Si(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await pt(t,e,r,h=>In(h,a.config));return}let u=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(u){let h=decodeURIComponent(u[1]),f=h.indexOf("::");if(f>0){let b=h.slice(0,f),x=h.slice(f+2),y=a.config.node?.id||a.config.node?.name||"local";if(b===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===b);if(M){let A=vt(M.url.replace(/\/+$/,""),a.config);if(A){await Tn(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}v(e,404,{error:`unknown node "${b}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let u=vt(d,a.config);if(!u){v(e,404,{error:`unknown peer: ${d}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,b=>b.startsWith("?")?"?":"");await Tn(t,e,u,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Sa(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Ti(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-5HDW5F66.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",f=await d({running:h});v(e,200,f)}catch(d){v(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ma({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Aa(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ia({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await ui(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 Ja(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await pt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ya(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){en(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",u=d.startsWith("Bearer ")?d.slice(7):"";if(u!==a.token){let h=new ae,f=u?h.verify(u):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ca(t,e);return}if(r.startsWith("/api/admin/graph/")){await xa(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await tn(t,e,r);return}if(r.startsWith("/api/admin/")){await pa(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(oa);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){v(e,400,{error:"invalid asset name"});return}let u=_i("web/"+d);try{let h=await Ei(u),f=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",b=n.searchParams.has("v");e.writeHead(200,{"Content-Type":f,"Cache-Control":b?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{v(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await xt(a.config);v(e,200,d)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),u=n.searchParams.get("timezone")||"UTC",h=await xt(a.config,{date:d,timezone:u});v(e,200,h)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(u,h,f,b)=>{let x=parseInt(n.searchParams.get(u)||"",10);return Number.isFinite(x)?Math.max(f,Math.min(b,x)):h};try{let u=await le(a.config);v(e,200,await gn(u,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(u){v(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){v(e,400,{error:"day=YYYY-MM-DD query param required"});return}let u=(h,f,b,x)=>{let y=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(y)?Math.max(b,Math.min(x,y)):f};try{let h=await le(a.config);v(e,200,await xn(h,{day:d,tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",40,1,200)}))}catch(h){v(e,502,{error:h.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){v(e,400,{error:"node query param required"});return}let u=n.searchParams,h;if(r==="/api/mesh/thread"){let[f,b,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!f||!b||!x){v(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(b)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[f,b]=[u.get("kind"),u.get("key")];if(!f||!b){v(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(f)}&key=${encodeURIComponent(b)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[f,b,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!f||!b||!x){v(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(b)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(u.get("tzOffset")||"0")}`}else{let f=u.get("task");if(!f){v(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(f)}`}try{await fn(e,await le(a.config),d,h)}catch(f){v(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/live/stream"){hi(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),h=d.searchParams.get("agent"),f=d.searchParams.get("task");if(!u||!h||!f){v(e,400,{error:"node, agent, task query params required"});return}await gi(t,e,a,u,h,f);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),h=d.searchParams.get("agent"),f=d.searchParams.get("task"),b=d.searchParams.get("limit")||"50";if(!u||!h){v(e,400,{error:"node and agent query params required"});return}await vi(e,a,u,h,f,b);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),u=d.searchParams.get("node"),h=d.searchParams.get("task"),f=d.searchParams.get("kind");if(!u||!h||f!=="cancel"&&f!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await bi(t,e,a,u,h,f);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){v(e,400,{error:"node query param required"});return}await An(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!u.ok)throw new Error(`HTTP ${u.status}`);let h=await u.json();v(e,200,h)}catch(d){v(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await se(t);try{let u=await wi(a.config,d);v(e,200,u)}catch(u){v(e,502,{error:u.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!fi(t,e,[`agent:${d}`]))return;await xi(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",u=d.startsWith("Bearer ")?d.slice(7):"";if(u!==a.token){let h=new ae,f=u?h.verify(u):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){v(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="GET"&&r==="/events"){let u=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({name:y.name,url:y.url,token:y.token}))],f={flag:!1},b=[];t.on("close",()=>{f.flag=!0;for(let y of b)try{y.abort()}catch{}});let x=setInterval(()=>{if(!f.flag)try{e.write(`: ping
|
|
14361
14655
|
|
|
14362
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let
|
|
14656
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let y of h)(async()=>{let M={Accept:"text/event-stream"};y.token&&(M.Authorization=`Bearer ${y.token}`);let A=new AbortController;b.push(A);try{let w=await fetch(`${y.url.replace(/\/+$/,"")}/events${u?`?${u}`:""}`,{headers:M,signal:A.signal});if(!w.ok||!w.body)return;let I=w.body.getReader(),L=new TextDecoder,R="";for(;!f.flag;){let{done:N,value:Z}=await I.read();if(N)break;R+=L.decode(Z,{stream:!0});let B;for(;(B=R.indexOf(`
|
|
14363
14657
|
|
|
14364
14658
|
`))>=0;){let O=R.slice(0,B);if(R=R.slice(B+2),f.flag)break;try{e.write(O+`
|
|
14365
14659
|
|
|
14366
|
-
`)}catch{f.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),u=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),h=d.searchParams.get("workflowId")||void 0,f=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",
|
|
14367
|
-
`;
|
|
14660
|
+
`)}catch{f.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),u=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),h=d.searchParams.get("workflowId")||void 0,f=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",b=a.workflowRuns.list({limit:u,workflowId:h}),x=`?limit=${u}${h?`&workflowId=${encodeURIComponent(h)}`:""}${f?"&summary=1":""}`,y=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],M=await Promise.all(y.map(async L=>{let R={};L.token&&(R.Authorization=`Bearer ${L.token}`);try{let N=new AbortController,Z=setTimeout(()=>N.abort(),5e3);try{let B=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:R,signal:N.signal});if(!B.ok)return[];let O=await B.json();return Array.isArray(O.runs)?O.runs:[]}finally{clearTimeout(Z)}}catch{return[]}})),A=new Map;for(let L of b)A.set(L.id,L);for(let L of M)for(let R of L)A.set(R.id,R);let w=Array.from(A.values()).sort((L,R)=>L.updatedAt<R.updatedAt?1:-1).slice(0,u),I=f?w.map(L=>di(L)):w;v(e,200,{runs:I})}catch(d){v(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let g=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(g){let d=decodeURIComponent(g[1]),u=a.workflowRuns.get(d);if(u){v(e,200,{run:u});return}let h=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(f=>({url:f.url,token:f.token}))];for(let f of h)try{let b={};f.token&&(b.Authorization=`Bearer ${f.token}`);let x=await fetch(`${f.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:b});if(x.ok){v(e,200,await x.json());return}}catch{}v(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let u=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${u}/api/actions/builtin`,{headers:d}),f=await h.json().catch(()=>({error:`HTTP ${h.status}`}));v(e,h.status,f)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let _=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(_){try{let d=await se(t).catch(()=>({})),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${h}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:u,body:JSON.stringify(d??{})}),b=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,b)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Sn(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(u,h,f)=>{if(a.token)return!0;let b=Ke(u);if(!b)return!0;let x=new ae().verify(b);if(!x)return v(h,401,{error:"invalid or revoked token"}),!1;for(let y of f)if(!ve(x,y))return v(h,403,{error:`token missing scope: ${y}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){v(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(S&&o==="GET"){let d=a.sources.get(S[1]);if(!d){v(e,404,{error:"unknown board"});return}try{let u=typeof d.listMembers=="function"?await d.listMembers():[];v(e,200,u)}catch(u){v(e,502,{error:u.message})}return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(k&&o==="GET"){let d=a.sources.get(k[1]);if(!d){v(e,404,{error:"unknown board"});return}try{let u=typeof d.listMilestones=="function"?await d.listMilestones():[];v(e,200,u)}catch(u){v(e,502,{error:u.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,d,u]=E,h=decodeURIComponent(u),f=a.boards.find(A=>A.id===d);if(!f){v(e,404,{error:`unknown board: ${d}`});return}let b=a.sources.get(d);if(!b){v(e,503,{error:`board "${d}" source unavailable`});return}let x=await se(t),y=f.columns.find(A=>A.id===x.to),M=f.columns.find(A=>A.id===x.from);if(!y){v(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await li(b,h,M,y),ht({actor:gt(t),action:"move",boardId:d,itemId:h,payload:{from:x.from,to:x.to}}),v(e,200,{ok:!0})}catch(A){v(e,502,{error:A.message||"transition failed"})}return}if(T){let[,d,u]=T,h=u?decodeURIComponent(u):void 0,f=a.boards.find(x=>x.id===d);if(!f){v(e,404,{error:`unknown board: ${d}`});return}let b=a.sources.get(d);if(!b){v(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!h){let{columns:x,totals:y}=await ii(f,b,n.searchParams);v(e,200,{columns:x,totals:y});return}if(o==="GET"&&h){try{let x=typeof b.getItem=="function"?await b.getItem(h):null;if(!x){v(e,404,{error:"not found"});return}v(e,200,x)}catch(x){v(e,502,{error:x.message})}return}if(o==="PATCH"&&h){let x=await se(t);try{let y=typeof b.updateItem=="function"?await b.updateItem(h,x):null;if(!y){v(e,501,{error:"update unsupported"});return}ht({actor:gt(t),action:"update",boardId:d,itemId:h,payload:x}),v(e,200,y)}catch(y){v(e,502,{error:y.message})}return}if(o==="POST"&&!h){let x=await se(t);if(!x.title){v(e,400,{error:"title required"});return}if(!b.capabilities.create||!b.create){v(e,400,{error:`source ${b.type} does not support create`});return}try{let y=await b.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});ht({actor:gt(t),action:"create",boardId:d,itemId:y.id,payload:{title:x.title}}),v(e,201,y)}catch(y){v(e,502,{error:y.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),h={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(h){e.writeHead(302,{Location:h}),e.end();return}}v(e,404,{error:"not found",path:r})}async function ii(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let u of t.columns)d[u.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(u=>[u.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,l=a.get("assignee")||void 0,i=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),m=t.columns.some(d=>d.kind==="closed"),g=p?await e.listAll({sinceDays:i,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],_=m?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],S={};for(let d of t.columns)S[d.id]=[];let k=t.columns.find(d=>d.kind==="closed");for(let d of _)k&&S[k.id].push({...d,stage:k.id});let E=t.columns.filter(d=>d.kind!=="closed");for(let d of g){let u=yt(d,E);if(!u)continue;let h=S[u];h&&h.push({...d,stage:u})}if(l)for(let d of Object.keys(S))S[d]=S[d].filter(u=>u.assignee===l);for(let d of Object.keys(S))S[d].sort((u,h)=>{let f=(u.priority??99)-(h.priority??99);return f!==0?f:(h.updatedAt||"").localeCompare(u.updatedAt||"")});let T=Object.fromEntries(Object.entries(S).map(([d,u])=>[d,u.length]));return{columns:S,totals:T}}async function li(t,e,a,n){let r=wt(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 di(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 ci(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 Dt(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function ht(t){try{let e=ke(process.cwd(),".agentx");Cn(e)||ti(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
14661
|
+
`;ei(ke(e,"board-audit.jsonl"),a)}catch{}}function gt(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function pi(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)}`:"",[l,i,c,p,m,g,_]=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)]);if(!i||!i.ok)return o.error=i?`HTTP ${i.status}`:"unreachable",o;let S=await i.json();if(o.agents=S.map(k=>({id:k.id,name:k.name,tier:k.tier,model:k.model,skillCount:Number.isFinite(k.skillCount)?k.skillCount:void 0,active:k.active||0,total:k.total||0,errors:k.errors||0,lastActive:k.lastActive,lastSummary:k.lastSummary,hourlyTasks:Array.isArray(k.hourlyTasks)?k.hourlyTasks:void 0,runningTasks:Array.isArray(k.runningTasks)?k.runningTasks:[]})),l&&l.ok){let k=await l.json();o.uptimeSec=k.uptime,o.name=k.node?.name||k.node?.id||t,o.id=k.node?.id||t,k.usage&&(o.usage=k.usage)}if(p&&p.ok){let k=await p.json();o.crons=k.map(E=>({id:E.id,enabled:E.enabled===!0,schedule:String(E.schedule||""),timezone:E.timezone,agent:String(E.agent||""),kind:typeof E.command=="string"&&E.command.trim()?"command":"agent",model:E.model,nextRun:E.nextRun,retryPending:E.retryPending===!0,consecutiveErrors:Number(E.consecutiveErrors)||0}))}if(m&&m.ok){let k=await m.json();o.cronRuns=Array.isArray(k.runs)?k.runs:[]}if(_&&_.ok){let k=await _.json().catch(()=>null);k&&Array.isArray(k.routines)&&(o.routines=k.routines.slice(0,$t.routines))}if(g&&g.ok){let k=await g.json().catch(()=>null);k?.active&&k.kind==="lesson"&&(o.lesson={agentId:k.agentId??null,mode:String(k.mode||"teach"),goal:String(k.goal||""),step:Number(k.step)||0,saying:String(k.saying||""),startedAt:String(k.startedAt||"")})}o.reachable=!0,o._peers=Array.isArray(c&&await mi(c))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Be=null;function ui(t){if(Be)return Be;let e=ke(process.cwd(),".agentx/wiki");return Be=Yt({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Be}var ft=new WeakMap;async function mi(t){if(ft.has(t))return ft.get(t);try{let e=t.ok?await t.json():null;return ft.set(t,e),e}catch{return null}}async function ze(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 le(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=new Map;r.set(n,{name:"primary",url:n,token:a.token});for(let s of a.daemons){let l=s.url.replace(/\/+$/,"");r.has(l)||r.set(l,{name:s.name,url:l,token:s.token})}let o=await ze(n,a.token,e);for(let s of o)r.has(s.url)||r.set(s.url,s);return[...r.values()]}async function xt(t,e){let a=new AbortController,n=setTimeout(()=>a.abort(),3e3);try{let r=await le(t,a.signal),o=await Promise.all(r.map(s=>pi(s.url,s.token,a.signal,e)));return{ts:new Date().toISOString(),nodes:o}}finally{clearTimeout(n)}}function hi(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,i)=>{n||e.write(`event: ${l}
|
|
14368
14662
|
data: ${JSON.stringify(i)}
|
|
14369
14663
|
|
|
14370
|
-
`)},o=async()=>{try{let l=await xt(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}};o();let s=setInterval(o,2e3);t.on("close",()=>{n=!0,clearInterval(s),e.end()})}async function
|
|
14664
|
+
`)},o=async()=>{try{let l=await xt(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}};o();let s=setInterval(o,2e3);t.on("close",()=>{n=!0,clearInterval(s),e.end()})}async function gi(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),l=new Set;l.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let S of a.config.dashboard.daemons)l.add(S.url.replace(/\/+$/,""));try{let S=await ze(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let k of S)l.add(k.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){v(e,403,{error:"node not in dashboard allowlist",target:s});return}let i=s===a.config.dashboard.daemonUrl.replace(/\/+$/,"")?a.config.dashboard.token:a.config.dashboard.daemons.find(S=>S.url.replace(/\/+$/,"")===s)?.token,c={Accept:"text/event-stream"};i&&(c.Authorization=`Bearer ${i}`);let p=new AbortController,m;try{m=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(S){v(e,502,{error:S.message||"upstream connect failed"});return}if(!m.ok||!m.body){v(e,m.status||502,{error:`upstream HTTP ${m.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*","X-Accel-Buffering":"no"});let g=m.body.getReader();(async()=>{try{for(;;){let{value:S,done:k}=await g.read();if(k)break;S&&e.write(S)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function fi(t,e,a){let n=Ke(t);if(!n)return v(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ae().verify(n);if(!r)return v(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ve(r,o))return v(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function xi(t,e,a,n){let r=a.agents?.[n];if(!r){v(e,404,{error:"unknown agent"});return}if(r.access!=="public"){v(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await se(t)}catch{v(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){v(e,400,{error:"required: { message: string, context?: {...} }"});return}let l=a.dashboard.daemonUrl.replace(/\/+$/,""),i={"Content-Type":"application/json"};a.dashboard.token&&(i.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${l}/task`,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(p)}catch(c){v(e,502,{error:c.message||"upstream call failed"})}}async function vi(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),l=new Set;l.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let m of e.config.dashboard.daemons)l.add(m.url.replace(/\/+$/,""));try{let m=await ze(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let g of m)l.add(g.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){v(t,403,{error:"node not in dashboard allowlist",target:s});return}let i=s===e.config.dashboard.daemonUrl.replace(/\/+$/,"")?e.config.dashboard.token:e.config.dashboard.daemons.find(m=>m.url.replace(/\/+$/,"")===s)?.token,c={Accept:"application/json"};i&&(c.Authorization=`Bearer ${i}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let m=await fetch(`${s}${p}`,{headers:c}),g=await m.text();t.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),t.end(g)}catch(m){v(t,502,{error:m.message||"upstream fetch failed"})}}async function bi(t,e,a,n,r,o){await An(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function An(t,e,a,n,r){let o=n.replace(/\/+$/,""),s=new Set;s.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let p of a.config.dashboard.daemons)s.add(p.url.replace(/\/+$/,""));try{let p=await ze(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let m of p)s.add(m.url.replace(/\/+$/,""))}catch{}if(!s.has(o)){v(e,403,{error:"node not in dashboard allowlist",target:o});return}let l=o===a.config.dashboard.daemonUrl.replace(/\/+$/,"")?a.config.dashboard.token:a.config.dashboard.daemons.find(p=>p.url.replace(/\/+$/,"")===o)?.token,i={"Content-Type":"application/json",Accept:"application/json"};l&&(i.Authorization=`Bearer ${l}`);let c="{}";try{let p=await se(t);c=p?JSON.stringify(p):"{}"}catch{}try{let p=await fetch(`${o}${r}`,{method:"POST",headers:i,body:c}),m=await p.text();e.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(m)}catch(p){v(e,502,{error:p.message||"upstream fetch failed"})}}var yi=`
|
|
14371
14665
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
14372
14666
|
|
|
14373
14667
|
Title pattern:
|
|
@@ -14399,10 +14693,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
14399
14693
|
Shape:
|
|
14400
14694
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
14401
14695
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
14402
|
-
`;async function
|
|
14696
|
+
`;async function wi(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):
|
|
14403
14697
|
- ${r.knownLabels.slice(0,60).join(`
|
|
14404
14698
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
14405
|
-
`),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",l={"Content-Type":"application/json"};t.dashboard.token&&(l.Authorization=`Bearer ${t.dashboard.token}`);let i=await fetch(s,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:
|
|
14699
|
+
`),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",l={"Content-Type":"application/json"};t.dashboard.token&&(l.Authorization=`Bearer ${t.dashboard.token}`);let i=await fetch(s,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:yi}})});if(!i.ok)throw new Error(`daemon /task HTTP ${i.status}: ${await i.text().catch(()=>"")}`);let c=await i.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),m=ki(p);if(!m||typeof m.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let g=Array.isArray(m.labels)?m.labels.filter(_=>typeof _=="string"):[];return r.primaryLabel&&!g.includes(r.primaryLabel)&&g.unshift(r.primaryLabel),r.columnLabel&&!g.includes(r.columnLabel)&&g.unshift(r.columnLabel),{title:m.title.trim(),description:(m.description||"").toString(),labels:g,assigneeUsername:typeof m.assigneeUsername=="string"?m.assigneeUsername:void 0,kind:typeof m.kind=="string"?m.kind:void 0,raw:p}}function ki(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 _i(t){let e=ri(ni(import.meta.url));return ke(e,t)}async function Ei(t){return ai(t)}function v(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function se(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 Mn(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:Mn(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 Si(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;v(e,200,await He(await In(r,a.config)))}async function In(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=ct(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(l=>l.url),s=await Promise.all(o.map(async l=>{let i=vt(l.url.replace(/\/+$/,""),e);if(!i)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let m=await fetch(`${i.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:c.signal});return m.ok?{nodeId:l.name||l.url,snap:await m.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let l of s)l&&n.push(l);return Xa(n)}async function Ti(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let m=process.env.HOME||"",g=[m&&`${m}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),_=g.find(S=>Cn(S));if(!_){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:g}));return}r="tail",o=["-F","-n","200",_]}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}
|
|
14406
14700
|
|
|
14407
14701
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),l="",i=m=>{l+=m.toString("utf8");let g;for(;(g=l.indexOf(`
|
|
14408
14702
|
`))>=0;){let _=l.slice(0,g).replace(/\r$/,"");l=l.slice(g+1);try{e.write(`event: line
|
|
@@ -14410,5 +14704,5 @@ data: ${_.replace(/\n/g," ")}
|
|
|
14410
14704
|
|
|
14411
14705
|
`)}catch{}}};s.stdout?.on("data",i),s.stderr?.on("data",i);let c=setInterval(()=>{try{e.write(`: hb
|
|
14412
14706
|
|
|
14413
|
-
`)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function
|
|
14414
|
-
//# sourceMappingURL=board-dashboard-
|
|
14707
|
+
`)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function Tn(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),l=o!=="GET"&&o!=="HEAD"?await new Promise((m,g)=>{let _=[];t.on("data",S=>_.push(S)),t.on("end",()=>m(Buffer.concat(_))),t.on("error",g)}):void 0,i={},c=t.headers["content-type"];c&&(i["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(i["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(i.Authorization=`Bearer ${a.token}`),i["X-Agentx-Peer"]="primary";try{let m=await fetch(r,{method:o,headers:i,body:l&&l.length>0?l:void 0}),g=Buffer.from(await m.arrayBuffer());e.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json","Cache-Control":"no-store","Access-Control-Allow-Origin":"*"}),e.end(g)}catch(m){v(e,502,{error:`proxy to peer failed: ${m?.message||m}`,target:r})}}function vt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Mn(n),token:n.dashboardToken||n.token}:null}export{_c as startBoardDashboard};
|
|
14708
|
+
//# sourceMappingURL=board-dashboard-OYGL7Z7X.js.map
|