agentix-cli 0.43.0 → 0.44.1

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.
Files changed (116) hide show
  1. package/apps/mac-helper/Resources/AppIcon.png +0 -0
  2. package/apps/mac-helper/Sources/AgentXHelper/Notify.swift +51 -0
  3. package/apps/mac-helper/Sources/AgentXHelper/main.swift +15 -1
  4. package/apps/mac-helper/build.sh +25 -2
  5. package/dist/{App-HSRGG5VA.js → App-QTUGMHG7.js} +2 -2
  6. package/dist/{ChatApp-4FOU6Q3S.js → ChatApp-634FDG3W.js} +2 -2
  7. package/dist/{agent-54NUP2Z3.js → agent-3XDPLWMX.js} +2 -2
  8. package/dist/{board-dashboard-HLTVSSGW.js → board-dashboard-B5FMUMGA.js} +470 -182
  9. package/dist/board-dashboard-B5FMUMGA.js.map +1 -0
  10. package/dist/{chunk-XRPMP6A5.js → chunk-3TL5EIVN.js} +151 -148
  11. package/dist/chunk-3TL5EIVN.js.map +1 -0
  12. package/dist/{chunk-H4MIYENA.js → chunk-6HMZ5TTM.js} +2 -2
  13. package/dist/{chunk-SJPLXXCI.js → chunk-7A7RC3R4.js} +2 -2
  14. package/dist/chunk-BIFJSQB5.js +123 -0
  15. package/dist/chunk-BIFJSQB5.js.map +1 -0
  16. package/dist/{chunk-WBGROLOX.js → chunk-BTGPZ6B7.js} +2 -2
  17. package/dist/{chunk-X763UOES.js → chunk-ICZPZYYR.js} +2 -2
  18. package/dist/{chunk-RCVGIKC2.js → chunk-MTVRYTLL.js} +2 -2
  19. package/dist/chunk-MX5GCR7Y.js +36 -0
  20. package/dist/chunk-MX5GCR7Y.js.map +1 -0
  21. package/dist/{chunk-B32HVIDN.js → chunk-NSYY5NCR.js} +3 -3
  22. package/dist/chunk-NSYY5NCR.js.map +1 -0
  23. package/dist/chunk-QJANPP4C.js +15 -0
  24. package/dist/chunk-QJANPP4C.js.map +1 -0
  25. package/dist/{chunk-REPZID5M.js → chunk-SAFAI4AV.js} +43 -43
  26. package/dist/chunk-SAFAI4AV.js.map +1 -0
  27. package/dist/chunk-T76YTN34.js +178 -0
  28. package/dist/chunk-T76YTN34.js.map +1 -0
  29. package/dist/chunk-TCJ3SMOF.js +9 -0
  30. package/dist/chunk-TCJ3SMOF.js.map +1 -0
  31. package/dist/{chunk-RQKUQOFC.js → chunk-TNFOGJWZ.js} +2 -2
  32. package/dist/{chunk-FAJEBVZE.js → chunk-V5FZJUK4.js} +2 -2
  33. package/dist/chunk-WLVQDEOT.js +2 -0
  34. package/dist/chunk-WLVQDEOT.js.map +1 -0
  35. package/dist/{chunk-B5HKRYCU.js → chunk-YQVR2HQS.js} +2 -2
  36. package/dist/{chunk-2HNKBYQ6.js → chunk-ZQOGAUQS.js} +194 -210
  37. package/dist/chunk-ZQOGAUQS.js.map +1 -0
  38. package/dist/cli.js +1 -1
  39. package/dist/cli.js.map +1 -1
  40. package/dist/client-NTC667CA.js +2 -0
  41. package/dist/config-5V444ZFW.js +2 -0
  42. package/dist/config-mutator-E6NQLFWR.js +2 -0
  43. package/dist/doctor-5HDW5F66.js +2 -0
  44. package/dist/{editor-chat-OB7IQOB5.js → editor-chat-MOMQHMO4.js} +2 -2
  45. package/dist/editor-chat-MOMQHMO4.js.map +1 -0
  46. package/dist/index.d.ts +462 -46
  47. package/dist/index.js +1 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/program-JLCKBO2A.js +2 -0
  50. package/dist/query-6EMTLCHQ.js +2 -0
  51. package/dist/registry-5QOY65FS.js +2 -0
  52. package/dist/{request-planner-326NOKPZ.js → request-planner-KYQCJDAW.js} +2 -2
  53. package/dist/{review-candidates-LEOPEOEG.js → review-candidates-BFAWNDOR.js} +2 -2
  54. package/dist/routing-OC3QJI3W.js +2 -0
  55. package/dist/schedule-tool-VQCNMBJF.js +8 -0
  56. package/dist/schedule-tool-VQCNMBJF.js.map +1 -0
  57. package/dist/scheduler-NRXPVG7P.js +2 -0
  58. package/dist/seat-3WT3VJC2.js +2 -0
  59. package/dist/{select-L4VIYSFJ.js → select-KPQWIC22.js} +2 -2
  60. package/dist/web/activity-graph.global.js.map +1 -1
  61. package/dist/web/workflow-editor.global.js +1 -1
  62. package/dist/web/workflow-editor.global.js.map +1 -1
  63. package/dist/wiki-5JORBO4G.js +2 -0
  64. package/package.json +2 -1
  65. package/dist/board-dashboard-HLTVSSGW.js.map +0 -1
  66. package/dist/chunk-2HNKBYQ6.js.map +0 -1
  67. package/dist/chunk-B32HVIDN.js.map +0 -1
  68. package/dist/chunk-DIKZWTL5.js +0 -170
  69. package/dist/chunk-DIKZWTL5.js.map +0 -1
  70. package/dist/chunk-F6CNF7V3.js +0 -25
  71. package/dist/chunk-F6CNF7V3.js.map +0 -1
  72. package/dist/chunk-IAG6FI3Q.js +0 -13
  73. package/dist/chunk-IAG6FI3Q.js.map +0 -1
  74. package/dist/chunk-NZ6AQIKJ.js +0 -121
  75. package/dist/chunk-NZ6AQIKJ.js.map +0 -1
  76. package/dist/chunk-P7LNYB53.js +0 -9
  77. package/dist/chunk-P7LNYB53.js.map +0 -1
  78. package/dist/chunk-REPZID5M.js.map +0 -1
  79. package/dist/chunk-XRPMP6A5.js.map +0 -1
  80. package/dist/client-6BGTH2TT.js +0 -2
  81. package/dist/config-SRTXHGSK.js +0 -2
  82. package/dist/config-mutator-KJ5GEMVV.js +0 -2
  83. package/dist/doctor-J4FLV45L.js +0 -2
  84. package/dist/editor-chat-OB7IQOB5.js.map +0 -1
  85. package/dist/program-LYFTYF7E.js +0 -2
  86. package/dist/query-ZSUBNWOL.js +0 -2
  87. package/dist/registry-OMUDCBKM.js +0 -2
  88. package/dist/routing-AWIRBYGU.js +0 -2
  89. package/dist/scheduler-PGGYW5AB.js +0 -2
  90. package/dist/seat-XB4EGUKJ.js +0 -2
  91. package/dist/wiki-GBC6I7ZX.js +0 -2
  92. /package/dist/{App-HSRGG5VA.js.map → App-QTUGMHG7.js.map} +0 -0
  93. /package/dist/{ChatApp-4FOU6Q3S.js.map → ChatApp-634FDG3W.js.map} +0 -0
  94. /package/dist/{agent-54NUP2Z3.js.map → agent-3XDPLWMX.js.map} +0 -0
  95. /package/dist/{chunk-H4MIYENA.js.map → chunk-6HMZ5TTM.js.map} +0 -0
  96. /package/dist/{chunk-SJPLXXCI.js.map → chunk-7A7RC3R4.js.map} +0 -0
  97. /package/dist/{chunk-WBGROLOX.js.map → chunk-BTGPZ6B7.js.map} +0 -0
  98. /package/dist/{chunk-X763UOES.js.map → chunk-ICZPZYYR.js.map} +0 -0
  99. /package/dist/{chunk-RCVGIKC2.js.map → chunk-MTVRYTLL.js.map} +0 -0
  100. /package/dist/{chunk-RQKUQOFC.js.map → chunk-TNFOGJWZ.js.map} +0 -0
  101. /package/dist/{chunk-FAJEBVZE.js.map → chunk-V5FZJUK4.js.map} +0 -0
  102. /package/dist/{chunk-B5HKRYCU.js.map → chunk-YQVR2HQS.js.map} +0 -0
  103. /package/dist/{client-6BGTH2TT.js.map → client-NTC667CA.js.map} +0 -0
  104. /package/dist/{config-SRTXHGSK.js.map → config-5V444ZFW.js.map} +0 -0
  105. /package/dist/{config-mutator-KJ5GEMVV.js.map → config-mutator-E6NQLFWR.js.map} +0 -0
  106. /package/dist/{doctor-J4FLV45L.js.map → doctor-5HDW5F66.js.map} +0 -0
  107. /package/dist/{program-LYFTYF7E.js.map → program-JLCKBO2A.js.map} +0 -0
  108. /package/dist/{query-ZSUBNWOL.js.map → query-6EMTLCHQ.js.map} +0 -0
  109. /package/dist/{registry-OMUDCBKM.js.map → registry-5QOY65FS.js.map} +0 -0
  110. /package/dist/{request-planner-326NOKPZ.js.map → request-planner-KYQCJDAW.js.map} +0 -0
  111. /package/dist/{review-candidates-LEOPEOEG.js.map → review-candidates-BFAWNDOR.js.map} +0 -0
  112. /package/dist/{routing-AWIRBYGU.js.map → routing-OC3QJI3W.js.map} +0 -0
  113. /package/dist/{scheduler-PGGYW5AB.js.map → scheduler-NRXPVG7P.js.map} +0 -0
  114. /package/dist/{seat-XB4EGUKJ.js.map → seat-3WT3VJC2.js.map} +0 -0
  115. /package/dist/{select-L4VIYSFJ.js.map → select-KPQWIC22.js.map} +0 -0
  116. /package/dist/{wiki-GBC6I7ZX.js.map → wiki-5JORBO4G.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as Bt}from"./chunk-3RHPZXCR.js";import{a as T,b as zt,c as qt,d as Ft,e as Ut,f as ae,g as ve,h as Ke,i as Gt}from"./chunk-REPZID5M.js";import{a as Wt}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 Ot,o as Ht,p as Nt}from"./chunk-7CVJ4JOE.js";import{a as Mt,c as _e,d as Xe,e as It,m as Lt,o as ue,p as Ee,q as Se,r as Te,s as Ce,t as Rt,u as Pt,v as Dt,w as Ae}from"./chunk-F6CNF7V3.js";import{g as Ct,h as At}from"./chunk-FAJEBVZE.js";import{a as $t,b as jt}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-P7LNYB53.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-NZ6AQIKJ.js";import"./chunk-AFRHKA7B.js";import"./chunk-B32HVIDN.js";import{b as kt}from"./chunk-RCVGIKC2.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-H4MIYENA.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-AJONZWLT.js";import"./chunk-F4HZTZHW.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import{a as yt,b as wt,c as Tn,g as K,j as Ue}from"./chunk-IAG6FI3Q.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 Xt(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 Kt(t={}){return $({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as Wt}from"./chunk-3RHPZXCR.js";import{a as C,b as Gt,c as Xt,d as Kt,e as Jt,f as ae,g as ve,h as Ke,i as Yt,j as Qt,k as Zt}from"./chunk-SAFAI4AV.js";import{a as Vt}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 qt,o as Ft,p as Ut}from"./chunk-7CVJ4JOE.js";import{D as Ht,F as ue,G as Ee,H as Se,I as Te,J as Ce,K as Nt,L as Bt,M as zt,N as Ae,a as Mt,c as _e,d as Xe,e as It,i as $t,u as jt,w as Lt,x as Rt,y as Pt}from"./chunk-MX5GCR7Y.js";import{g as Ct,h as At}from"./chunk-V5FZJUK4.js";import{a as Dt,b as Ot}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 Pn,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 ea(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 ta(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:Cn,scripts:`<script>${me({decayOf:Je,rankByDecay:Xt})}const ICON = ${JSON.stringify(V)};${An}</script>`})}var Cn=`
88
+ </div>`,css:Dn,scripts:`<script>${me({decayOf:Je,rankByDecay:ea})}const ICON = ${JSON.stringify(V)};${On}</script>`})}var Dn=`
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
- }`,An=String.raw`
364
+ }`,On=String.raw`
365
365
  (function(){
366
366
  const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[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 Jt(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(C=>i.startedAt>=C.from&&i.startedAt<=C.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),b=s.get(i.laneKey)??{key:i.laneKey,label:i.laneLabel,sub:i.laneSub,tracks:1,runs:[]};b.runs.push({...i,band:c,track:0,left:g,width:_,marks:o.get(i.id)??[]}),s.set(i.laneKey,b)}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 Mn}from"crypto";import{readFileSync as In,statSync as $n}from"fs";import{resolve as jn,dirname as Ln}from"path";import{fileURLToPath as Rn}from"url";var Vt=new Map;function Le(t){let e=Vt.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Ln(Rn(import.meta.url)),r=jn(n,"web",t),o=$n(r),s=o.size<8e6?Mn("sha1").update(In(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Vt.set(t,a),a}var Q={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>",Pn=[["agent","Agent",Q.bot],["client","Client",Q.user],["project","Project",Q.folder],["channel","Channel",Q.route],["node","Node",Q.mesh]],Yt={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &mdash; 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 Qt(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">
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),u=r[r.length-1];u&&i.startedAt-u.to<=e?(u.to=Math.max(u.to,c),u.runs++):r.push({from:i.startedAt,to:c,runs:1})}for(;r.length>a;){let i=0,c=1/0;for(let u=1;u<r.length;u++){let m=r[u].from-r[u-1].to;m<c&&(c=m,i=u)}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 aa(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 u=n[c],m=u.to-u.from||1,g=(i.startedAt-u.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,u)=>Ye(i.runs.filter(m=>m.band===u))),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 Hn}from"crypto";import{readFileSync as Nn,statSync as Bn}from"fs";import{resolve as zn,dirname as qn}from"path";import{fileURLToPath as Fn}from"url";var na=new Map;function Le(t){let e=na.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=qn(Fn(import.meta.url)),r=zn(n,"web",t),o=Bn(r),s=o.size<8e6?Hn("sha1").update(Nn(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return na.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>",Un=[["agent","Agent",ee.bot],["client","Client",ee.user],["project","Project",ee.folder],["channel","Channel",ee.route],["node","Node",ee.mesh]],ra={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &mdash; 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 oa(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">${Yt[e]}</p>
785
+ <p class="ac-sub" id="sub">${ra[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",Q.timeline],["map","Map",Q.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("")}
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(Q.refresh,13)} Refresh</button>
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
- ${Pn.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("")}
802
+ ${Un.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(Q.x,11)}canceled</span>
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:Dn,scripts:`<script>${me({computeBands:Ve,packTracks:Ye,buildTimeline:Jt})}const ICON = ${JSON.stringify(Q)};const SUB = ${JSON.stringify(Yt)};${On}</script>`})}var Dn=`
822
+ </div>`,css:Wn,scripts:`<script>${me({computeBands:Ve,packTracks:Ye,buildTimeline:aa})}const ICON = ${JSON.stringify(ee)};const SUB = ${JSON.stringify(ra)};${Gn}</script>`})}var Wn=`
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
- `,On=String.raw`
908
+ `,Gn=String.raw`
909
909
  const $=id=>document.getElementById(id);
910
910
  const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[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 Zt(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:Hn,scripts:`<script src="${Le("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Hn=`
1025
+ `;function sa(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:Xn,scripts:`<script src="${Le("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Xn=`
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
- ${Nt}
1048
- ${Nn}
1049
- ${Fn}</script>`})}var Nn=`
1046
+ `;Pn();import{createServer as ti}from"http";import{appendFileSync as ai,existsSync as Mn,mkdirSync as ni}from"fs";import{readFile as ri}from"fs/promises";import{fileURLToPath as oi}from"url";import{dirname as si,resolve as ke}from"path";var ia='/*! 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 da,writeFileSync as ca,rmSync as Zi,mkdirSync as Zn,copyFileSync as er,readdirSync as tr}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 la(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+Jn()+qt,css:Yn,scripts:`${e}<script>${Ft}
1047
+ ${Ut}
1048
+ ${Kn}
1049
+ ${Qn}</script>`})}var Kn=`
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 Bn(){let t=jt().business?`<button data-tab="business">Business</button>
1111
- `:"";return zn.replace("__BUSINESS_TABS__",t)}var zn=`
1110
+ })();`;function Jn(){let t=Ot().business?`<button data-tab="business">Business</button>
1111
+ `:"";return Vn.replace("__BUSINESS_TABS__",t)}var Vn=`
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:Z.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."})}
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:Z.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."})}
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:Z.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."})}
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:Z.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."})}
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:Z.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."})}
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:Z.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>."})}
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:Z.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."})}
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:Z.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>."})}
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:Z.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."})}
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:Z.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."})}
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
- `,qn=`
1713
+ `,Yn=`
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
- `,Fn=`
1921
+ `,Qn=`
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 pa(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(la({peers:a,localToken:n}))}async function ua(t,e){let a=et();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function ma(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await gr(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await ar(t),r={"GET /api/admin/state":()=>rr(),"POST /api/admin/agents":()=>cr(n),"PATCH /api/admin/agents":()=>pr(n),"DELETE /api/admin/agents":()=>ur(n),"POST /api/admin/agents/access":()=>or(n),"POST /api/admin/channels/telegram":()=>mr(n),"DELETE /api/admin/channels/telegram":()=>Or(n),"POST /api/admin/channels/telegram/toggle":()=>Hr(n),"POST /api/admin/crons":()=>Nr(n),"DELETE /api/admin/crons":()=>Br(n),"POST /api/admin/config/raw":()=>zr(n),"GET /api/admin/tokens":()=>sr(),"POST /api/admin/tokens":()=>ir(n),"DELETE /api/admin/tokens":()=>lr(n),"POST /api/admin/agents/test":()=>dr(n),"POST /api/admin/agents/integrations":()=>wr(n),"DELETE /api/admin/agents/integrations":()=>kr(n),"PATCH /api/admin/agents/integrations":()=>_r(n),"PATCH /api/admin/channels/telegram":()=>hr(n),"POST /api/admin/channels/slack":()=>Ir(n),"POST /api/admin/channels/slack/toggle":()=>$r(n),"POST /api/admin/channels/discord":()=>jr(n),"POST /api/admin/channels/discord/toggle":()=>Lr(n),"POST /api/admin/channels/gitlab":()=>Rr(n),"POST /api/admin/channels/gitlab/toggle":()=>Pr(n),"GET /api/admin/channels/whatsapp/state":()=>be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>be("/webrtc/history"),"POST /api/admin/actions":()=>eo(n),"DELETE /api/admin/actions":()=>to(n),"POST /api/admin/actions/run":()=>ao(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":()=>Dr(n),"POST /api/admin/webhooks":()=>Er(n),"PATCH /api/admin/webhooks":()=>Sr(n),"DELETE /api/admin/webhooks":()=>Mr(n),"POST /api/admin/mesh/peers":()=>Tr(n),"DELETE /api/admin/mesh/peers":()=>Cr(n),"POST /api/admin/mesh/toggle":()=>Ar(n),"GET /api/admin/files":()=>fr(t),"GET /api/admin/files/read":()=>xr(t),"PUT /api/admin/files":()=>vr(n),"POST /api/admin/files/skill":()=>br(n),"DELETE /api/admin/files/skill":()=>yr(n),"POST /api/admin/business/orgchart":()=>qr(n),"DELETE /api/admin/business/orgchart":()=>Fr(n),"POST /api/admin/business/project":()=>Ur(n),"DELETE /api/admin/business/project":()=>Xr(n),"POST /api/admin/business/client":()=>Wr(n),"DELETE /api/admin/business/client":()=>Gr(n),"POST /api/admin/business/contact":()=>Kr(n),"DELETE /api/admin/business/contact":()=>Jr(n),"POST /api/admin/boards":()=>Vr(n),"DELETE /api/admin/boards":()=>Yr(n),"POST /api/admin/boards/columns":()=>Qr(n),"DELETE /api/admin/boards/columns":()=>Zr(n),"POST /api/admin/notifications":()=>ro(n),"POST /api/admin/webhooks/triggers":()=>oo(n),"POST /api/admin/mesh/health":()=>no(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 ar(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 nr(t){let e=he(process.cwd(),t);if(!Pe(e))return[];let a=[];for(let n of tr(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(da(he(e,n.name),"utf-8")))}catch{}return a}function et(){let t=he(process.cwd(),"agentx.json");return Pe(t)?JSON.parse(da(t,"utf-8")):null}function rr(){let t=et();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,p])=>({id:d,name:p.name,tier:p.tier,model:p.model,mentions:p.mentions||[],workspace:p.workspace,access:p.access||"private",systemPrompt:p.systemPrompt||"",maxConcurrent:p.maxConcurrent??1,maxExecutionMinutes:p.maxExecutionMinutes??20,permissionMode:p.permissionMode||"default",integrations:(Array.isArray(p.integrations)?p.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,p])=>({id:d,botUsername:p.botUsername||"",agentBinding:p.agentBinding||"",botTokenRef:p.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,p])=>({id:d,schedule:p.schedule,agent:p.agent,prompt:(p.prompt||"").slice(0,200),enabled:p.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],u={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},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:Yt(t.channels?.ntfy)},E=[];try{E=nr(".agentx/actions").filter(p=>p&&typeof p=="object"&&p.id).map(p=>({id:p.id,title:p.title,kind:p.kind,description:p.description||"",inputs:Array.isArray(p.inputs)?p.inputs:[],timeoutMs:p.timeoutMs??3e4,command:p.kind==="shell"?p.command:void 0,url:p.kind==="http"?p.url:void 0,method:p.kind==="http"?p.method:void 0})).sort((p,h)=>p.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:u,daemonUrl:m,nodeName:t.node?.name,business:_,boards:T,notifications:k,actions:E}}function or(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 sr(){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 ir(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 lr(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 dr(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let u=K();r=u.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=u.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 cr(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=ga(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(u=>{if(u.agents=u.agents||{},u.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)),u.agents[e]=m,`added agent "${e}"`}),c=he(l,"CLAUDE.md");if(!Pe(c))try{Zn(l,{recursive:!0}),ca(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 pr(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=ga(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 ur(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 mr(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 hr(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 gr(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 fr(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 xr(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 vr(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 br(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 yr(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 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)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 kr(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 _r(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(u=>u.kind===a&&u.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var ha=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Er(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(!ha.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(u=>u.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),i.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:l}}function Sr(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"&&ha.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 Tr(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 Cr(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 Ar(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 Mr(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 Ir(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 $r(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 jr(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 Lr(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 Rr(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 Pr(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 Dr(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 Or(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 Hr(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 Nr(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 Br(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 zr(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{er(n,r)}catch{}ca(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 ga(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function qr(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 Fr(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 Ur(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 Wr(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 Gr(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 Xr(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 Kr(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 Jr(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 Vr(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),u={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(u.primaryToolLabel=r),c>=0){let m=i.boards[c];return i.boards[c]={...m,...u,columns:m.columns,labels:m.labels},`board "${e}" updated`}return i.boards.push(u),`board "${e}" added`});return{summary:l}}async function Yr(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 Qr(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 u=i.columns.findIndex(m=>m.id===a);return u>=0?(i.columns[u]={...i.columns[u],...c},`column "${a}" updated`):(i.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Zr(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 eo(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 to(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 ao(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 no(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 ro(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=Qt(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function oo(t){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 lo}from"path";function fa(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:Yr,scripts:`${e}<script>${Qr}</script>`})}var Yr=`
4736
+ </section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:so,scripts:`${e}<script>${io}</script>`})}var so=`
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; }`,Qr=`
4840
+ details[open] summary { margin-bottom: 8px; }`,io=`
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 pa(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(da({peers:a,localToken:n}))}async function ua(t,e,a){try{let n=t.method==="GET"?void 0:await lo(t),r=eo(),o={"GET /api/admin/graph/state":()=>to(r),"POST /api/admin/graph/classifications/approve":()=>ao(r,n),"POST /api/admin/graph/classifications/reject":()=>no(r,n),"POST /api/admin/graph/nodes":()=>ro(r,n),"PATCH /api/admin/graph/nodes":()=>oo(r,n),"DELETE /api/admin/graph/nodes":()=>so(r,n),"PUT /api/admin/graph/schema":()=>io(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 eo(){let t=K(),e=Zr(process.cwd(),t.graph.baseDir);return new kt({baseDir:e})}function to(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 ao(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=ma(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 no(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=ma(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function ma(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 ro(t,e){let a=ca(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?ca(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 oo(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 so(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function io(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 ca(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 lo(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 uo}from"path";import{existsSync as mo}from"fs";import ho from"better-sqlite3";function ha(t={}){let e=`<div class="ax-obs">
5060
+ `;function va(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fa({peers:a,localToken:n}))}async function ba(t,e,a){try{let n=t.method==="GET"?void 0:await vo(t),r=co(),o={"GET /api/admin/graph/state":()=>po(r),"POST /api/admin/graph/classifications/approve":()=>uo(r,n),"POST /api/admin/graph/classifications/reject":()=>mo(r,n),"POST /api/admin/graph/nodes":()=>ho(r,n),"PATCH /api/admin/graph/nodes":()=>go(r,n),"DELETE /api/admin/graph/nodes":()=>fo(r,n),"PUT /api/admin/graph/schema":()=>xo(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 co(){let t=K(),e=lo(process.cwd(),t.graph.baseDir);return new kt({baseDir:e})}function po(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 uo(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=ya(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 mo(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=ya(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function ya(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 ho(t,e){let a=xa(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?xa(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 go(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 fo(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function xo(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 xa(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 vo(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 wo}from"path";import{existsSync as ko}from"fs";import _o from"better-sqlite3";function wa(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:co,scripts:`<script>${po}</script>`})}var co=`
5182
+ </div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:bo,scripts:`<script>${yo}</script>`})}var bo=`
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
- `,po=`
5299
+ `,yo=`
5245
5300
  (function(){
5246
5301
  var panes = document.querySelectorAll('.ax-obs__pane');
5247
5302
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -5625,23 +5680,23 @@ refresh();
5625
5680
 
5626
5681
  load(current);
5627
5682
  })();
5628
- `;var xa={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 va(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=xa[va(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 go(){let t=uo(process.cwd(),".agentx/db.sqlite");if(!mo(t))return null;try{let e=new ho(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function ba(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ha({peers:a}))}function fo(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 ya(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=go();if(!r)return re(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=fo(t);if(n==="routing"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
5683
+ `;var Ea={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 Sa(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=Ea[Sa(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 Eo(){let t=wo(process.cwd(),".agentx/db.sqlite");if(!ko(t))return null;try{let e=new _o(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Ta(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wa({peers:a}))}function So(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 Ca(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Eo();if(!r)return re(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=So(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 "):""}
5632
5687
  ORDER BY at DESC LIMIT @limit
5633
- `,p=r.db.prepare(c).all(i);return re(e,200,{rows:p}),!0}if(n==="rotations"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
5688
+ `,u=r.db.prepare(c).all(i);return re(e,200,{rows:u}),!0}if(n==="rotations"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
5634
5689
  SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
5635
5690
  FROM rotations
5636
5691
  ${l.length?"WHERE "+l.join(" AND "):""}
5637
5692
  ORDER BY rotated_at DESC LIMIT @limit
5638
- `,p=r.db.prepare(c).all(i);return re(e,200,{rows:p}),!0}if(n==="errors"){let l=["status = 'error'"],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
5693
+ `,u=r.db.prepare(c).all(i);return re(e,200,{rows:u}),!0}if(n==="errors"){let l=["status = 'error'"],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
5639
5694
  SELECT started_at, agent_id, channel, message_preview, error
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:wa(g.error)}));return re(e,200,{rows:m}),!0}if(n==="summary"||n==="overview")return re(e,200,xo(r.db)),!0;if(n==="activity")return re(e,200,vo(r.db,{agent:s})),!0;if(n==="cost"){let l=new URL(t.url||"/","http://_"),i=ga(l.searchParams.get("range"));return re(e,200,fa(r.db,i)),!0}if(n==="cost.csv"){let l=new URL(t.url||"/","http://_"),i=ga(l.searchParams.get("range")),c=fa(r.db,i),p=bo(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 wa(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(`
5644
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function xo(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=w=>p.length?p[Math.min(p.length-1,Math.floor(p.length*w))].duration_ms:0,g=m(.5),_=m(.95),C=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((w,M)=>w+rt(M),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((w,M)=>w+rt(M),0),S=t.prepare(`
5698
+ `,m=r.db.prepare(c).all(i).map(g=>({...g,plain:Aa(g.error)}));return re(e,200,{rows:m}),!0}if(n==="summary"||n==="overview")return re(e,200,To(r.db)),!0;if(n==="activity")return re(e,200,Co(r.db,{agent:s})),!0;if(n==="cost"){let l=new URL(t.url||"/","http://_"),i=ka(l.searchParams.get("range"));return re(e,200,_a(r.db,i)),!0}if(n==="cost.csv"){let l=new URL(t.url||"/","http://_"),i=ka(l.searchParams.get("range")),c=_a(r.db,i),u=Ao(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(u),!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 Aa(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 To(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,u=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),m=y=>u.length?u[Math.min(u.length-1,Math.floor(u.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(w=>w.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(w=>w.agent_id)),f=u.filter(w=>!h.has(w)),x=t.prepare(`
5717
+ `).all(a),p=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=p.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(w=>({...w,plain:wa(w.error)}));return{kpis:{tasksToday:s,tasksDelta:s-l,errorsToday:i,errorRate:s>0?i/s:0,avgDurationMs:Math.round(c),p50DurationMs:g,p95DurationMs:_,spendToday:C,spendDelta:C-E,idleAgentCount:f.length},perAgent:S,perChannel:d,idleAgents:f,recentErrors:x}}function vo(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(`
5722
+ `).all(o).map(y=>({...y,plain:Aa(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 Co(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 ga(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 fa(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
5749
+ `).all({since:n,last24:a});return{hourly:s,daily:l,perAgent:i}}function ka(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 _a(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,20 +5754,20 @@ 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,b=0,C=0,E=0,S={},d={};for(let k of n){let I=rt(k),L=va(k.model),R=xa[L],N=(k.tier2_input_tokens||0)/1e6*R.input*.5+(k.tier2_output_tokens||0)/1e6*R.output*.5+(k.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(k.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,Y=(k.input_tokens||0)+(k.tier2_input_tokens||0),B=(k.output_tokens||0)+(k.tier2_output_tokens||0),O=(k.cache_read_tokens||0)+(k.tier2_cache_read_tokens||0),H=(k.cache_create_tokens||0)+(k.tier2_cache_create_tokens||0);m+=I,k.day>=s&&(p+=I,b+=k.tasks||0),k.day>=l&&k.day<s&&(E+=I,C+=k.tasks||0),k.day===r&&(i+=I),k.day===o&&(c+=I),k.day===r&&(g+=N),k.day>=s&&(_+=N);let G=S[k.day]||(S[k.day]={date:k.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});G.tasks+=k.tasks||0,G.input+=Y,G.output+=B,G.cacheRead+=O,G.cacheCreate+=H,G.cost+=I,G.tier2+=N;let z=G.agents[k.agent_id]||(G.agents[k.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:k.model});z.tasks+=k.tasks||0,z.cost+=I,z.tier2+=N,z.input+=Y,z.output+=B,z.cacheRead+=O,z.cacheCreate+=H,k.model&&(z.model=k.model);let X=d[k.agent_id]||(d[k.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:k.model});X.tasks+=k.tasks||0,X.cost+=I,X.tier2+=N,X.input+=Y,X.output+=B,X.cacheRead+=O,X.cacheCreate+=H,k.model&&(X.model=k.model)}let u=Object.values(S).sort((k,I)=>k.date<I.date?-1:1),h=0,f=0,y=0,x=0,w=0,M=0;for(let k of u)h+=k.tasks,f+=k.input,y+=k.output,x+=k.cacheRead,w+=k.cacheCreate,M+=k.cost;let A=Object.entries(d).map(([k,I])=>({agent_id:k,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((k,I)=>I.cost-k.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+y+x+w,cacheHitRange:x+f>0?x/(x+f):0,costPerTaskRange:h>0?M/h:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:C>0?(b-C)/C:0},days:u,perAgent:A}}function bo(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+`
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,u=0,m=0,g=0,_=0,S=0,k=0,E=0,T={},d={};for(let w of n){let I=rt(w),L=Sa(w.model),R=Ea[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&&(u+=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 p=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 p)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:u,spend30d:m,tier2Today:g,tier2_7d:_,tier2PctToday:i>0?g/i:0,spendRange:M,avgDailyRange:p.length?M/p.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?(u-E)/E:0,tasksDeltaWoW:k>0?(S-k)/k:0},days:p,perAgent:A}}function Ao(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 yo}from"path";import{existsSync as wo}from"fs";import ko from"better-sqlite3";function _o(){let t=yo(process.cwd(),".agentx/intent/ledger.sqlite");if(!wo(t))return null;try{let e=new ko(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ka>6e4&&(ka=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var ka=0;function ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Eo(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 _a(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=_o();if(!r)return ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=Eo(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}),b=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${g}`).get({since:s}).n,C=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,S=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(`
5760
+ `}import{resolve as Mo}from"path";import{existsSync as Io}from"fs";import $o from"better-sqlite3";function jo(){let t=Mo(process.cwd(),".agentx/intent/ledger.sqlite");if(!Io(t))return null;try{let e=new $o(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ma>6e4&&(Ma=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Ma=0;function ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Lo(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 Ia(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=jo();if(!r)return ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=Lo(o.searchParams.get("since")),l=o.searchParams.get("source")||"",i=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),u=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let 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:b,decisionsByOutcome:C,totalDivergences:E,divergencesBySource:S,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 _=`
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:u};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 "):""}
5714
5769
  ORDER BY ts DESC LIMIT @limit
5715
- `;return ce(e,200,{rows:r.db.prepare(_).all(g)}),!0}if(n==="divergences"){let m=[],g={limit:p};s!==void 0&&(m.push("ts >= @since"),g.since=s),l&&(m.push("source = @source"),g.source=l);let _=`
5770
+ `;return ce(e,200,{rows:r.db.prepare(_).all(g)}),!0}if(n==="divergences"){let m=[],g={limit:u};s!==void 0&&(m.push("ts >= @since"),g.since=s),l&&(m.push("source = @source"),g.source=l);let _=`
5716
5771
  SELECT ts, source, decided_by,
5717
5772
  legacy_agent_id, legacy_outcome, legacy_reason,
5718
5773
  ledger_agent_id, ledger_outcome, ledger_reason,
@@ -5720,7 +5775,7 @@ refresh();
5720
5775
  FROM intent_divergences
5721
5776
  ${m.length?"WHERE "+m.join(" AND "):""}
5722
5777
  ORDER BY ts DESC LIMIT @limit
5723
- `;return ce(e,200,{rows:r.db.prepare(_).all(g)}),!0}if(n==="active"){let m=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],g={limit:p};l&&(m.push("e.source = @source"),g.source=l);let _=`
5778
+ `;return ce(e,200,{rows:r.db.prepare(_).all(g)}),!0}if(n==="active"){let m=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],g={limit:u};l&&(m.push("e.source = @source"),g.source=l);let _=`
5724
5779
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
5725
5780
  d.decided_by, d.decided_at, d.agent_id, d.reason
5726
5781
  FROM intent_decisions d
@@ -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 Ea(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
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 $a(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 Sa(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
5992
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function ja(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 Ta(t={}){let e=`<div class="ax-pj__root">
6565
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function La(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:So,scripts:`<script>${To}</script>`})}var So=`
6592
+ </div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ro,scripts:`<script>${Po}</script>`})}var Ro=`
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
- `,To=`
6779
+ `,Po=`
6725
6780
  (function(){
6726
6781
  const $ = (sel) => document.querySelector(sel);
6727
6782
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -7371,31 +7426,31 @@ refresh();
7371
7426
  load();
7372
7427
  });
7373
7428
  })();
7374
- `;import{resolve as it,join as Bo}from"path";import{existsSync as lt,readdirSync as zo,readFileSync as qo}from"fs";import Fo from"better-sqlite3";var Aa=String.raw`[\w.-]+(?:/[\w.-]+)+`,Co=new RegExp(`^(?:chat:)?(${Aa}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Ao=new RegExp(`^\\[(?:GitLab|GitHub) (${Aa}) `);function Ca(t){if(!t)return null;let e=t.match(Co);return e?e[1]:null}function ot(t){if(!t)return null;let e=t.trimStart().match(Ao);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():Ca(typeof n?.chatId=="string"?n.chatId:null)??Ca(e)??ot(a)}function Mo(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 Io=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,$o=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,jo=t=>/^issue/i.test(t)?"issue":"mr";function Lo(t){let e=t.subject.match(Io)??t.inputPreview.trimStart().match($o);return e?{kind:jo(e[1]),n:Number(e[2])}:null}function Ro(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 Ma(t){if(!Mo(t.projectId))return[];let e=Lo(t);return e?[e]:Ro(t.inputPreview)}var Po=6e4,Do=5*6e4,Oo=40,Ia=6,$a=new Map;function ja(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 Ma(n)){let s=Oe(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Oo)return[...e.values()]}}return[...e.values()]}async function La(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let l=Oe(s.project,s.ref),i=$a.get(l);i&&n-i.at<(s.github?Do:Po)?i.item&&(r[l]=i.item):o.push(s)}for(let s=0;s<o.length;s+=Ia)await Promise.all(o.slice(s,s+Ia).map(async l=>{let i=Oe(l.project,l.ref),c=null;try{c=l.github?await No(l,e,a):await Ho(l,e,a)}catch{}$a.set(i,{at:n,item:c}),c&&(r[i]=c)}));return r}async function Ra(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 Ho(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 Ra(`${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 No(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 Ra(`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 Fo(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Pa>6e4&&(Pa=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Pa=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 Uo(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 Ha(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 Wo(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 Na(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 Go(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=Da(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:Da(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 Da(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 Ba(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}
7429
+ `;import{resolve as it,join as Jo}from"path";import{existsSync as lt,readdirSync as Vo,readFileSync as Yo}from"fs";import Qo from"better-sqlite3";var Pa=String.raw`[\w.-]+(?:/[\w.-]+)+`,Do=new RegExp(`^(?:chat:)?(${Pa}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Oo=new RegExp(`^\\[(?:GitLab|GitHub) (${Pa}) `);function Ra(t){if(!t)return null;let e=t.match(Do);return e?e[1]:null}function ot(t){if(!t)return null;let e=t.trimStart().match(Oo);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():Ra(typeof n?.chatId=="string"?n.chatId:null)??Ra(e)??ot(a)}function Ho(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 No=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Bo=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,zo=t=>/^issue/i.test(t)?"issue":"mr";function qo(t){let e=t.subject.match(No)??t.inputPreview.trimStart().match(Bo);return e?{kind:zo(e[1]),n:Number(e[2])}:null}function Fo(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 Da(t){if(!Ho(t.projectId))return[];let e=qo(t);return e?[e]:Fo(t.inputPreview)}var Uo=6e4,Wo=5*6e4,Go=40,Oa=6,Ha=new Map;function Na(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 Da(n)){let s=Oe(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Go)return[...e.values()]}}return[...e.values()]}async function Ba(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let l=Oe(s.project,s.ref),i=Ha.get(l);i&&n-i.at<(s.github?Wo:Uo)?i.item&&(r[l]=i.item):o.push(s)}for(let s=0;s<o.length;s+=Oa)await Promise.all(o.slice(s,s+Oa).map(async l=>{let i=Oe(l.project,l.ref),c=null;try{c=l.github?await Ko(l,e,a):await Xo(l,e,a)}catch{}Ha.set(i,{at:n,item:c}),c&&(r[i]=c)}));return r}async function za(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 Xo(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 za(`${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 Ko(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 za(`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 Qo(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-qa>6e4&&(qa=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var qa=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 Zo(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 Wa(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 es(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 Ga(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 ts(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 u=typeof n.channel=="string"?n.channel:"",m=Fa(u);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:Fa(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 Fa(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 Xa(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 Xo(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 za(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
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 as(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 Ka(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),w=x.map((I,L)=>`@id${L}`).join(","),M=Object.fromEntries(x.map((I,L)=>[`id${L}`,I])),A=t.prepare(`
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 (${w}) ORDER BY decided_at ASC
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 k=t.prepare(`
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 (${w})
7385
- `).all(M);for(let I of k)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??[],b=e?.business?.contactMap??[],C=Xe(e?.business??{});for(let x of o){let w=null;try{w=JSON.parse(x.raw_json)}catch{}let M=Na(x.source,w,b),A=Ba(x.source,w),k=x.project??De(w,x.subject,A),I=null,L=null;M?(I=M.client,L=M.project||`${M.client}/_chat`):k&&(I=_e(k,_),L=k);let R=Uo(x.source,x.intent||"",w),N=ge[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:N.label,color:N.color});let Y="__system",B,O=Go(x.source,x.intent||"",w);if(O){Y=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,En=z?.duration_ms??(qe?n-X:0),Sn=qe?"active":z?.status==="error"||z?.status==="fail"?"error":"completed",W,xe;if(I)W=I,xe=L;else{let Fe=C.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:Ha(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:Y,initiatorKind:B,subject:Xo(x.subject),intent:x.intent||"",startedAt:X,resolvedAt:bt,duration:En,active:qe,outcome:Sn,tokens:0,inputPreview:A,system:Wo(H.agent_id,e)})}}let E=[...i.values()].map(x=>({...x,projects:[...c.get(x.id)||[]].sort()})).sort((x,w)=>x.id.localeCompare(w.id)),S=[],d=new Set;if(e){let x=e.business??{},w=M=>{let A=x.orgChart?.[M]?.role,k=A?x.roles?.[A]?.title:void 0;return typeof k=="string"&&k.trim()?k.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let k={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:w(M)};S.push(k),d.add(M)}}for(let x of g)d.has(x.agentId)||(S.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),d.add(x.agentId));S.sort((x,w)=>x.id.localeCompare(w.id));let u=[],h=new Set;for(let[x,w]of Object.entries(ge))u.push({id:x,label:w.label,color:w.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 y=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:S,channels:u,initiators:f,dispatches:g,forges:{gitlab:typeof y=="string"?y:void 0,github:"https://github.com"}}}function ct(t){let e=dt();if(!e)return null;try{return za(e.db,ie,t)}finally{e.close()}}function qa(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=Ko(m);if(g.clientId!==m.clientId&&!e.has(g.clientId)&&e.set(g.clientId,{id:g.clientId,name:g.clientId,color:Ha(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 Ko(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 La(ja(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 Fa(t){ie=t}async function Ua(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=Wa(parseInt(r.searchParams.get("hours")||"6",10));oe(e,200,await He(za(n.db,ie,o)))}catch(r){oe(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Jo=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
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,u=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=Ga(x.source,y,S),A=Xa(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=Zo(x.source,x.intent||"",y),N=ge[R]||{label:R,color:"#6b7280"};u.has(R)||u.set(R,{id:R,label:N.label,color:N.color});let Z="__system",B,O=ts(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,Ln=z?.duration_ms??(qe?n-X:0),Rn=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:Wa(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:as(x.subject),intent:x.intent||"",startedAt:X,resolvedAt:bt,duration:Ln,active:qe,outcome:Rn,tokens:0,inputPreview:A,system:es(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 p=[],h=new Set;for(let[x,y]of Object.entries(ge))p.push({id:x,label:y.label,color:y.color}),h.add(x);for(let x of u.values())h.has(x.id)||p.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:p,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 Ka(e.db,ie,t)}finally{e.close()}}function Ja(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:u}of t){i.gitlab??=u.forges?.gitlab,i.github??=u.forges?.github,u.now>s&&(s=u.now),u.windowH>l&&(l=u.windowH);for(let m of u.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 u.agents)a.has(m.id)||a.set(m.id,m);for(let m of u.channels)n.has(m.id)||n.set(m.id,m);for(let m of u.initiators)r.has(m.id)||r.set(m.id,m);for(let m of u.dispatches){let g=ns(m);if(g.clientId!==m.clientId&&!e.has(g.clientId)&&e.set(g.clientId,{id:g.clientId,name:g.clientId,color:Wa(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,u)=>c.id.localeCompare(u.id)),agents:[...a.values()].sort((c,u)=>c.id.localeCompare(u.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,u)=>u.startedAt-c.startedAt)}}function ns(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 Ba(Na(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 Va(t){ie=t}async function Ya(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=Qa(parseInt(r.searchParams.get("hours")||"6",10));oe(e,200,await He(Ka(n.db,ie,o)))}catch(r){oe(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var rs=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=Wa(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
7442
+ `);let r=new URL(t.url||"/","http://_"),o=Qa(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
- `)}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
7444
+ `)}catch{l()}},25e3);try{for(;!s;){try{let u=await n(o),m=u&&await He(u);if(s)break;m?(e.write(`event: snapshot
7390
7445
  `),e.write(`data: ${JSON.stringify(m)}
7391
7446
 
7392
7447
  `)):e.write(`event: error
7393
7448
  data: ${JSON.stringify({error:"ledger not available"})}
7394
7449
 
7395
- `)}catch(p){e.write(`event: error
7396
- data: ${JSON.stringify({error:p?.message??String(p)})}
7450
+ `)}catch(u){e.write(`event: error
7451
+ data: ${JSON.stringify({error:u?.message??String(u)})}
7397
7452
 
7398
- `)}let c=Date.now();for(;!s&&Date.now()-c<Jo;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(i);try{e.end()}catch{}}return!0}function Wa(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Vo(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)?Oa(s,e,a):null}return Oa(r,e,a)}function Oa(t,e,a){let n=null,r=1/0;for(let o of zo(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(qo(Bo(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 Ga(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 _=Ba(c.source,g),b=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)||_,C=null,E=null;if(p.agent_id){let y=Vo(p.agent_id,p.decided_at);if(y){typeof y.responseText=="string"&&(C=y.responseText);let x=y.transcript;Array.isArray(x)&&(E=x.length)}}let S=ie?.business?.projects??[],d=ie?.business?.contactMap??[],u=Xe(ie?.business??{}),h={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},f=Na(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 y=c.project||De(g,c.subject,_);h={client:_e(y,S),project:y,via:c.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(p.agent_id){let y=u.get(p.agent_id);y&&(h={client:y,project:`${y}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${y})`})}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:b,response:C,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 es,readFileSync as ts}from"fs";import{resolve as Ka}from"path";Ue();function Xa(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=Yo.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:Qo,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>${Zo}</script>`})}var Yo=`
7453
+ `)}let c=Date.now();for(;!s&&Date.now()-c<rs;)await new Promise(u=>setTimeout(u,200))}}finally{clearInterval(i);try{e.end()}catch{}}return!0}function Qa(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function os(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)?Ua(s,e,a):null}return Ua(r,e,a)}function Ua(t,e,a){let n=null,r=1/0;for(let o of Vo(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Yo(Jo(t,o),"utf-8"))}catch{continue}let l=s.startedAt,i;if(typeof l=="number")i=l;else if(typeof l=="string"){let u=Date.parse(l);if(!Number.isFinite(u))continue;i=u}else continue;let c=Math.abs(i-e);c<r&&c<=a&&(n=s,r=c)}return n}async function Za(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 u=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(!u)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 _=Xa(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(u.agent_id){let b=os(u.agent_id,u.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??[],p=Xe(ie?.business??{}),h={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},f=Ga(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(u.agent_id){let b=p.get(u.agent_id);b&&(h={client:b,project:`${b}/_${c.source}`,via:`orgChart fallback (agent ${u.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:u.decided_by,agentId:u.agent_id,outcome:u.outcome,reason:u.reason,startedAt:u.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 ds,readFileSync as cs}from"fs";import{resolve as tn}from"path";Ue();function en(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=ss.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:is,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>${ls}</script>`})}var ss=`
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
- `,Qo=`
8042
+ `,is=`
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
- `,Zo=`
8161
+ `,ls=`
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 Ja(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({agentId:a,peers:n,localToken:r}))}async function Va(t,e,a){try{let n=t.method==="GET"?void 0:await _s(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 ":()=>as(l,n),"PATCH capability":()=>os(l,n),"POST mcp":()=>ns(l,n),"DELETE mcp":()=>rs(l,n),"GET identity":()=>ss(l),"GET identity/file":()=>is(l,String(o.path||"")),"PUT identity/file":()=>ls(l,n),"GET skills":()=>ds(l),"POST skills":()=>cs(l,n),"DELETE skills":()=>ps(l,n),"GET skills/tree":()=>us(l,String(o.slug||"")),"GET skills/file":()=>ms(l,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>hs(l,n),"GET skills/deps":()=>gs(l,String(o.slug||"")),"POST skills/install":()=>fs(l,n,t),"POST skills/deps":()=>xs(l,n,t),"GET channels":()=>vs(l),"GET activity":()=>bs(l,t),"GET handovers":()=>ys(l),"POST handovers":()=>ws(l,n),"DELETE handovers":()=>ks(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 Ya(){let t=Ka(process.cwd(),"agentx.json");return es(t)?JSON.parse(ts(t,"utf-8")):null}function U(t){let e=Ya();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 as(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=T(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:we(t)}}function ns(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}=T(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 rs(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=T(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:we(t)}}function os(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=T(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,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 ss(t){let{def:e}=U(t);return ue(e.workspace)}function is(t,e){if(!e)throw new Error("path query param required");let{def:a}=U(t);return Ee(a.workspace,e)}function ls(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 ds(t){let{def:e}=U(t),a=ue(e.workspace);return{skills:a.skills,workspace:a.workspace}}function cs(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 ps(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 us(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t),n=Rt(a.workspace,e),r=Ae(a.workspace,e);return{slug:e,tree:n,deps:r}}function ms(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=U(t);return Pt(n.workspace,e,a)}function hs(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 Dt(r.workspace,a,n,String(e?.content??""))}function gs(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t);return Ae(a.workspace,e)}async function fs(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=Qa(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(`
8961
- `);return Za(a,r,s,`install-${n}:${Date.now()}`)}async function xs(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Qa(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=Ka(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(`
8962
- `);return Za(a,r,i,`deps-${t}-${n}:${Date.now()}`)}function Qa(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 Za(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 vs(t){let e=Ya(),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 bs(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 ys(t){let e=ut(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function ws(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 ks(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 _s(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 en=[{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>
9015
+ `;function an(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(en({agentId:a,peers:n,localToken:r}))}async function nn(t,e,a){try{let n=t.method==="GET"?void 0:await js(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 ":()=>ps(l,n),"PATCH capability":()=>hs(l,n),"POST mcp":()=>us(l,n),"DELETE mcp":()=>ms(l,n),"GET identity":()=>gs(l),"GET identity/file":()=>fs(l,String(o.path||"")),"PUT identity/file":()=>xs(l,n),"GET skills":()=>vs(l),"POST skills":()=>bs(l,n),"DELETE skills":()=>ys(l,n),"GET skills/tree":()=>ws(l,String(o.slug||"")),"GET skills/file":()=>ks(l,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>_s(l,n),"GET skills/deps":()=>Es(l,String(o.slug||"")),"POST skills/install":()=>Ss(l,n,t),"POST skills/deps":()=>Ts(l,n,t),"GET channels":()=>Cs(l),"GET activity":()=>As(l,t),"GET handovers":()=>Ms(l),"POST handovers":()=>Is(l,n),"DELETE handovers":()=>$s(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 rn(){let t=tn(process.cwd(),"agentx.json");return ds(t)?JSON.parse(cs(t,"utf-8")):null}function U(t){let e=rn();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 ps(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 us(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 ms(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 hs(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 gs(t){let{def:e}=U(t);return ue(e.workspace)}function fs(t,e){if(!e)throw new Error("path query param required");let{def:a}=U(t);return Ee(a.workspace,e)}function xs(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 vs(t){let{def:e}=U(t),a=ue(e.workspace);return{skills:a.skills,workspace:a.workspace}}function bs(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 ys(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 ws(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t),n=Nt(a.workspace,e),r=Ae(a.workspace,e);return{slug:e,tree:n,deps:r}}function ks(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=U(t);return Bt(n.workspace,e,a)}function _s(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 zt(r.workspace,a,n,String(e?.content??""))}function Es(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t);return Ae(a.workspace,e)}async function Ss(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=on(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 sn(a,r,s,`install-${n}:${Date.now()}`)}async function Ts(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=on(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=tn(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 sn(a,r,i,`deps-${t}-${n}:${Date.now()}`)}function on(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 sn(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(),u;try{u=JSON.parse(c)}catch{u={content:c}}if(!i.ok)throw new Error(u?.error||`daemon /task HTTP ${i.status}`);return{worker:e,taskId:u?.taskId,content:u?.content,duration:u?.duration,error:u?.error}}function Cs(t){let e=rn(),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 As(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 Ms(t){let e=ut(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Is(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 $s(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 js(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 ln=[{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:Es,scripts:e+`<script>${Ss}</script>`,headExtras:`<script>
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:Ls,scripts:e+`<script>${Rs}</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 Es=`
9034
+ </script>`})}var Ls=`
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); } }`,Ss=`
9235
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,Rs=`
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 tn=`
9738
+ `;var dn=`
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 an=`<script>
9912
+ `;var cn=`<script>
9854
9913
  window.MX=(function(){
9855
9914
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
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 nn=`<script>
10021
+ </script>`;var pn=`<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 rn=`<script>
10235
+ </script>`;var un=`<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 on=`<script>
10551
+ </script>`;var mn=`<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 status=!job.enabled?'disabled':latest?latest.status:job.retryPending?'retrying':'waiting';
10543
- var summary=latest?(latest.errorSummary||latest.responseSummary||'No summary')
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 ee={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',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 te(t,e,a,n,r=""){return q({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Ts=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Cs=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function sn(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">
10729
+ </script>`;var hn=`
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
+ `,gn=`<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&#39;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 Ps=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Ds=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Os=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function fn(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
- ${Ts.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("")}
10899
+ ${Ds.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
- ${Cs.map(l=>`<button type="button" data-days="${l.days}" aria-pressed="${l.days===30}">${l.label}</button>`).join("")}
10902
+ ${Os.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
- ${te(ee.activity,"What ran","One lane per origin. Each lane is scaled to its own peak so a quiet channel stays readable next to a busy one. Select a column for the day behind it.","mx-lanes-title")}
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
- ${te(ee.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
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
- ${te(ee.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
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
- ${te(ee.effort,"Effort against output","Every recurring job, plotted as runtime spent against tokens produced on its successful runs. Both axes are logarithmic.","mx-scatter-title")}
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
- ${te(ee.lifetime,"Thread lifetimes","A thread is one agent talking on one channel in one conversation. The bar is its real first-to-last span; each tick is a session cut. Select one for its turns, tokens and time.","mx-threads-title")}
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
- ${te(ee.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
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
- ${te(ee.schedules,"Today's automations","Persisted attempts are authoritative. Select a schedule to inspect its latest result and runtime.","mx-auto-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-run-count">0 schedules</span><button class="ax-btn ax-btn--ghost mx-show-all" id="mx-show-all" type="button" hidden>Show all</button></div>')}
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
+ ${Ps.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
- ${te(ee.activity,"Activity provenance","Who initiated current work and where it is running.","mx-active-title",'<span class="ax-tab-count" id="mx-active-count">0 active</span>')}
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
- ${te(ee.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
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
- ${te(ee.agents,"Agents and skills","Runtime, model, installed skills, and task totals by node.","mx-agents-title",'<span class="ax-tab-count" id="mx-agent-count">0 agents</span>')}
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:tn,scripts:an+As+nn+rn+on})}var As=`<script>
10988
+ </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:dn+hn,scripts:cn+Hs+pn+un+gn+mn})}var Hs=`<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 ln(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 Ms(s,e.days)}function Ms(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,b=0;for(let{node:E,data:S}of t)if(S){a.runs+=S.totals.runs,a.errors+=S.totals.errors,a.hours+=S.totals.hours,a.agents+=S.totals.agents,a.threads+=S.totals.threads;for(let d of S.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 S.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 S.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 S.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=S.rotations.total,p+=S.rotations.tokenSum||0,m+=S.rotations.tokenSamples||0,g=Math.max(g,S.rotations.maxTokens),_+=S.retention.traces,b+=S.retention.tracesWithSteps;for(let d of S.jobs)l.push({...d,node:E.name,nodeUrl:E.url});for(let d of S.threads)i.push({...d,node:E.name,nodeUrl:E.url})}let C=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:C.length?Math.min(...C):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,S)=>E.day.localeCompare(S.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,S)=>S.runs-E.runs),causes:[...o.values()].sort((E,S)=>S.count-E.count),jobs:l.sort((E,S)=>S.hours-E.hours),threads:i.sort((E,S)=>S.lastAt-S.firstAt-(E.lastAt-E.firstAt)||S.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,S])=>({reason:E,count:S})).sort((E,S)=>S.count-E.count),tokenSum:p,tokenSamples:m,maxTokens:g},retention:{traces:_,tracesWithSteps:b}}}async function dn(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 cn(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 Is(s,e.day)}function Is(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 pn(t={}){let e=`
11016
+ </script>`;async function xn(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 Ns(s,e.days)}function Ns(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,u=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 p=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])p[h][0]+=d[h]?.[0]||0,p[h][1]+=d[h]?.[1]||0;n.set(d.day,p)}for(let d of T.origins){let p=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};p.runs+=d.runs,p.errors+=d.errors,p.hours+=d.hours,r.set(d.channel,p)}for(let d of T.causes){let p=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};p.count+=d.count;for(let h of d.agents)p.agents.includes(h)||p.agents.push(h);p.example||(p.example=d.example),o.set(d.cause,p)}for(let d of T.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=T.rotations.total,u+=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:u,tokenSamples:m,maxTokens:g},retention:{traces:_,tracesWithSteps:S}}}async function vn(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 bn(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 Bs(s,e.day)}function Bs(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 yn(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:$s,scripts:`<script>${js}</script>`,headExtras:`<script>
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:zs,scripts:`<script>${qs}</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 $s=`
11133
+ </script>`})}var zs=`
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
- `,js=`
11386
+ `,qs=`
11121
11387
  'use strict';
11122
11388
  const state = {
11123
11389
  boards: [], current: null, items: {},
@@ -12049,16 +12315,9 @@ if (descEl) descEl.addEventListener('input', () => {
12049
12315
  // --- Agent activity panel (live polling of the daemon API) ---
12050
12316
 
12051
12317
  const activity = {
12052
- open: false, timer: null, daemonUrl: null, lastEventAt: 0, eventsRing: [],
12318
+ open: false, timer: null, lastEventAt: 0, eventsRing: [],
12053
12319
  };
12054
12320
 
12055
- function resolveDaemonUrl() {
12056
- // Allow ?daemon=http://host:port override; fall back to localhost:18800 (MacBook) then 19900 (peer).
12057
- const q = new URLSearchParams(window.location.search).get('daemon');
12058
- if (q) return q.replace(/\\/+$/, '');
12059
- return localStorage.getItem('agentx.daemon') || 'http://localhost:18800';
12060
- }
12061
-
12062
12321
  function toggleActivity(force) {
12063
12322
  activity.open = typeof force === 'boolean' ? force : !activity.open;
12064
12323
  const panel = document.getElementById('activity-panel');
@@ -12071,8 +12330,9 @@ function toggleActivity(force) {
12071
12330
  }
12072
12331
 
12073
12332
  async function startActivity() {
12074
- activity.daemonUrl = resolveDaemonUrl();
12075
- document.getElementById('activity-source').textContent = activity.daemonUrl.replace(/^https?:\\/\\//, '');
12333
+ // Same-origin: the dashboard proxies its configured daemon. A direct call
12334
+ // to the daemon would be cross-origin, and the daemon no longer allows it.
12335
+ document.getElementById('activity-source').textContent = 'dashboard daemon';
12076
12336
  await tickActivity();
12077
12337
  activity.timer = setInterval(tickActivity, 3000);
12078
12338
  }
@@ -12085,10 +12345,10 @@ async function tickActivity() {
12085
12345
  try {
12086
12346
  // Fetch /agents (always present) + /business/status (optional \u2014 404 tolerated)
12087
12347
  const [agentsRes, bizRes] = await Promise.all([
12088
- fetch(activity.daemonUrl + '/agents').catch(() => null),
12089
- fetch(activity.daemonUrl + '/business/status').catch(() => null),
12348
+ fetch('/api/agents').catch(() => null),
12349
+ fetch('/api/business/status').catch(() => null),
12090
12350
  ]);
12091
- if (!agentsRes || !agentsRes.ok) throw new Error('daemon unreachable at ' + activity.daemonUrl);
12351
+ if (!agentsRes || !agentsRes.ok) throw new Error('daemon unreachable');
12092
12352
  const agents = await agentsRes.json();
12093
12353
  const biz = bizRes && bizRes.ok ? await bizRes.json() : null;
12094
12354
 
@@ -12176,9 +12436,9 @@ function appendEvents(events) {
12176
12436
  }
12177
12437
 
12178
12438
  loadBoards().catch(e => toast('Init failed: ' + e.message));
12179
- `;function un(t={}){let a=`<h1>Plain-English glossary</h1>
12439
+ `;function wn(t={}){let a=`<h1>Plain-English glossary</h1>
12180
12440
  <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
- ${en.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:Ls})}var Ls=`
12441
+ ${ln.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:Fs})}var Fs=`
12182
12442
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
12183
12443
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
12184
12444
  .lead {
@@ -12208,7 +12468,7 @@ article.term .alias {
12208
12468
  }
12209
12469
  article.term p {
12210
12470
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
12211
- }`;function mn(t={}){let e=`<div class="ax-wf__root">
12471
+ }`;function kn(t={}){let e=`<div class="ax-wf__root">
12212
12472
  <aside class="ax-wf__list">
12213
12473
  <header>
12214
12474
  <h2>Workflows</h2>
@@ -12285,7 +12545,7 @@ article.term p {
12285
12545
  </aside>
12286
12546
  </div>
12287
12547
 
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:Rs,scripts:`<script>${me({workflowHealth:Mt})}${Ps}</script>`})}var Rs=`
12548
+ <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:Us,scripts:`<script>${me({workflowHealth:Mt})}${Ws}</script>`})}var Us=`
12289
12549
  .ax-wf__root {
12290
12550
  display: grid;
12291
12551
  grid-template-columns: 340px 1fr;
@@ -12669,7 +12929,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
12669
12929
  font-size: 12px; z-index: 50;
12670
12930
  }
12671
12931
  .hint { color: var(--ax-muted); font-size: 11px; }
12672
- `,Ps=`
12932
+ `,Ws=`
12673
12933
  (() => {
12674
12934
  const $ = (sel) => document.querySelector(sel)
12675
12935
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -13110,7 +13370,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13110
13370
  description: { type: "string", description: "Issue body markdown" },
13111
13371
  action: { type: "string", enum: ["open", "reopen", "update", "close"] },
13112
13372
  labels: { type: "array", description: "Current labels (array of strings)" },
13113
- author: { type: "string", description: "Reporter's username" },
13373
+ author: { type: "string", description: "Username that triggered the event" },
13114
13374
  url: { type: "string", description: "GitLab URL of the issue" },
13115
13375
  project: { type: "string", description: "org/repo path" },
13116
13376
  },
@@ -13126,6 +13386,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13126
13386
  source_branch: { type: "string" },
13127
13387
  target_branch: { type: "string" },
13128
13388
  labels: { type: "array" },
13389
+ author: { type: "string", description: "Username that triggered the event" },
13129
13390
  url: { type: "string" },
13130
13391
  project: { type: "string" },
13131
13392
  },
@@ -13457,7 +13718,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13457
13718
  setInterval(refresh, 15000)
13458
13719
  })
13459
13720
  })();
13460
- `;function hn(t={}){let e=`<div class="ax-proc__root">
13721
+ `;function _n(t={}){let e=`<div class="ax-proc__root">
13461
13722
  <header class="ax-proc__header">
13462
13723
  <h1>Procedures</h1>
13463
13724
  <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 +13762,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13501
13762
  <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
13763
  <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
13764
  </section>
13504
- </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ds,scripts:`<script>${Os}</script>`})}var Ds=`
13765
+ </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Gs,scripts:`<script>${Xs}</script>`})}var Gs=`
13505
13766
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
13506
13767
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
13507
13768
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -13527,7 +13788,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13527
13788
  .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
13789
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
13529
13790
  .ax-proc__link:hover { text-decoration: underline; }
13530
- `,Os=`
13791
+ `,Xs=`
13531
13792
  (function(){
13532
13793
  function $(sel){ return document.querySelector(sel) }
13533
13794
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -13627,7 +13888,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13627
13888
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
13628
13889
  else bootAll()
13629
13890
  })();
13630
- `;function gn(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
13891
+ `;function En(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
13631
13892
  data-task-id="${P(t.taskId)}"
13632
13893
  data-agent-id="${P(t.agentId)}"
13633
13894
  data-node-url="${P(t.nodeUrl)}"
@@ -13670,7 +13931,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13670
13931
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
13671
13932
  </div>
13672
13933
  </footer>
13673
- </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Hs,scripts:`<script>${Ns}</script>`})}var Hs=`
13934
+ </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ks,scripts:`<script>${Js}</script>`})}var Ks=`
13674
13935
  /* The shell gives <main> no padding, so page content butted straight against
13675
13936
  the sticky topbar. Breathe. */
13676
13937
  .ax-task-page {
@@ -13812,7 +14073,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13812
14073
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
13813
14074
  }
13814
14075
 
13815
- `,Ns=`
14076
+ `,Js=`
13816
14077
  (function () {
13817
14078
  var root = document.querySelector('.ax-task-page');
13818
14079
  if (!root) return;
@@ -13827,6 +14088,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13827
14088
  var hintEl = document.getElementById('task-hint');
13828
14089
  var sendBtn = document.getElementById('task-send');
13829
14090
  var stopBtn = document.getElementById('task-stop');
14091
+ var composeEl = root.querySelector('.ax-task-page__compose');
13830
14092
 
13831
14093
  var buffer = '';
13832
14094
  var raf = 0;
@@ -14072,6 +14334,59 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14072
14334
  var seededAsk = root.getAttribute('data-ask');
14073
14335
  if (seededAsk) showAsk(seededAsk, '', root.getAttribute('data-ask-at'));
14074
14336
 
14337
+ function action(kind, message) {
14338
+ var q = '/api/task/action?node=' + encodeURIComponent(nodeUrl)
14339
+ + '&task=' + encodeURIComponent(taskId) + '&kind=' + encodeURIComponent(kind);
14340
+ // agent lets the daemon find the stored record when the task has
14341
+ // already finished, so a follow-up on a scheduled run resumes its chat.
14342
+ var payload = message ? { message: message, agent: agentId } : {};
14343
+ return fetch(q, {
14344
+ method: 'POST',
14345
+ headers: { 'Content-Type': 'application/json' },
14346
+ body: JSON.stringify(payload)
14347
+ }).then(function (r) { return r.json().catch(function () { return {}; }); });
14348
+ }
14349
+
14350
+ /** The Task page for another run of the same agent on this node. */
14351
+ function taskHref(id, channel) {
14352
+ var q = new URLSearchParams(location.search);
14353
+ q.set('agent', agentId);
14354
+ q.set('node', nodeUrl);
14355
+ if (channel) q.set('channel', channel);
14356
+ q.delete('archived'); q.delete('ask'); q.delete('at');
14357
+ return '/tasks/' + encodeURIComponent(id) + '?' + q.toString();
14358
+ }
14359
+
14360
+ sendBtn.addEventListener('click', function () {
14361
+ var text = (inputEl.value || '').trim();
14362
+ if (!text) { inputEl.focus(); return; }
14363
+ sendBtn.disabled = true;
14364
+ hintEl.textContent = 'queuing\u2026';
14365
+ action('followup', text).then(function (r) {
14366
+ sendBtn.disabled = false;
14367
+ if (r && r.error) { hintEl.textContent = 'failed: ' + r.error; return; }
14368
+ inputEl.value = '';
14369
+ // A finished scheduled run was continued as a new turn in its chat.
14370
+ // Follow that turn: it is where the reply will appear.
14371
+ if (r && r.resumed && r.taskId) { location.href = taskHref(r.taskId, r.channel); return; }
14372
+ if (r && r.resumed) { hintEl.textContent = 'agent busy \u2014 queued as the next turn in this chat'; return; }
14373
+ hintEl.textContent = 'queued \u2014 dispatches as the next turn';
14374
+ });
14375
+ });
14376
+
14377
+ stopBtn.addEventListener('click', function () {
14378
+ stopBtn.disabled = true;
14379
+ hintEl.textContent = 'stopping\u2026';
14380
+ action('cancel').then(function (r) {
14381
+ stopBtn.disabled = false;
14382
+ hintEl.textContent = (r && r.error) ? 'failed: ' + r.error : 'stop requested';
14383
+ });
14384
+ });
14385
+
14386
+ inputEl.addEventListener('keydown', function (e) {
14387
+ if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') { e.preventDefault(); sendBtn.click(); }
14388
+ });
14389
+
14075
14390
  // Archived: one fetch of the stored record, no SSE. Opening a stream for a
14076
14391
  // task that ended hours ago would sit "connecting\u2026" forever and then report
14077
14392
  // a disconnect, which reads as breakage rather than as history.
@@ -14086,6 +14401,14 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14086
14401
  .then(function (rec) {
14087
14402
  setStatus(rec.ok ? 'archived' : 'failed', rec.ok ? 'done' : 'err');
14088
14403
  showAsk(rec.message, rec.sender, rec.startedAt);
14404
+ // A scheduled run's chat has nobody on the other end, so this page is
14405
+ // where it continues: Send resumes the cron session with a new turn.
14406
+ // Other channels stay read-only \u2014 their replies belong in their chat.
14407
+ if (rec.channel === 'cron') {
14408
+ composeEl.hidden = false;
14409
+ stopBtn.style.display = 'none'; // nothing is running to stop
14410
+ inputEl.placeholder = 'Continue this scheduled run \u2014 your message starts a new turn in the same session. \u2318/Ctrl+Enter to send.';
14411
+ }
14089
14412
  var tx = rec.transcript || '';
14090
14413
  if (tx) append(tx);
14091
14414
  // Only append the final reply when the transcript didn't already
@@ -14132,43 +14455,8 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14132
14455
  if (!finished) setStatus('disconnected', 'err');
14133
14456
  });
14134
14457
 
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
14458
  })();
14171
- `;function fn(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14459
+ `;function Sn(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14172
14460
  data-agent-id="${P(t.agentId)}"
14173
14461
  data-agent-name="${P(e)}"
14174
14462
  data-node-url="${P(t.nodeUrl)}">
@@ -14197,7 +14485,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14197
14485
  <div class="ax-history__list" id="hist-list">
14198
14486
  <div class="ax-history__empty">loading\u2026</div>
14199
14487
  </div>
14200
- </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Bs,scripts:`<script>${zs}</script>`})}var Bs=`
14488
+ </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Vs,scripts:`<script>${Ys}</script>`})}var Vs=`
14201
14489
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
14202
14490
  flush against the sticky topbar. */
14203
14491
  .ax-history {
@@ -14249,7 +14537,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14249
14537
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
14250
14538
  }
14251
14539
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
14252
- `,zs=`
14540
+ `,Ys=`
14253
14541
  (function () {
14254
14542
  var root = document.querySelector('.ax-history');
14255
14543
  if (!root) return;
@@ -14349,25 +14637,25 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14349
14637
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
14350
14638
  });
14351
14639
  })();
14352
- `;function vn(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=>xn(e,a,i,{mode:"create",convertFromYaml:l}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Fs(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=>xn(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 qs=["mesh"];function xn(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 qs)!(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 Fs(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 Us(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 Us(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)}
14640
+ `;function Cn(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=>Tn(e,a,i,{mode:"create",convertFromYaml:l}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Zs(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 u=Ge(c.data).map(m=>({path:"",message:m}));return j(e,200,{ok:u.length===0,issues:u,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,u=>Tn(e,a,u,{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 Qs=["mesh"];function Tn(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 u of Qs)!(u in i)&&u in c&&(o[u]=c[u])}let l;try{l=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(i){let c=i?.message||String(i),u=i?.yamlPath,m=!!u||/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",...u?{path:u}:{}})}return e.layouts.sync(l.id,l.nodes.map(i=>i.id)),j(t,200,{workflow:l})}function Zs(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,u=r.get("summary")==="1"||r.get("summary")==="true",m=a.runs.list({workflowId:c,limit:i});if(!u)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 u=c?.status;return u!=="paused"&&u!=="running"&&u!=="canceled"?j(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(i,u)?j(e,200,{ok:!0,runId:i,status:u}):j(e,404,{error:"run not found"})})}let l=o.match(/^\/([^\/?]+)(\/stream)?$/);if(l){let i=decodeURIComponent(l[1]);if(l[2])return ei(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 ei(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
14641
 
14354
- `);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)}
14642
+ `);let o=!1,s=()=>{o=!0,i?.(),clearInterval(u);try{e.end()}catch{}};t.on("close",s);let l=m=>{if(!o)try{e.write(`data: ${JSON.stringify(m)}
14355
14643
 
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 cc(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,ai(_,t))}catch(b){console.error(` Board "${_.id}" failed to initialize: ${b.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);Fa(t),$t({business:t.business?.enabled===!0}),Ws(async(_,b)=>{try{await Qs(_,b,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:m})}catch(C){v(b,500,{error:C.message||"internal error"})}}).listen(n,r,()=>{let _=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
14644
+ `)}catch{s()}},i=a.runEvents?.subscribe(n,l),c=r.updatedAt,u=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 Tc(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,ui(_,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),u=new St(i?{baseDir:i,nodeId:l}:{nodeId:l}),m=new Tt(i?{baseDir:i}:void 0);Va(t),Dt({business:t.business?.enabled===!0}),ti(async(_,S)=>{try{await li(_,S,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:u,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
14645
  Live dashboard: http://${_}:${n}
14358
14646
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
14359
14647
  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
14648
+ `),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 ii=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 li(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(Rt(t.headers)==="foreign"&&Pt(o)){v(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(o==="GET"&&ii.has(r)&&Vt("page",r),o==="GET"&&r==="/"){let d=Gt();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(yn({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 p=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:p||"{}"});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),p=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await se(t):void 0,f=h?.node??p,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),p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:p,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 p=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});v(e,p.status,await p.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(sa({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oa({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(ta({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,p=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(p)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fn({peers:D(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wn({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kn({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wt({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let d=n.searchParams.get("agent")||"",p=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(En({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:p,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(Sn({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"){Xt(t,e);return}if(o==="POST"&&r==="/api/setup"){await Kt(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Jt(t,e);return}if(o==="GET"&&r==="/admin"){pa(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){va(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}Ta(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 Ci(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await pt(t,e,r,h=>jn(h,a.config));return}let p=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(p){let h=decodeURIComponent(p[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 An(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 p=vt(d,a.config);if(!p){v(e,404,{error:`unknown peer: ${d}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,b=>b.startsWith("?")?"?":"");await An(t,e,p,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ca(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Ai(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($a({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Ia(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ja({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(La({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 hi(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 Ya(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 Za(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){an(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",p=d.startsWith("Bearer ")?d.slice(7):"";if(p!==a.token){let h=new ae,f=p?h.verify(p):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ua(t,e);return}if(r.startsWith("/api/admin/graph/")){await ba(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await nn(t,e,r);return}if(r.startsWith("/api/admin/")){await ma(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(ia);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 p=Si("web/"+d);try{let h=await Ti(p),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),p=n.searchParams.get("timezone")||"UTC",h=await xt(a.config,{date:d,timezone:p});v(e,200,h)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(p,h,f,b)=>{let x=parseInt(n.searchParams.get(p)||"",10);return Number.isFinite(x)?Math.max(f,Math.min(b,x)):h};try{let p=await le(a.config);v(e,200,await xn(p,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(p){v(e,502,{error:p.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 p=(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 bn(h,{day:d,tzOffsetMinutes:p("tzOffset",0,-840,840),limit:p("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 p=n.searchParams,h;if(r==="/api/mesh/thread"){let[f,b,x]=[p.get("agent"),p.get("channel"),p.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(p.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[f,b]=[p.get("kind"),p.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(p.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[f,b,x]=[p.get("agent"),p.get("channel"),p.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(p.get("tzOffset")||"0")}`}else{let f=p.get("task");if(!f){v(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(f)}`}try{await vn(e,await le(a.config),d,h)}catch(f){v(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/live/stream"){fi(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),p=d.searchParams.get("node"),h=d.searchParams.get("agent"),f=d.searchParams.get("task");if(!p||!h||!f){v(e,400,{error:"node, agent, task query params required"});return}await xi(t,e,a,p,h,f);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),p=d.searchParams.get("node"),h=d.searchParams.get("agent"),f=d.searchParams.get("task"),b=d.searchParams.get("limit")||"50";if(!p||!h){v(e,400,{error:"node and agent query params required"});return}await yi(e,a,p,h,f,b);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),p=d.searchParams.get("node"),h=d.searchParams.get("task"),f=d.searchParams.get("kind");if(!p||!h||f!=="cancel"&&f!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await wi(t,e,a,p,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 In(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 p=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!p.ok)throw new Error(`HTTP ${p.status}`);let h=await p.json();v(e,200,h)}catch(d){v(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let p=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!p.ok){v(e,p.status,{error:`HTTP ${p.status}`});return}v(e,200,await p.json())}catch(d){v(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await se(t);try{let p=await _i(a.config,d);v(e,200,p)}catch(p){v(e,502,{error:p.message||"draft failed"})}return}let u=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(u&&o==="POST"){let d=u[1];if(!vi(t,e,[`agent:${d}`]))return;await bi(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",p=d.startsWith("Bearer ")?d.slice(7):"";if(p!==a.token){let h=new ae,f=p?h.verify(p):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 p=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(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
14649
 
14362
- `)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let w of h)(async()=>{let M={Accept:"text/event-stream"};w.token&&(M.Authorization=`Bearer ${w.token}`);let A=new AbortController;y.push(A);try{let k=await fetch(`${w.url.replace(/\/+$/,"")}/events${u?`?${u}`:""}`,{headers:M,signal:A.signal});if(!k.ok||!k.body)return;let I=k.body.getReader(),L=new TextDecoder,R="";for(;!f.flag;){let{done:N,value:Y}=await I.read();if(N)break;R+=L.decode(Y,{stream:!0});let B;for(;(B=R.indexOf(`
14650
+ `)}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${p?`?${p}`:""}`,{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
14651
 
14364
14652
  `))>=0;){let O=R.slice(0,B);if(R=R.slice(B+2),f.flag)break;try{e.write(O+`
14365
14653
 
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",y=a.workflowRuns.list({limit:u,workflowId:h}),x=`?limit=${u}${h?`&workflowId=${encodeURIComponent(h)}`:""}${f?"&summary=1":""}`,w=[{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(w.map(async L=>{let R={};L.token&&(R.Authorization=`Bearer ${L.token}`);try{let N=new AbortController,Y=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(Y)}}catch{return[]}})),A=new Map;for(let L of y)A.set(L.id,L);for(let L of M)for(let R of L)A.set(R.id,R);let k=Array.from(A.values()).sort((L,R)=>L.updatedAt<R.updatedAt?1:-1).slice(0,u),I=f?k.map(L=>ti(L)):k;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 y={};f.token&&(y.Authorization=`Bearer ${f.token}`);let x=await fetch(`${f.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:y});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??{})}),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(r.startsWith("/api/workflows")&&vn(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(u,h,f)=>{if(a.token)return!0;let y=Ke(u);if(!y)return!0;let x=new ae().verify(y);if(!x)return v(h,401,{error:"invalid or revoked token"}),!1;for(let w of f)if(!ve(x,w))return v(h,403,{error:`token missing scope: ${w}`,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 b=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(b&&o==="GET"){let d=a.sources.get(b[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 C=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(C&&o==="GET"){let d=a.sources.get(C[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$/),S=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 y=a.sources.get(d);if(!y){v(e,503,{error:`board "${d}" source unavailable`});return}let x=await se(t),w=f.columns.find(A=>A.id===x.to),M=f.columns.find(A=>A.id===x.from);if(!w){v(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await ei(y,h,M,w),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(S){let[,d,u]=S,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 y=a.sources.get(d);if(!y){v(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!h){let{columns:x,totals:w}=await Zs(f,y,n.searchParams);v(e,200,{columns:x,totals:w});return}if(o==="GET"&&h){try{let x=typeof y.getItem=="function"?await y.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 w=typeof y.updateItem=="function"?await y.updateItem(h,x):null;if(!w){v(e,501,{error:"update unsupported"});return}ht({actor:gt(t),action:"update",boardId:d,itemId:h,payload:x}),v(e,200,w)}catch(w){v(e,502,{error:w.message})}return}if(o==="POST"&&!h){let x=await se(t);if(!x.title){v(e,400,{error:"title required"});return}if(!y.capabilities.create||!y.create){v(e,400,{error:`source ${y.type} does not support create`});return}try{let w=await y.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:w.id,payload:{title:x.title}}),v(e,201,w)}catch(w){v(e,502,{error:w.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 Zs(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"}):[],b={};for(let d of t.columns)b[d.id]=[];let C=t.columns.find(d=>d.kind==="closed");for(let d of _)C&&b[C.id].push({...d,stage:C.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=b[u];h&&h.push({...d,stage:u})}if(l)for(let d of Object.keys(b))b[d]=b[d].filter(u=>u.assignee===l);for(let d of Object.keys(b))b[d].sort((u,h)=>{let f=(u.priority??99)-(h.priority??99);return f!==0?f:(h.updatedAt||"").localeCompare(u.updatedAt||"")});let S=Object.fromEntries(Object.entries(b).map(([d,u])=>[d,u.length]));return{columns:b,totals:S}}async function ei(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 ti(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 ai(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 Lt(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");yn(e)||Xs(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
14367
- `;Gs(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 ni(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)]);if(!i||!i.ok)return o.error=i?`HTTP ${i.status}`:"unreachable",o;let _=await i.json();if(o.agents=_.map(b=>({id:b.id,name:b.name,tier:b.tier,model:b.model,skillCount:Number.isFinite(b.skillCount)?b.skillCount:void 0,active:b.active||0,total:b.total||0,errors:b.errors||0,lastActive:b.lastActive,lastSummary:b.lastSummary,hourlyTasks:Array.isArray(b.hourlyTasks)?b.hourlyTasks:void 0,runningTasks:Array.isArray(b.runningTasks)?b.runningTasks:[]})),l&&l.ok){let b=await l.json();o.uptimeSec=b.uptime,o.name=b.node?.name||b.node?.id||t,o.id=b.node?.id||t,b.usage&&(o.usage=b.usage)}if(p&&p.ok){let b=await p.json();o.crons=b.map(C=>({id:C.id,enabled:C.enabled===!0,schedule:String(C.schedule||""),timezone:C.timezone,agent:String(C.agent||""),model:C.model,nextRun:C.nextRun,retryPending:C.retryPending===!0,consecutiveErrors:Number(C.consecutiveErrors)||0}))}if(m&&m.ok){let b=await m.json();o.cronRuns=Array.isArray(b.runs)?b.runs:[]}if(g&&g.ok){let b=await g.json().catch(()=>null);b?.active&&b.kind==="lesson"&&(o.lesson={agentId:b.agentId??null,mode:String(b.mode||"teach"),goal:String(b.goal||""),step:Number(b.step)||0,saying:String(b.saying||""),startedAt:String(b.startedAt||"")})}o.reachable=!0,o._peers=Array.isArray(c&&await oi(c))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Be=null;function ri(t){if(Be)return Be;let e=ke(process.cwd(),".agentx/wiki");return Be=Gt({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Be}var ft=new WeakMap;async function oi(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=>ni(s.url,s.token,a.signal,e)));return{ts:new Date().toISOString(),nodes:o}}finally{clearTimeout(n)}}function si(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}
14654
+ `)}catch{f.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),p=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:p,workflowId:h}),x=`?limit=${p}${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,p),I=f?w.map(L=>pi(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]),p=a.workflowRuns.get(d);if(p){v(e,200,{run:p});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 p=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${p}/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(()=>({})),p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${h}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:p,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")&&Cn(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(p,h,f)=>{if(a.token)return!0;let b=Ke(p);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 p=typeof d.listMembers=="function"?await d.listMembers():[];v(e,200,p)}catch(p){v(e,502,{error:p.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 p=typeof d.listMilestones=="function"?await d.listMilestones():[];v(e,200,p)}catch(p){v(e,502,{error:p.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,p]=E,h=decodeURIComponent(p),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 ci(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,p]=T,h=p?decodeURIComponent(p):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 di(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 di(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let p of t.columns)d[p.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(p=>[p.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),u=t.columns.some(d=>d.kind!=="closed"),m=t.columns.some(d=>d.kind==="closed"),g=u?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 p=yt(d,E);if(!p)continue;let h=S[p];h&&h.push({...d,stage:p})}if(l)for(let d of Object.keys(S))S[d]=S[d].filter(p=>p.assignee===l);for(let d of Object.keys(S))S[d].sort((p,h)=>{let f=(p.priority??99)-(h.priority??99);return f!==0?f:(h.updatedAt||"").localeCompare(p.updatedAt||"")});let T=Object.fromEntries(Object.entries(S).map(([d,p])=>[d,p.length]));return{columns:S,totals:T}}async function ci(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 pi(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 ui(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 Ht(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");Mn(e)||ni(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
14655
+ `;ai(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 mi(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,u,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(u&&u.ok){let k=await u.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 gi(c))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Be=null;function hi(t){if(Be)return Be;let e=ke(process.cwd(),".agentx/wiki");return Be=Zt({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Be}var ft=new WeakMap;async function gi(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=>mi(s.url,s.token,a.signal,e)));return{ts:new Date().toISOString(),nodes:o}}finally{clearTimeout(n)}}function fi(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
14656
  data: ${JSON.stringify(i)}
14369
14657
 
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 ii(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),l=new Set;l.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let b of a.config.dashboard.daemons)l.add(b.url.replace(/\/+$/,""));try{let b=await ze(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let C of b)l.add(C.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(b=>b.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(b){v(e,502,{error:b.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:b,done:C}=await g.read();if(C)break;b&&e.write(b)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function li(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 di(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 ci(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 pi(t,e,a,n,r,o){await wn(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function wn(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 ui=`
14658
+ `)},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 xi(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 u=new AbortController,m;try{m=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:u.signal})}catch(S){v(e,502,{error:S.message||"upstream connect failed"});return}if(!m.ok||!m.body){v(e,m.status||502,{error:`upstream HTTP ${m.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let 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",()=>{u.abort();try{e.end()}catch{}})}function vi(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 bi(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||{}}})}),u=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(u)}catch(c){v(e,502,{error:c.message||"upstream call failed"})}}async function yi(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 u=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let m=await fetch(`${s}${u}`,{headers:c}),g=await m.text();t.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(g)}catch(m){v(t,502,{error:m.message||"upstream fetch failed"})}}async function wi(t,e,a,n,r,o){await In(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function In(t,e,a,n,r){let o=n.replace(/\/+$/,""),s=new Set;s.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of a.config.dashboard.daemons)s.add(u.url.replace(/\/+$/,""));try{let u=await ze(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let m of u)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(u=>u.url.replace(/\/+$/,"")===o)?.token,i={"Content-Type":"application/json",Accept:"application/json"};l&&(i.Authorization=`Bearer ${l}`);let c="{}";try{let u=await se(t);c=u?JSON.stringify(u):"{}"}catch{}try{let u=await fetch(`${o}${r}`,{method:"POST",headers:i,body:c}),m=await u.text();e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(m)}catch(u){v(e,502,{error:u.message||"upstream fetch failed"})}}var ki=`
14371
14659
  You are helping draft a new GitLab issue. Follow these conventions strictly.
14372
14660
 
14373
14661
  Title pattern:
@@ -14399,10 +14687,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
14399
14687
  Shape:
14400
14688
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
14401
14689
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
14402
- `;async function mi(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):
14690
+ `;async function _i(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
14691
  - ${r.knownLabels.slice(0,60).join(`
14404
14692
  - `)}`:"",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:ui}})});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=hi(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 hi(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 gi(t){let e=Vs(Js(import.meta.url));return ke(e,t)}async function fi(t){return Ks(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 kn(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:kn(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 xi(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 _n(r,a.config)))}async function _n(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 qa(n)}async function vi(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(b=>yn(b));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}
14693
+ `),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:ki}})});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 u=(c.content||"").toString(),m=Ei(u);if(!m||typeof m.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+u.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:u}}function Ei(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 Si(t){let e=si(oi(import.meta.url));return ke(e,t)}async function Ti(t){return ri(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 $n(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:$n(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 Ci(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 jn(r,a.config)))}async function jn(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,u=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(u)}}catch{return null}}));for(let l of s)l&&n.push(l);return Ja(n)}async function Ai(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=>Mn(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
14694
 
14407
14695
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),l="",i=m=>{l+=m.toString("utf8");let g;for(;(g=l.indexOf(`
14408
14696
  `))>=0;){let _=l.slice(0,g).replace(/\r$/,"");l=l.slice(g+1);try{e.write(`event: line
@@ -14410,5 +14698,5 @@ data: ${_.replace(/\n/g," ")}
14410
14698
 
14411
14699
  `)}catch{}}};s.stdout?.on("data",i),s.stderr?.on("data",i);let c=setInterval(()=>{try{e.write(`: hb
14412
14700
 
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 bn(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",b=>_.push(b)),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:kn(n),token:n.dashboardToken||n.token}:null}export{cc as startBoardDashboard};
14414
- //# sourceMappingURL=board-dashboard-HLTVSSGW.js.map
14701
+ `)}catch{}},15e3),u=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",u),s.on("exit",u),s.on("error",u)}async function An(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 u=t.headers["x-requested-with"];u&&(i["X-Requested-With"]=Array.isArray(u)?u[0]:u),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"}),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:$n(n),token:n.dashboardToken||n.token}:null}export{Tc as startBoardDashboard};
14702
+ //# sourceMappingURL=board-dashboard-B5FMUMGA.js.map