agentix-cli 0.53.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/AgentClient.swift +26 -0
  2. package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +55 -3
  3. package/apps/mac-voice/Sources/AgentXVoice/main.swift +136 -13
  4. package/dist/{App-R62ZQVSF.js → App-4EM7IPB3.js} +2 -2
  5. package/dist/{ChatApp-AS567EFE.js → ChatApp-FYTEEGSU.js} +2 -2
  6. package/dist/{agent-H4NB4BUA.js → agent-RZ46ZB4W.js} +2 -2
  7. package/dist/{board-dashboard-E3MUVNVQ.js → board-dashboard-NRRYCDZW.js} +1097 -215
  8. package/dist/board-dashboard-NRRYCDZW.js.map +1 -0
  9. package/dist/chunk-2D3RYIDU.js +3 -0
  10. package/dist/chunk-2D3RYIDU.js.map +1 -0
  11. package/dist/{chunk-KB7YIM3W.js → chunk-4HEVSWO3.js} +2 -2
  12. package/dist/{chunk-7DPKPBRJ.js → chunk-6AK6WKE5.js} +2 -2
  13. package/dist/{chunk-TH5KNJLA.js → chunk-723K4SAW.js} +2 -2
  14. package/dist/{chunk-OMTRHHZJ.js → chunk-76AHNHWC.js} +44 -45
  15. package/dist/chunk-76AHNHWC.js.map +1 -0
  16. package/dist/{chunk-KJWBQZT7.js → chunk-C3VRBEJ7.js} +2 -2
  17. package/dist/{chunk-C5JXPMTW.js → chunk-CELYD5QW.js} +2 -2
  18. package/dist/{chunk-FSZXY53Z.js → chunk-D3LSPFHK.js} +2 -2
  19. package/dist/chunk-EJ5ISSWW.js +151 -0
  20. package/dist/chunk-EJ5ISSWW.js.map +1 -0
  21. package/dist/{chunk-FS4WBYY3.js → chunk-EZN2YXRY.js} +2 -2
  22. package/dist/{chunk-QU6ZUKAD.js → chunk-GSOL2LW6.js} +2 -2
  23. package/dist/{chunk-7OWXFLAM.js → chunk-JC5Q5MPI.js} +171 -164
  24. package/dist/chunk-JC5Q5MPI.js.map +1 -0
  25. package/dist/{chunk-SABOPOYX.js → chunk-K4RDE6YU.js} +211 -197
  26. package/dist/chunk-K4RDE6YU.js.map +1 -0
  27. package/dist/{ntfy-ZY2NPGBA.js → chunk-KZKDVIOE.js} +3 -3
  28. package/dist/chunk-KZKDVIOE.js.map +1 -0
  29. package/dist/{chunk-VD4TMPJI.js → chunk-LKJSPO3S.js} +2 -2
  30. package/dist/{chunk-NF52Q3TV.js → chunk-M4AG2YNX.js} +2 -2
  31. package/dist/{chunk-WKTFP3SK.js → chunk-NO2HOK4B.js} +2 -2
  32. package/dist/{chunk-KFG6WWFS.js → chunk-O3XG2NVR.js} +18 -18
  33. package/dist/{chunk-KFG6WWFS.js.map → chunk-O3XG2NVR.js.map} +1 -1
  34. package/dist/chunk-QD6IICK7.js +2 -0
  35. package/dist/chunk-QD6IICK7.js.map +1 -0
  36. package/dist/{chunk-PGJL5V6Y.js → chunk-SA23V7WX.js} +2 -2
  37. package/dist/chunk-U4H35SJS.js +15 -0
  38. package/dist/chunk-U4H35SJS.js.map +1 -0
  39. package/dist/chunk-UIVHSYCN.js +29 -0
  40. package/dist/chunk-UIVHSYCN.js.map +1 -0
  41. package/dist/{chunk-6OOK7Y4S.js → chunk-W4YMMWJL.js} +2 -2
  42. package/dist/chunk-WOMQ2VGA.js +5 -0
  43. package/dist/{chunk-OV35MJKS.js.map → chunk-WOMQ2VGA.js.map} +1 -1
  44. package/dist/chunk-WWMFNLKD.js +10 -0
  45. package/dist/chunk-WWMFNLKD.js.map +1 -0
  46. package/dist/chunk-X5C5W3E4.js +3 -0
  47. package/dist/chunk-X5C5W3E4.js.map +1 -0
  48. package/dist/{chunk-CCMM5TP4.js → chunk-XEOAKD5C.js} +2 -2
  49. package/dist/cli.js +1 -1
  50. package/dist/cli.js.map +1 -1
  51. package/dist/client-IA7ZPE56.js +2 -0
  52. package/dist/{compaction-NWPBPWY2.js → compaction-H5U32UU6.js} +2 -2
  53. package/dist/config-HPN2F7LH.js +2 -0
  54. package/dist/config-mutator-7GPTMTVB.js +2 -0
  55. package/dist/doctor-IBWQVQV4.js +2 -0
  56. package/dist/index.d.ts +273 -19
  57. package/dist/index.js +1 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/memory-extract-F76BE6KA.js +2 -0
  60. package/dist/ntfy-52EXHVMD.js +2 -0
  61. package/dist/program-D5TAPSIH.js +2 -0
  62. package/dist/{promote-DJFMTLRC.js → promote-T4UJROEH.js} +2 -2
  63. package/dist/push-HEDA6P3B.js +2 -0
  64. package/dist/push-HEDA6P3B.js.map +1 -0
  65. package/dist/push-keys-2DTD7YNQ.js +2 -0
  66. package/dist/push-store-LXTYULUF.js +2 -0
  67. package/dist/query-VUJC4Y5O.js +2 -0
  68. package/dist/registry-DX2RI7I7.js +2 -0
  69. package/dist/{request-planner-2H7HCUCZ.js → request-planner-B7DE7VJR.js} +2 -2
  70. package/dist/{review-candidates-U7R64OCS.js → review-candidates-4YJHIBAF.js} +2 -2
  71. package/dist/routing-MZG3UODH.js +2 -0
  72. package/dist/schedule-tool-A4OFQ4YZ.js +2 -0
  73. package/dist/scheduler-RHJW2V4M.js +2 -0
  74. package/dist/scheduler-RHJW2V4M.js.map +1 -0
  75. package/dist/seat-2PEI7JRX.js +2 -0
  76. package/dist/seat-2PEI7JRX.js.map +1 -0
  77. package/dist/{select-XGK27RPP.js → select-4KIUR27O.js} +2 -2
  78. package/dist/{set-enabled-7YGN2FAZ.js → set-enabled-SE7HQKPF.js} +2 -2
  79. package/dist/subscriptions-RYVPHVIV.js +2 -0
  80. package/dist/subscriptions-RYVPHVIV.js.map +1 -0
  81. package/dist/{tool-HKDIZ6I4.js → tool-5VMD7IE4.js} +2 -2
  82. package/dist/wiki-2QFLAH4U.js +2 -0
  83. package/dist/wiki-2QFLAH4U.js.map +1 -0
  84. package/package.json +3 -1
  85. package/dist/board-dashboard-E3MUVNVQ.js.map +0 -1
  86. package/dist/chunk-47EEUZBK.js +0 -15
  87. package/dist/chunk-47EEUZBK.js.map +0 -1
  88. package/dist/chunk-7OWXFLAM.js.map +0 -1
  89. package/dist/chunk-D4HAR3L3.js +0 -28
  90. package/dist/chunk-D4HAR3L3.js.map +0 -1
  91. package/dist/chunk-HRBKSZ34.js +0 -2
  92. package/dist/chunk-HRBKSZ34.js.map +0 -1
  93. package/dist/chunk-IDYP7G7Z.js +0 -150
  94. package/dist/chunk-IDYP7G7Z.js.map +0 -1
  95. package/dist/chunk-OMTRHHZJ.js.map +0 -1
  96. package/dist/chunk-OV35MJKS.js +0 -5
  97. package/dist/chunk-SABOPOYX.js.map +0 -1
  98. package/dist/client-XTQDYMOX.js +0 -2
  99. package/dist/config-3SW4V44Z.js +0 -2
  100. package/dist/config-mutator-H32FXUYJ.js +0 -2
  101. package/dist/doctor-J6RCHFVE.js +0 -2
  102. package/dist/memory-extract-MGGXIZTE.js +0 -2
  103. package/dist/ntfy-ZY2NPGBA.js.map +0 -1
  104. package/dist/program-SQTOPCQW.js +0 -2
  105. package/dist/query-UAZUMU4N.js +0 -2
  106. package/dist/registry-4OUBA2TY.js +0 -2
  107. package/dist/routing-LVQH6WOJ.js +0 -2
  108. package/dist/schedule-tool-2BONJVCJ.js +0 -2
  109. package/dist/scheduler-7CEXDECA.js +0 -2
  110. package/dist/seat-2KGFNCIW.js +0 -2
  111. package/dist/wiki-6YT7B5HU.js +0 -2
  112. /package/dist/{App-R62ZQVSF.js.map → App-4EM7IPB3.js.map} +0 -0
  113. /package/dist/{ChatApp-AS567EFE.js.map → ChatApp-FYTEEGSU.js.map} +0 -0
  114. /package/dist/{agent-H4NB4BUA.js.map → agent-RZ46ZB4W.js.map} +0 -0
  115. /package/dist/{chunk-KB7YIM3W.js.map → chunk-4HEVSWO3.js.map} +0 -0
  116. /package/dist/{chunk-7DPKPBRJ.js.map → chunk-6AK6WKE5.js.map} +0 -0
  117. /package/dist/{chunk-TH5KNJLA.js.map → chunk-723K4SAW.js.map} +0 -0
  118. /package/dist/{chunk-KJWBQZT7.js.map → chunk-C3VRBEJ7.js.map} +0 -0
  119. /package/dist/{chunk-C5JXPMTW.js.map → chunk-CELYD5QW.js.map} +0 -0
  120. /package/dist/{chunk-FSZXY53Z.js.map → chunk-D3LSPFHK.js.map} +0 -0
  121. /package/dist/{chunk-FS4WBYY3.js.map → chunk-EZN2YXRY.js.map} +0 -0
  122. /package/dist/{chunk-QU6ZUKAD.js.map → chunk-GSOL2LW6.js.map} +0 -0
  123. /package/dist/{chunk-VD4TMPJI.js.map → chunk-LKJSPO3S.js.map} +0 -0
  124. /package/dist/{chunk-NF52Q3TV.js.map → chunk-M4AG2YNX.js.map} +0 -0
  125. /package/dist/{chunk-WKTFP3SK.js.map → chunk-NO2HOK4B.js.map} +0 -0
  126. /package/dist/{chunk-PGJL5V6Y.js.map → chunk-SA23V7WX.js.map} +0 -0
  127. /package/dist/{chunk-6OOK7Y4S.js.map → chunk-W4YMMWJL.js.map} +0 -0
  128. /package/dist/{chunk-CCMM5TP4.js.map → chunk-XEOAKD5C.js.map} +0 -0
  129. /package/dist/{client-XTQDYMOX.js.map → client-IA7ZPE56.js.map} +0 -0
  130. /package/dist/{compaction-NWPBPWY2.js.map → compaction-H5U32UU6.js.map} +0 -0
  131. /package/dist/{config-3SW4V44Z.js.map → config-HPN2F7LH.js.map} +0 -0
  132. /package/dist/{config-mutator-H32FXUYJ.js.map → config-mutator-7GPTMTVB.js.map} +0 -0
  133. /package/dist/{doctor-J6RCHFVE.js.map → doctor-IBWQVQV4.js.map} +0 -0
  134. /package/dist/{memory-extract-MGGXIZTE.js.map → memory-extract-F76BE6KA.js.map} +0 -0
  135. /package/dist/{program-SQTOPCQW.js.map → ntfy-52EXHVMD.js.map} +0 -0
  136. /package/dist/{promote-DJFMTLRC.js.map → program-D5TAPSIH.js.map} +0 -0
  137. /package/dist/{query-UAZUMU4N.js.map → promote-T4UJROEH.js.map} +0 -0
  138. /package/dist/{registry-4OUBA2TY.js.map → push-keys-2DTD7YNQ.js.map} +0 -0
  139. /package/dist/{routing-LVQH6WOJ.js.map → push-store-LXTYULUF.js.map} +0 -0
  140. /package/dist/{schedule-tool-2BONJVCJ.js.map → query-VUJC4Y5O.js.map} +0 -0
  141. /package/dist/{scheduler-7CEXDECA.js.map → registry-DX2RI7I7.js.map} +0 -0
  142. /package/dist/{request-planner-2H7HCUCZ.js.map → request-planner-B7DE7VJR.js.map} +0 -0
  143. /package/dist/{review-candidates-U7R64OCS.js.map → review-candidates-4YJHIBAF.js.map} +0 -0
  144. /package/dist/{seat-2KGFNCIW.js.map → routing-MZG3UODH.js.map} +0 -0
  145. /package/dist/{wiki-6YT7B5HU.js.map → schedule-tool-A4OFQ4YZ.js.map} +0 -0
  146. /package/dist/{select-XGK27RPP.js.map → select-4KIUR27O.js.map} +0 -0
  147. /package/dist/{set-enabled-7YGN2FAZ.js.map → set-enabled-SE7HQKPF.js.map} +0 -0
  148. /package/dist/{tool-HKDIZ6I4.js.map → tool-5VMD7IE4.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as da}from"./chunk-GUJB53QU.js";import{a as C,b as ca,c as pa,d as ua,e as ma,f as V,g as me,h as st,i as be,j as ha,k as fa,l as xa,m as va,n as ba}from"./chunk-OMTRHHZJ.js";import{a as ga}from"./chunk-Z3IP66SL.js";import{a as oa,b as ve,d as $,e as P,j as He,k as Be,l as J,m as q,n as ze,o as sa,p as ia,q as la}from"./chunk-KAFO5QZR.js";import{B as ue,C as Jt,D as Vt,I as Zt,K as xe,L as Re,M as Pe,N as Oe,O as De,P as ea,Q as ta,R as aa,S as Ne,U as na,X as ra,a as Ut,c as $e,d as ot,e as Wt,i as Gt,u as je,v as Le}from"./chunk-D4HAR3L3.js";import{g as qt,h as Ft}from"./chunk-TH5KNJLA.js";import{a as Yt,b as Qt}from"./chunk-LQRBGQIR.js";import{o as Xt,r as Kt}from"./chunk-S7CVSKOX.js";import"./chunk-6OOK7Y4S.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{a as Nt,c as nt,d as rt,h as Ht,i as Bt,j as zt}from"./chunk-C5JXPMTW.js";import"./chunk-N6EWZGIX.js";import"./chunk-WP6KLXTP.js";import"./chunk-DP7RTNDM.js";import"./chunk-PGJL5V6Y.js";import"./chunk-KFG6WWFS.js";import"./chunk-AFRHKA7B.js";import"./chunk-FS4WBYY3.js";import"./chunk-HRBKSZ34.js";import"./chunk-VD4TMPJI.js";import{b as Dt}from"./chunk-KJWBQZT7.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-NF52Q3TV.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as Pt,b as Ot,c as br,m as K,p as at}from"./chunk-47EEUZBK.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function it(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 ya(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:it(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var Y={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},he=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",qe=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+he(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function wa(t={}){return $({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as ka}from"./chunk-WWMFNLKD.js";import{a as Aa}from"./chunk-GUJB53QU.js";import{a as C,b as Ma,c as Ia,d as $a,e as La,f as we,g as ja,h as Ra,i as Na,j as Oa,k as Da}from"./chunk-76AHNHWC.js";import{a as Pa}from"./chunk-Z3IP66SL.js";import{a as _a,b as ue,c as Ea,d as $,e as P,j as Ge,k as Xe,l as Z,m as U,n as Ke,o as Sa,p as Ta,q as Ca}from"./chunk-KAFO5QZR.js";import{A as Be,G as se,H as ua,I as ma,N as ga,P as ye,Q as ze,R as qe,S as Ue,T as Fe,U as xa,V as va,W as ba,X as We,Z as ya,a as ra,aa as wa,c as De,d as ht,e as oa,i as sa,k as ia,m as Q,n as ge,o as gt,z as He}from"./chunk-UIVHSYCN.js";import{g as aa,h as na}from"./chunk-723K4SAW.js";import{o as la,r as da}from"./chunk-S7CVSKOX.js";import{a as fa,b as ha}from"./chunk-LQRBGQIR.js";import"./chunk-SA23V7WX.js";import"./chunk-W4YMMWJL.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ca,c as pa}from"./chunk-2D3RYIDU.js";import{a as Qt,c as mt,d as ft,h as Zt,i as ea,j as ta}from"./chunk-CELYD5QW.js";import"./chunk-WP6KLXTP.js";import{a as ut}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-O3XG2NVR.js";import"./chunk-EZN2YXRY.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-LKJSPO3S.js";import{b as Yt}from"./chunk-C3VRBEJ7.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-M4AG2YNX.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as Jt,b as Vt,c as Zr,n as Y,q as pt}from"./chunk-U4H35SJS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function xt(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function Ha(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:xt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ee={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},xe=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Je=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+xe(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ba(t={}){return $({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
2
2
 
3
3
  <div class="bf-head">
4
4
  <div>
@@ -7,8 +7,8 @@ import{a as da}from"./chunk-GUJB53QU.js";import{a as C,b as ca,c as pa,d as ua,e
7
7
  </div>
8
8
  <div class="bf-sync">
9
9
  <span class="bf-sync__t" id="synced">Gathering&hellip;</span>
10
- <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${he(Y.pulse,13)} Activity</a>
11
- <button class="ax-btn" id="refresh" title="Refresh now">${he(Y.refresh)} Refresh</button>
10
+ <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${xe(ee.pulse,13)} Activity</a>
11
+ <button class="ax-btn" id="refresh" title="Refresh now">${xe(ee.refresh)} Refresh</button>
12
12
  </div>
13
13
  </div>
14
14
 
@@ -21,24 +21,24 @@ import{a as da}from"./chunk-GUJB53QU.js";import{a as C,b as ca,c as pa,d as ua,e
21
21
 
22
22
  <div class="bf-grid">
23
23
  <section class="bf-col">
24
- ${qe(Y.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
24
+ ${Je(ee.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
25
25
  <div id="you" class="bf-col"></div>
26
26
 
27
- ${qe(Y.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed &mdash; not yet automatic</span>')}
27
+ ${Je(ee.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed &mdash; not yet automatic</span>')}
28
28
  <div id="agents" class="bf-col"></div>
29
29
  <button class="ax-btn ax-btn--sm" id="more-actions" hidden></button>
30
30
 
31
31
  <div id="handled"></div>
32
32
  </section>
33
33
  <aside class="bf-col">
34
- ${qe(Y.pulse,"In motion","run-count")}
34
+ ${Je(ee.pulse,"In motion","run-count")}
35
35
  <div id="running" class="bf-col"></div>
36
36
  </aside>
37
37
  </div>
38
38
 
39
- ${qe(Y.file,"Session briefings","brief-count")}
39
+ ${Je(ee.file,"Session briefings","brief-count")}
40
40
  <div class="bf-toolbar">
41
- <div class="bf-search">${he(Y.search)}
41
+ <div class="bf-search">${xe(ee.search)}
42
42
  <input id="search" type="search" placeholder="Search sessions&hellip;" aria-label="Search sessions">
43
43
  </div>
44
44
  <div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
@@ -46,15 +46,15 @@ ${qe(Y.file,"Session briefings","brief-count")}
46
46
  <div id="reviews" class="bf-col"></div>
47
47
 
48
48
  <section class="ax-panel bf-connect">
49
- <div class="bf-connect__head">${he(Y.plug,17)}<h2>Connect a CLI session</h2>
49
+ <div class="bf-connect__head">${xe(ee.plug,17)}<h2>Connect a CLI session</h2>
50
50
  <span class="bf-connect__note">Daemon-owned processes only</span></div>
51
51
  <div class="bf-discover">
52
52
  <div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
53
- <button class="ax-btn" id="discover">${he(Y.search)} Discover CLIs</button>
53
+ <button class="ax-btn" id="discover">${xe(ee.search)} Discover CLIs</button>
54
54
  </div>
55
55
  <div class="bf-cli" id="discovered"></div>
56
56
  <details class="bf-manual">
57
- <summary>${he(Y.chev,12)} Register manually</summary>
57
+ <summary>${xe(ee.chev,12)} Register manually</summary>
58
58
  <div class="bf-forms">
59
59
  <form id="register" class="bf-form">
60
60
  <div class="ax-sec-label"><h3>Register a session</h3></div>
@@ -85,7 +85,7 @@ ${qe(Y.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:yr,scripts:`<script>${ve({decayOf:it,rankByDecay:ya})}const ICON = ${JSON.stringify(Y)};${wr}</script>`})}var yr=`
88
+ </div>`,css:eo,scripts:`<script>${ue({decayOf:xt,rankByDecay:Ha})}const ICON = ${JSON.stringify(ee)};${to}</script>`})}var eo=`
89
89
  .bf{max-width:1240px;margin:0 auto;padding:22px 24px 48px}
90
90
  .bf-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
91
91
  .bf :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
@@ -361,7 +361,7 @@ button.bf-tag.is-on{background:color-mix(in oklch,var(--ax-accent) 14%,transpare
361
361
  .bf{padding:16px 14px 36px}
362
362
  .bf-head{flex-direction:column;gap:14px;align-items:stretch}
363
363
  .bf-sync{justify-content:space-between}
364
- }`,wr=String.raw`
364
+ }`,to=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 lt(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,d),p.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let p=1;p<r.length;p++){let m=r[p].from-r[p-1].to;m<d&&(d=m,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function dt(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 ka(t,e=[],a){let{bands:n,gaps:r}=lt(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(w=>l.startedAt>=w.from&&l.startedAt<=w.to);if(d===-1)continue;let p=n[d],m=p.to-p.from||1,h=(l.startedAt-p.from)/m*100,y=Math.min(Math.max((l.durationMs||0)/m*100,1.2),100-h),S=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};S.runs.push({...l,band:d,track:0,left:h,width:y,marks:o.get(l.id)??[]}),s.set(l.laneKey,S)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>dt(l.runs.filter(m=>m.band===p))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as kr}from"crypto";import{readFileSync as _r,statSync as Sr}from"fs";import{resolve as Er,dirname as Tr}from"path";import{fileURLToPath as Cr}from"url";var _a=new Map;function Fe(t){let e=_a.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Tr(Cr(import.meta.url)),r=Er(n,"web",t),o=Sr(r),s=o.size<8e6?kr("sha1").update(_r(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return _a.set(t,a),a}var te={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},Ue=(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>",Ar=[["agent","Agent",te.bot],["client","Client",te.user],["project","Project",te.folder],["channel","Channel",te.route],["node","Node",te.mesh]],Sa={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 Ea(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 vt(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,d),p.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<d&&(d=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function bt(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function za(t,e=[],a){let{bands:n,gaps:r}=vt(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(T=>l.startedAt>=T.from&&l.startedAt<=T.to);if(d===-1)continue;let p=n[d],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,y=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:d,track:0,left:f,width:y,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>bt(l.runs.filter(u=>u.band===p))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as ao}from"crypto";import{readFileSync as no,statSync as ro}from"fs";import{resolve as oo,dirname as so}from"path";import{fileURLToPath as io}from"url";var qa=new Map;function Ve(t){let e=qa.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=so(io(import.meta.url)),r=oo(n,"web",t),o=ro(r),s=o.size<8e6?ao("sha1").update(no(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return qa.set(t,a),a}var ae={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},Ye=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",lo=[["agent","Agent",ae.bot],["client","Client",ae.user],["project","Project",ae.folder],["channel","Channel",ae.route],["node","Node",ae.mesh]],Ua={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &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 Fa(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return $({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
780
780
 
781
781
  <div class="ac-head">
782
782
  <div>
783
783
  <div class="ac-kicker">Operations</div>
784
784
  <h1>What ran, where, and what it decided</h1>
785
- <p class="ac-sub" id="sub">${Sa[e]}</p>
785
+ <p class="ac-sub" id="sub">${Ua[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
789
- ${[["timeline","Timeline",te.timeline],["map","Map",te.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Ue(o,13)}${r}</button>`).join("")}
789
+ ${[["timeline","Timeline",ae.timeline],["map","Map",ae.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Ye(o,13)}${r}</button>`).join("")}
790
790
  </div>
791
791
  <div class="ac-seg" id="hours" role="radiogroup" aria-label="Window">
792
792
  ${[["6","6h"],["24","24h"],["72","3d"],["168","7d"]].map(([n,r],o)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${o===1}"${o===1?' class="is-on"':""}>${r}</button>`).join("")}
793
793
  </div>
794
- <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${Ue(te.refresh,13)} Refresh</button>
794
+ <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${Ye(ae.refresh,13)} Refresh</button>
795
795
  </div>
796
796
  </div>
797
797
 
@@ -799,14 +799,14 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${Ar.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ue(o,13)}${r}</button>`).join("")}
802
+ ${lo.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ye(o,13)}${r}</button>`).join("")}
803
803
  </div>
804
804
  <div class="ac-key">
805
805
  <span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
806
806
  <span class="ac-k"><i class="ac-d ac-d--warning"></i>warning</span>
807
807
  <span class="ac-k"><i class="ac-d ac-d--recommendation"></i>friction</span>
808
808
  <span class="ac-k"><i class="ac-d ac-d--later"></i>do later</span>
809
- <span class="ac-k">${Ue(te.x,11)}canceled</span>
809
+ <span class="ac-k">${Ye(ae.x,11)}canceled</span>
810
810
  </div>
811
811
  </div>
812
812
 
@@ -816,10 +816,10 @@ refresh();
816
816
  </div>
817
817
 
818
818
  <div id="view-map" class="ac-map"${a?"":" hidden"}>
819
- <div id="ax-fleet-root" data-hours="24" data-src="${Fe("activity-graph.global.js")}"></div>
819
+ <div id="ax-fleet-root" data-hours="24" data-src="${Ve("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:Mr,scripts:`<script>${ve({computeBands:lt,packTracks:dt,buildTimeline:ka})}const ICON = ${JSON.stringify(te)};const SUB = ${JSON.stringify(Sa)};${Ir}</script>`})}var Mr=`
822
+ </div>`,css:co,scripts:`<script>${ue({computeBands:vt,packTracks:bt,buildTimeline:za})}const ICON = ${JSON.stringify(ae)};const SUB = ${JSON.stringify(Ua)};${po}</script>`})}var co=`
823
823
  .ac{max-width:1440px;margin:0 auto;padding:22px 24px 48px}
824
824
  .ac :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
825
825
  .ac-head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:14px}
@@ -905,7 +905,7 @@ refresh();
905
905
  @media (max-width:640px){.ac{padding:16px 16px 32px}.ac-head{flex-direction:column;gap:10px}
906
906
  .ac-tools{flex-wrap:wrap;padding-top:0}.ac-map{height:calc(100vh - 250px);margin:0 -16px;
907
907
  border-left:none;border-right:none;border-radius:0}}
908
- `,Ir=String.raw`
908
+ `,po=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 Ta(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:$r,scripts:`<script src="${Fe("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var $r=`
1025
+ `;function Wa(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return $({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:uo,scripts:`<script src="${Ve("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var uo=`
1026
1026
  /* Preload the fonts the redesign's CSS references. Placed in the shell so
1027
1027
  * they start fetching while the React bundle is still parsing. */
1028
1028
  @import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
@@ -1043,10 +1043,10 @@ body { margin: 0; overflow: hidden; }
1043
1043
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
1044
1044
  text-align: center;
1045
1045
  }
1046
- `;import{createServer as cl}from"http";import{appendFileSync as pl,existsSync as mr,mkdirSync as ul}from"fs";import{readFile as ml}from"fs/promises";import{fileURLToPath as hl}from"url";import{dirname as fl,resolve as Me}from"path";br();var Ca='/*! 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 We,readFileSync as Ma,writeFileSync as Ia,rmSync as dd,mkdirSync as Dr,copyFileSync as Nr,readdirSync as Hr}from"fs";import{resolve as ye}from"path";at();var ae={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function Aa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=He({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.`})+Be([{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+Lr()+sa,css:Pr,scripts:`${e}<script>${ia}
1047
- ${la}
1048
- ${jr}
1049
- ${Or}</script>`})}var jr=`
1046
+ `;import{createServer as rd}from"http";import{appendFileSync as od,existsSync as Gr,mkdirSync as sd}from"fs";import{readFile as id}from"fs/promises";import{fileURLToPath as ld}from"url";import{dirname as dd,resolve as Pe}from"path";Zr();var Ga='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Qe,readFileSync as Ka,writeFileSync as Ja,rmSync as cc,mkdirSync as vo,copyFileSync as bo,readdirSync as yo}from"fs";import{resolve as ke}from"path";pt();var ne={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function Xa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Ge({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Xe([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">');return $({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+fo()+Sa,css:go,scripts:`${e}<script>${Ta}
1047
+ ${Ca}
1048
+ ${mo}
1049
+ ${xo}</script>`})}var mo=`
1050
1050
  (function(){
1051
1051
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1052
1052
  async function refresh() {
@@ -1107,8 +1107,8 @@ ${Or}</script>`})}var jr=`
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 Lr(){let t=Qt().business?`<button data-tab="business">Business</button>
1111
- `:"";return Rr.replace("__BUSINESS_TABS__",t)}var Rr=`
1110
+ })();`;function fo(){let t=ha().business?`<button data-tab="business">Business</button>
1111
+ `:"";return ho.replace("__BUSINESS_TABS__",t)}var ho=`
1112
1112
  <div id="peer-banner" class="peer-banner">
1113
1113
  <span class="label">Managing</span>
1114
1114
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -1251,8 +1251,8 @@ ${Or}</script>`})}var jr=`
1251
1251
  <div id="global-msg" class="msg"></div>
1252
1252
 
1253
1253
  <section id="tab-agents" class="tab active">
1254
- ${q({icon:ae.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1255
- ${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>).`})}
1254
+ ${U({icon:ne.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1255
+ ${Z({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
1256
1256
  <div id="agent-list" class="ax-stack"></div>
1257
1257
  <div class="add-form">
1258
1258
  <h3>Add a new agent</h3>
@@ -1274,8 +1274,8 @@ ${Or}</script>`})}var jr=`
1274
1274
  </section>
1275
1275
 
1276
1276
  <section id="tab-channels" class="tab">
1277
- ${q({icon:ae.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1278
- ${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."})}
1277
+ ${U({icon:ne.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1278
+ ${Z({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
1279
1279
 
1280
1280
  <details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
1281
1281
  <summary class="primary">\u2699 Notifications routing</summary>
@@ -1360,10 +1360,10 @@ ${Or}</script>`})}var jr=`
1360
1360
  </div>
1361
1361
  </details>
1362
1362
 
1363
- <div id="ch-chatapps-label">${ze({label:"Chat apps"})}</div>
1363
+ <div id="ch-chatapps-label">${Ke({label:"Chat apps"})}</div>
1364
1364
  <div class="ax-connectors" id="ch-chatapps"></div>
1365
1365
 
1366
- <div id="ch-devtools-label">${ze({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
1366
+ <div id="ch-devtools-label">${Ke({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
1367
1367
  <div class="ax-connectors" id="ch-devtools"></div>
1368
1368
 
1369
1369
  <!-- Active-channel configuration panes. One shows at a time; clicking
@@ -1381,8 +1381,8 @@ ${Or}</script>`})}var jr=`
1381
1381
  </section>
1382
1382
 
1383
1383
  <section id="tab-crons" class="tab">
1384
- ${q({icon:ae.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
1385
- ${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."})}
1384
+ ${U({icon:ne.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
1385
+ ${Z({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
1386
1386
  <div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
1387
1387
 
1388
1388
  <div class="ax-builder">
@@ -1479,8 +1479,8 @@ ${Or}</script>`})}var jr=`
1479
1479
  </section>
1480
1480
 
1481
1481
  <section id="tab-webhooks" class="tab">
1482
- ${q({icon:ae.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
1483
- ${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.`})}
1482
+ ${U({icon:ne.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
1483
+ ${Z({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
1484
1484
  <div id="webhook-list" class="ax-stack"></div>
1485
1485
  <div class="add-form">
1486
1486
  <h3>Add a webhook</h3>
@@ -1499,10 +1499,10 @@ ${Or}</script>`})}var jr=`
1499
1499
  </section>
1500
1500
 
1501
1501
  <section id="tab-mesh" class="tab">
1502
- ${q({icon:ae.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
1502
+ ${U({icon:ne.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
1503
1503
  <div id="mesh-hero" class="ax-mesh-hero"></div>
1504
- ${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."})}
1505
- ${ze({label:"Connected peers"})}
1504
+ ${Z({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
1505
+ ${Ke({label:"Connected peers"})}
1506
1506
  <div id="mesh-peers" class="ax-stack"></div>
1507
1507
  <div class="add-form">
1508
1508
  <h3>Add a peer</h3>
@@ -1529,8 +1529,8 @@ ${Or}</script>`})}var jr=`
1529
1529
  </section>
1530
1530
 
1531
1531
  <section id="tab-business" class="tab">
1532
- ${q({icon:ae.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
1533
- ${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.'})}
1532
+ ${U({icon:ne.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
1533
+ ${Z({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
1534
1534
 
1535
1535
  <div class="ax-stack" style="margin-top:14px">
1536
1536
  <h3 style="margin:0 0 6px;font-size:13px">Org chart</h3>
@@ -1617,8 +1617,8 @@ ${Or}</script>`})}var jr=`
1617
1617
  </section>
1618
1618
 
1619
1619
  <section id="tab-boards-cfg" class="tab">
1620
- ${q({icon:ae.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
1621
- ${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.'})}
1620
+ ${U({icon:ne.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
1621
+ ${Z({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
1622
1622
 
1623
1623
  <div class="ax-stack" style="margin-top:14px">
1624
1624
  <h3 style="margin:0 0 6px;font-size:13px">Boards</h3>
@@ -1642,8 +1642,8 @@ ${Or}</script>`})}var jr=`
1642
1642
  </section>
1643
1643
 
1644
1644
  <section id="tab-actions" class="tab">
1645
- ${q({icon:ae.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
1646
- ${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."})}
1645
+ ${U({icon:ne.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
1646
+ ${Z({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
1647
1647
 
1648
1648
  <div class="ax-stack" style="margin-top:14px">
1649
1649
  <h3 style="margin:0 0 6px;font-size:13px">Registered actions</h3>
@@ -1698,8 +1698,8 @@ ${Or}</script>`})}var jr=`
1698
1698
  </section>
1699
1699
 
1700
1700
  <section id="tab-tokens" class="tab">
1701
- ${q({icon:ae.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
1702
- ${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."})}
1701
+ ${U({icon:ne.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
1702
+ ${Z({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
1703
1703
  <div id="token-list" class="ax-stack"></div>
1704
1704
  <div class="add-form">
1705
1705
  <h3>Mint a new token</h3>
@@ -1718,8 +1718,8 @@ ${Or}</script>`})}var jr=`
1718
1718
  </section>
1719
1719
 
1720
1720
  <section id="tab-advanced" class="tab">
1721
- ${q({icon:ae.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
1722
- ${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.`})}
1721
+ ${U({icon:ne.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
1722
+ ${Z({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
1723
1723
 
1724
1724
  <div class="ax-jv-toolbar">
1725
1725
  <input class="ax-jv-search" id="jv-search" placeholder="Search keys & values\u2026" />
@@ -1745,7 +1745,7 @@ ${Or}</script>`})}var jr=`
1745
1745
  <div class="hint-block">Every setting is documented in the <code>docs/reference/config.md</code> reference. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
1746
1746
  </section>
1747
1747
  </main>
1748
- `,Pr=`
1748
+ `,go=`
1749
1749
 
1750
1750
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
1751
1751
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -1953,7 +1953,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
1953
1953
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
1954
1954
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
1955
1955
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
1956
- `,Or=`
1956
+ `,xo=`
1957
1957
  const $ = (id) => document.getElementById(id);
1958
1958
  let state = null;
1959
1959
 
@@ -4760,11 +4760,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
4760
4760
  })();
4761
4761
 
4762
4762
  refresh();
4763
- `;function $a(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Aa({peers:a,localToken:n}))}async function ja(t,e){let a=ut();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function La(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Zr(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Br(t),r={"GET /api/admin/state":()=>qr(),"POST /api/admin/agents":()=>Kr(n),"PATCH /api/admin/agents":()=>Jr(n),"DELETE /api/admin/agents":()=>Vr(n),"POST /api/admin/agents/access":()=>Fr(n),"POST /api/admin/channels/telegram":()=>Yr(n),"DELETE /api/admin/channels/telegram":()=>ko(n),"POST /api/admin/channels/telegram/toggle":()=>_o(n),"POST /api/admin/crons":()=>So(n),"DELETE /api/admin/crons":()=>Eo(n),"POST /api/admin/config/raw":()=>To(n),"GET /api/admin/tokens":()=>Ur(),"POST /api/admin/tokens":()=>Wr(n),"DELETE /api/admin/tokens":()=>Gr(n),"POST /api/admin/agents/test":()=>Xr(n),"POST /api/admin/agents/integrations":()=>oo(n),"DELETE /api/admin/agents/integrations":()=>so(n),"PATCH /api/admin/agents/integrations":()=>io(n),"PATCH /api/admin/channels/telegram":()=>Qr(n),"POST /api/admin/channels/slack":()=>fo(n),"POST /api/admin/channels/slack/toggle":()=>go(n),"POST /api/admin/channels/discord":()=>xo(n),"POST /api/admin/channels/discord/toggle":()=>vo(n),"POST /api/admin/channels/gitlab":()=>bo(n),"POST /api/admin/channels/gitlab/toggle":()=>yo(n),"GET /api/admin/channels/whatsapp/state":()=>Se("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Se("/webrtc/history"),"POST /api/admin/actions":()=>Ho(n),"DELETE /api/admin/actions":()=>Bo(n),"POST /api/admin/actions/run":()=>zo(n),"GET /api/admin/channels/whatsapp/chats":()=>Se("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Se("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>re("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>wo(n),"POST /api/admin/webhooks":()=>lo(n),"PATCH /api/admin/webhooks":()=>co(n),"DELETE /api/admin/webhooks":()=>ho(n),"POST /api/admin/mesh/peers":()=>po(n),"DELETE /api/admin/mesh/peers":()=>uo(n),"POST /api/admin/mesh/toggle":()=>mo(n),"GET /api/admin/files":()=>eo(t),"GET /api/admin/files/read":()=>to(t),"PUT /api/admin/files":()=>ao(n),"POST /api/admin/files/skill":()=>no(n),"DELETE /api/admin/files/skill":()=>ro(n),"POST /api/admin/business/orgchart":()=>Co(n),"DELETE /api/admin/business/orgchart":()=>Ao(n),"POST /api/admin/business/project":()=>Mo(n),"DELETE /api/admin/business/project":()=>jo(n),"POST /api/admin/business/client":()=>Io(n),"DELETE /api/admin/business/client":()=>$o(n),"POST /api/admin/business/contact":()=>Lo(n),"DELETE /api/admin/business/contact":()=>Ro(n),"POST /api/admin/boards":()=>Po(n),"DELETE /api/admin/boards":()=>Oo(n),"POST /api/admin/boards/columns":()=>Do(n),"DELETE /api/admin/boards/columns":()=>No(n),"POST /api/admin/notifications":()=>Fo(n),"POST /api/admin/screen":()=>Uo(n),"POST /api/admin/webhooks/triggers":()=>Wo(n),"POST /api/admin/mesh/health":()=>qo(n),"GET /api/admin/projects":()=>Se("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>re("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>re("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>re("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>re("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>re("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>re("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>re("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>re("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ct(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ct(e,200,i)}catch(n){ct(e,400,{error:n.message||"admin op failed"})}}function ct(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Br(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 zr(t){let e=ye(process.cwd(),t);if(!We(e))return[];let a=[];for(let n of Hr(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ma(ye(e,n.name),"utf-8")))}catch{}return a}function ut(){let t=ye(process.cwd(),"agentx.json");return We(t)?JSON.parse(Ma(t,"utf-8")):null}function qr(){let t=ut();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([c,u])=>({id:c,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(f=>{let g=f.credentials||{},b={};for(let[x,k]of Object.entries(g))typeof k=="string"&&/^[A-Z][A-Z0-9_]*$/.test(k)?b[x]=process.env[k]?"set":"unset":typeof k=="string"&&(b[x]="literal");return{kind:f.kind,label:f.label,enabled:f.enabled!==!1,credentials:g,credStatus:b,metadata:f.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([c,u])=>({id:c,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([c,u])=>({id:c,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(c=>({id:c.id,source:c.source,agentId:c.agentId,secretEnv:c.secretEnv||"",description:c.description||"",enabled:c.enabled!==!1,triggers:c.triggers&&typeof c.triggers=="object"?c.triggers:{},defaultWorkflow:c.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(c=>({url:c.url,name:c.name,hasToken:!!c.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},m=t.dashboard?.daemonUrl||"http://localhost:18800",h=t.business||{},y={enabled:!!h.enabled,timezone:h.timezone||"UTC",orgChart:h.orgChart||{},projects:Array.isArray(h.projects)?h.projects:[],contactMap:Array.isArray(h.contactMap)?h.contactMap:[],clients:h.clients&&typeof h.clients=="object"?h.clients:{}},S=t.notifications||{},w={longTaskThreshold:S.longTaskThreshold??30,destination:S.destination||null,on:{taskComplete:S.on?.taskComplete!==!1,taskError:S.on?.taskError!==!1,taskQueued:!!S.on?.taskQueued},local:Xt(S.local),ntfy:xa(t.channels?.ntfy)},E=[];try{E=zr(".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,f)=>u.id.localeCompare(f.id))}catch{}let T=(Array.isArray(t.boards)?t.boards:[]).map(c=>({id:c.id,name:c.name,source:c.source||{type:"gitlab",projects:[]},primaryToolLabel:c.primaryToolLabel||"",timeRangeDays:c.timeRangeDays??30,closedWindowDays:c.closedWindowDays??30,columns:Array.isArray(c.columns)?c.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,crons:l,webhooks:d,mesh:p,daemonUrl:m,nodeName:t.node?.name,business:y,boards:T,notifications:w,screen:na(t.screen),actions:E}}function Fr(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 Ur(){return new V().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function Wr(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new V().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Gr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new V().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Xr(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=K();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function Kr(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=Pa(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ye(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let m={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(m.model=o),s&&(m.systemPrompt=s.slice(0,400)),p.agents[e]=m,`added agent "${e}"`}),d=ye(i,"CLAUDE.md");if(!We(d))try{Dr(i,{recursive:!0}),Ia(d,`# ${a}
4763
+ `;function Va(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({peers:a,localToken:n}))}async function Ya(t,e){let a=kt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Qa(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ro(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await wo(t),r={"GET /api/admin/state":()=>_o(),"POST /api/admin/agents":()=>Mo(n),"PATCH /api/admin/agents":()=>Io(n),"DELETE /api/admin/agents":()=>$o(n),"POST /api/admin/agents/access":()=>Eo(n),"POST /api/admin/channels/telegram":()=>Lo(n),"DELETE /api/admin/channels/telegram":()=>as(n),"POST /api/admin/channels/telegram/toggle":()=>ns(n),"POST /api/admin/crons":()=>rs(n),"DELETE /api/admin/crons":()=>os(n),"POST /api/admin/config/raw":()=>ss(n),"GET /api/admin/tokens":()=>So(),"POST /api/admin/tokens":()=>To(n),"DELETE /api/admin/tokens":()=>Co(n),"POST /api/admin/agents/test":()=>Ao(n),"POST /api/admin/agents/integrations":()=>Bo(n),"DELETE /api/admin/agents/integrations":()=>zo(n),"PATCH /api/admin/agents/integrations":()=>qo(n),"PATCH /api/admin/channels/telegram":()=>jo(n),"POST /api/admin/channels/slack":()=>Jo(n),"POST /api/admin/channels/slack/toggle":()=>Vo(n),"POST /api/admin/channels/discord":()=>Yo(n),"POST /api/admin/channels/discord/toggle":()=>Qo(n),"POST /api/admin/channels/gitlab":()=>Zo(n),"POST /api/admin/channels/gitlab/toggle":()=>es(n),"GET /api/admin/channels/whatsapp/state":()=>Me("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Me("/webrtc/history"),"POST /api/admin/actions":()=>bs(n),"DELETE /api/admin/actions":()=>ys(n),"POST /api/admin/actions/run":()=>ws(n),"GET /api/admin/channels/whatsapp/chats":()=>Me("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Me("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ie("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ts(n),"POST /api/admin/webhooks":()=>Uo(n),"PATCH /api/admin/webhooks":()=>Fo(n),"DELETE /api/admin/webhooks":()=>Ko(n),"POST /api/admin/mesh/peers":()=>Wo(n),"DELETE /api/admin/mesh/peers":()=>Go(n),"POST /api/admin/mesh/toggle":()=>Xo(n),"GET /api/admin/files":()=>Po(t),"GET /api/admin/files/read":()=>No(t),"PUT /api/admin/files":()=>Oo(n),"POST /api/admin/files/skill":()=>Do(n),"DELETE /api/admin/files/skill":()=>Ho(n),"POST /api/admin/business/orgchart":()=>is(n),"DELETE /api/admin/business/orgchart":()=>ls(n),"POST /api/admin/business/project":()=>ds(n),"DELETE /api/admin/business/project":()=>us(n),"POST /api/admin/business/client":()=>cs(n),"DELETE /api/admin/business/client":()=>ps(n),"POST /api/admin/business/contact":()=>ms(n),"DELETE /api/admin/business/contact":()=>fs(n),"POST /api/admin/boards":()=>hs(n),"DELETE /api/admin/boards":()=>gs(n),"POST /api/admin/boards/columns":()=>xs(n),"DELETE /api/admin/boards/columns":()=>vs(n),"POST /api/admin/notifications":()=>_s(n),"POST /api/admin/screen":()=>Es(n),"POST /api/admin/webhooks/triggers":()=>Ss(n),"POST /api/admin/mesh/health":()=>ks(n),"GET /api/admin/projects":()=>Me("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ie("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ie("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ie("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ie("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ie("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ie("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ie("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ie("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){yt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();yt(e,200,i)}catch(n){yt(e,400,{error:n.message||"admin op failed"})}}function yt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function wo(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function ko(t){let e=ke(process.cwd(),t);if(!Qe(e))return[];let a=[];for(let n of yo(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ka(ke(e,n.name),"utf-8")))}catch{}return a}function kt(){let t=ke(process.cwd(),"agentx.json");return Qe(t)?JSON.parse(Ka(t,"utf-8")):null}function _o(){let t=kt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([c,m])=>({id:c,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(h=>{let x=h.credentials||{},k={};for(let[v,_]of Object.entries(x))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?k[v]=process.env[_]?"set":"unset":typeof _=="string"&&(k[v]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:x,credStatus:k,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([c,m])=>({id:c,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([c,m])=>({id:c,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(c=>({id:c.id,source:c.source,agentId:c.agentId,secretEnv:c.secretEnv||"",description:c.description||"",enabled:c.enabled!==!1,triggers:c.triggers&&typeof c.triggers=="object"?c.triggers:{},defaultWorkflow:c.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(c=>({url:c.url,name:c.name,hasToken:!!c.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},y={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},w=t.notifications||{},T={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:la(w.local),ntfy:Na(t.channels?.ntfy)},g=[];try{g=ko(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,h)=>m.id.localeCompare(h.id))}catch{}let S=(Array.isArray(t.boards)?t.boards:[]).map(c=>({id:c.id,name:c.name,source:c.source||{type:"gitlab",projects:[]},primaryToolLabel:c.primaryToolLabel||"",timeRangeDays:c.timeRangeDays??30,closedWindowDays:c.closedWindowDays??30,columns:Array.isArray(c.columns)?c.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,crons:l,webhooks:d,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:y,boards:S,notifications:T,screen:ya(t.screen),actions:g}}function Eo(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function So(){return new Q().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function To(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new Q().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Co(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Q().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ao(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=Y();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function Mo(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(t?.tier)?t.tier:"claude-code",r=en(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ke(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),d=ke(i,"CLAUDE.md");if(!Qe(d))try{vo(i,{recursive:!0}),Ja(d,`# ${a}
4764
4764
 
4765
4765
  ${s||"You are "+a+"."}
4766
- `)}catch{}return{summary:l}}function Jr(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=Pa(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 Vr(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 Yr(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 Qr(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 Se(t){let{url:e,headers:a}=mt(),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 re(t,e){let{url:a,headers:n}=mt(),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 Zr(t,e){try{let{url:a,headers:n}=mt(),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 mt(){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 Ee(t){let a=ut()?.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 pt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function eo(t){let e=pt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=xe(Ee(e));return{agentId:e,...a}}function to(t){let e=pt(t,"agent").trim(),a=pt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Re(Ee(e),a)}function ao(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=Pe(Ee(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function no(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=Oe(Ee(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function ro(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=De(Ee(e),a);return{summary:`removed skill "${a}"`,...n}}function oo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function so(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function io(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Ra=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function lo(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(!Ra.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(m=>m.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function co(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"&&Ra.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 po(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=C(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function uo(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 mo(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 ho(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 fo(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 go(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 xo(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 vo(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 bo(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 yo(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 wo(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-7CEXDECA.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(i){throw new Error(`Invalid cron: ${i.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let i=0;i<3;i++)s=a(e,s,r),o.push(s.toISOString())}catch(i){throw new Error(`Cron preview failed: ${i.message}`)}return{human:n,next:o,timezone:r}}function ko(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 _o(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 So(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 Eo(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 To(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=ye(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(We(n))try{Nr(n,r)}catch{}Ia(n,JSON.stringify(a,null,2)+`
4767
- `,"utf-8");try{let s=K().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function Pa(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Co(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function Ao(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 Mo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=C(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function Io(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=C(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function $o(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function jo(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 Lo(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 Ro(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=C(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function Po(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(m=>m.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let m=l.boards[d];return l.boards[d]={...m,...p,columns:m.columns,labels:m.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Oo(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 Do(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(m=>m.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let p=l.columns.findIndex(m=>m.id===a);return p>=0?(l.columns[p]={...l.columns[p],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function No(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=C(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Ho(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function Bo(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function zo(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function qo(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 Fo(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=Kt(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=va(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 Uo(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=ra(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Wo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}at();import{resolve as Ko}from"path";function Oa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4766
+ `)}catch{}return{summary:l}}function Io(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=en(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function $o(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function Lo(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=C(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function jo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Me(t){let{url:e,headers:a}=_t(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ie(t,e){let{url:a,headers:n}=_t(),r=await fetch(a+t,{method:"POST",headers:{...n,"Content-Type":"application/json"},body:JSON.stringify(e||{})}),o=await r.text();if(!r.ok)throw new Error(`daemon ${r.status}: ${o.slice(0,200)}`);try{return JSON.parse(o)}catch{return{raw:o}}}async function Ro(t,e){try{let{url:a,headers:n}=_t(),r=await fetch(a+e,{headers:n}),o=await r.text();t.writeHead(r.status,{"Content-Type":r.headers.get("content-type")||"image/svg+xml","Cache-Control":"no-store"}),t.end(o)}catch(a){t.writeHead(502,{"Content-Type":"text/plain; charset=utf-8"}),t.end("daemon unreachable: "+(a?.message||"unknown"))}}function _t(){let t="http://127.0.0.1:18800",e={};try{let a=Y();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ie(t){let a=kt()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function wt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Po(t){let e=wt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ye(Ie(e));return{agentId:e,...a}}function No(t){let e=wt(t,"agent").trim(),a=wt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return ze(Ie(e),a)}function Oo(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=qe(Ie(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Do(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=Ue(Ie(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Ho(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Fe(Ie(e),a);return{summary:`removed skill "${a}"`,...n}}function Bo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function zo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function qo(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Za=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Uo(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!Za.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Fo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Za.includes(a.source)&&(o.source=a.source),typeof a.agentId=="string"&&a.agentId.trim()){if(!r.agents?.[a.agentId])throw new Error(`Unknown agent "${a.agentId}".`);o.agentId=a.agentId.trim()}return typeof a.secretEnv=="string"&&(o.secretEnv=a.secretEnv.trim()||void 0),typeof a.description=="string"&&(o.description=a.description.trim()||void 0),typeof a.enabled=="boolean"&&(o.enabled=a.enabled),`updated webhook "${e}"`});return{summary:n}}function Wo(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=C(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function Go(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function Xo(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function Ko(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function Jo(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=C(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function Vo(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function Yo(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=C(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Qo(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Zo(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=C(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function es(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function ts(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-RHJW2V4M.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(i){throw new Error(`Invalid cron: ${i.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let i=0;i<3;i++)s=a(e,s,r),o.push(s.toISOString())}catch(i){throw new Error(`Cron preview failed: ${i.message}`)}return{human:n,next:o,timezone:r}}function as(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function ns(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function rs(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=C(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function os(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=C(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function ss(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ke(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Qe(n))try{bo(n,r)}catch{}Ja(n,JSON.stringify(a,null,2)+`
4767
+ `,"utf-8");try{let s=Y().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function en(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function is(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function ls(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=C(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function ds(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=C(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function cs(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=C(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function ps(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function us(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=C(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function ms(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=C(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function fs(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=C(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function hs(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let u=l.boards[d];return l.boards[d]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function gs(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=C(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function xs(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function vs(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=C(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function bs(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function ys(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function ws(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function ks(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=C(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function _s(t){let{summary:e}=C(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=da(a.notifications.local,t.local),n.push("local="+JSON.stringify(a.notifications.local))),"ntfy"in t&&t.ntfy&&typeof t.ntfy=="object"&&(a.channels=a.channels||{},a.channels.ntfy=Oa(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function Es(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=wa(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ss(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}pt();import{resolve as As}from"path";function tn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4768
4768
 
4769
4769
  <div id="disabled-banner" class="banner warn" style="display:none">
4770
4770
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -4819,7 +4819,7 @@ ${s||"You are "+a+"."}
4819
4819
  <h2>Recent classifications</h2>
4820
4820
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
4821
4821
  <div id="recent"></div>
4822
- </section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Go,scripts:`${e}<script>${Xo}</script>`})}var Go=`
4822
+ </section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ts,scripts:`${e}<script>${Cs}</script>`})}var Ts=`
4823
4823
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
4824
4824
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
4825
4825
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -4923,7 +4923,7 @@ details {
4923
4923
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
4924
4924
  }
4925
4925
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
4926
- details[open] summary { margin-bottom: 8px; }`,Xo=`
4926
+ details[open] summary { margin-bottom: 8px; }`,Cs=`
4927
4927
  const $ = (id) => document.getElementById(id);
4928
4928
  const state = { schema: null, nodes: [], pending: [], recent: [] };
4929
4929
 
@@ -5143,7 +5143,7 @@ $('btn-save-schema').addEventListener('click', async () => {
5143
5143
  $('btn-reload-schema').addEventListener('click', refresh);
5144
5144
 
5145
5145
  refresh();
5146
- `;function Na(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oa({peers:a,localToken:n}))}async function Ha(t,e,a){try{let n=t.method==="GET"?void 0:await ns(t),r=Jo(),o={"GET /api/admin/graph/state":()=>Vo(r),"POST /api/admin/graph/classifications/approve":()=>Yo(r,n),"POST /api/admin/graph/classifications/reject":()=>Qo(r,n),"POST /api/admin/graph/nodes":()=>Zo(r,n),"PATCH /api/admin/graph/nodes":()=>es(r,n),"DELETE /api/admin/graph/nodes":()=>ts(r,n),"PUT /api/admin/graph/schema":()=>as(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){ht(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();ht(e,200,l)}catch(n){ht(e,400,{error:n?.message||"graph op failed"})}}function Jo(){let t=K(),e=Ko(process.cwd(),t.graph.baseDir);return new Dt({baseDir:e})}function Vo(t){let e=K(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function Yo(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ba(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=ft(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Qo(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ba(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Ba(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 Zo(t,e){let a=Da(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Da(String(e.parentId)):null,o=ft({[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 es(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=ft({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function ts(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function as(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 ft(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 Da(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function ht(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ns(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 za(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5146
+ `;function nn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(tn({peers:a,localToken:n}))}async function rn(t,e,a){try{let n=t.method==="GET"?void 0:await Os(t),r=Ms(),o={"GET /api/admin/graph/state":()=>Is(r),"POST /api/admin/graph/classifications/approve":()=>$s(r,n),"POST /api/admin/graph/classifications/reject":()=>Ls(r,n),"POST /api/admin/graph/nodes":()=>js(r,n),"PATCH /api/admin/graph/nodes":()=>Rs(r,n),"DELETE /api/admin/graph/nodes":()=>Ps(r,n),"PUT /api/admin/graph/schema":()=>Ns(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Et(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Et(e,200,l)}catch(n){Et(e,400,{error:n?.message||"graph op failed"})}}function Ms(){let t=Y(),e=As(process.cwd(),t.graph.baseDir);return new Yt({baseDir:e})}function Is(t){let e=Y(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function $s(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=on(t,a);return Array.isArray(e?.path)&&e.path.length>0&&(n.path=e.path.map(r=>String(r))),e?.proposedAxes&&typeof e.proposedAxes=="object"&&(n.proposedAxes=St(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Ls(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=on(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function on(t,e){let n=t.readRecentClassifications(500).find(r=>r.msgHash===e);if(!n)throw new Error(`No classification found for ${e}`);return n}function js(t,e){let a=an(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?an(String(e.parentId)):null,o=St({[a]:e?.axes||{}})[a]||{};if(!a)throw new Error("id is required");if(!n)throw new Error("level is required");let s={id:a,level:n,parentId:r,axes:o,createdAt:new Date().toISOString(),createdBy:"admin-ui"};return t.addNode(s),{node:s}}function Rs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=St({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ps(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Ns(t,e){if(!e?.schema||typeof e.schema!="object")throw new Error("schema object is required");return t.saveSchema(e.schema),{summary:"Schema saved"}}function St(t){let e={};for(let[a,n]of Object.entries(t||{})){if(!n||typeof n!="object")continue;let r={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(r[o]=s);e[a]=r}return e}function an(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Et(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Os(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function sn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5147
5147
  <header class="apv__head">
5148
5148
  <div>
5149
5149
  <h1>Approvals</h1>
@@ -5176,7 +5176,7 @@ refresh();
5176
5176
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5177
5177
  </form>
5178
5178
  </details>
5179
- </div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:rs,scripts:`${e}<script>${os}</script>`})}var rs=`
5179
+ </div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ds,scripts:`${e}<script>${Hs}</script>`})}var Ds=`
5180
5180
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
5181
5181
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
5182
5182
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -5225,7 +5225,7 @@ refresh();
5225
5225
  @media (max-width: 560px) {
5226
5226
  .apv__acts .ax-btn { flex: 1 1 0; }
5227
5227
  }
5228
- `,os=`
5228
+ `,Hs=`
5229
5229
  (function(){
5230
5230
  var state = { items: [], snoozed: 0, kind: '', showAll: false };
5231
5231
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson' };
@@ -5376,7 +5376,7 @@ $('apv-form').addEventListener('submit', async function(ev){
5376
5376
  load();
5377
5377
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
5378
5378
  })();
5379
- `;var ss=["yes","no","later"];function oe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function qa(t,e=64*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8");if(!r.trim())return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function Fa(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(za({peers:e,localToken:a}))}async function Ua(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return oe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=je(s,{includeSnoozed:n.searchParams.get("all")==="1"});return oe(e,200,{...i,settings:be(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await qa(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!ss.includes(d))return oe(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=be(s.configPath),m=await Le(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return m.ok?(oe(e,200,{ok:!0,message:m.message}),!0):(oe(e,409,{error:m.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await qa(t),l={},d=m=>{let h=i[m];if(h!==void 0){if(typeof h!="number"||!(h>0))throw new Error(`${m} must be a positive number`);return h}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let m=i.destination.trim();if(!m)l.destination=null;else{let h=ha(m);if(!h)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=h}}let p=await fa(l,{configPath:s.configPath,reload:s.reload});return p.success?(oe(e,200,{ok:!0,settings:be(s.configPath)}),!0):(oe(e,400,{error:p.error}),!0)}}catch(i){return oe(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return oe(e,404,{error:"Not found"}),!0}import{resolve as ds}from"path";import{existsSync as cs}from"fs";import ps from"better-sqlite3";function Wa(t={}){let e=`<div class="ax-obs">
5379
+ `;var Bs=["yes","no","later"];function le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function ln(t,e=64*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8");if(!r.trim())return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function dn(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(sn({peers:e,localToken:a}))}async function cn(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return le(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=He(s,{includeSnoozed:n.searchParams.get("all")==="1"});return le(e,200,{...i,settings:we(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await ln(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!Bs.includes(d))return le(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=we(s.configPath),u=await Be(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(le(e,200,{ok:!0,message:u.message}),!0):(le(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await ln(t),l={},d=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let f=ja(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Ra(l,{configPath:s.configPath,reload:s.reload});return p.success?(le(e,200,{ok:!0,settings:we(s.configPath)}),!0):(le(e,400,{error:p.error}),!0)}}catch(i){return le(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return le(e,404,{error:"Not found"}),!0}import{resolve as Us}from"path";import{existsSync as Fs}from"fs";import Ws from"better-sqlite3";function pn(t={}){let e=`<div class="ax-obs">
5380
5380
  <header class="ax-obs__head">
5381
5381
  <h1>Health</h1>
5382
5382
  <p class="ax-obs__sub">Platform-health view: what each agent ran, what failed, and how the router decided. <span class="ax-obs__sub-link">Spend lives on the <a href="/admin/cost">Cost</a> page.</span></p>
@@ -5498,7 +5498,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5498
5498
  </div>
5499
5499
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
5500
5500
  </section>
5501
- </div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:is,scripts:`<script>${ls}</script>`})}var is=`
5501
+ </div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:zs,scripts:`<script>${qs}</script>`})}var zs=`
5502
5502
  .ax-obs { padding: 16px 24px; }
5503
5503
  .ax-obs__head { margin-bottom: 16px; }
5504
5504
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -5615,7 +5615,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5615
5615
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
5616
5616
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
5617
5617
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
5618
- `,ls=`
5618
+ `,qs=`
5619
5619
  (function(){
5620
5620
  var panes = document.querySelectorAll('.ax-obs__pane');
5621
5621
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -5999,23 +5999,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5999
5999
 
6000
6000
  load(current);
6001
6001
  })();
6002
- `;var Ka={opus:{input:15,output:75,cacheRead:1.5,cacheCreate:18.75},sonnet:{input:3,output:15,cacheRead:.3,cacheCreate:3.75},haiku:{input:.25,output:1.25,cacheRead:.025,cacheCreate:.3125},external:{input:0,output:0,cacheRead:0,cacheCreate:0}};function Ja(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function gt(t){let e=Ka[Ja(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 us(){let t=ds(process.cwd(),".agentx/db.sqlite");if(!cs(t))return null;try{let e=new ps(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Va(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wa({peers:a}))}function ms(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 se(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=us();if(!r)return se(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ms(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6002
+ `;var fn={opus:{input:15,output:75,cacheRead:1.5,cacheCreate:18.75},sonnet:{input:3,output:15,cacheRead:.3,cacheCreate:3.75},haiku:{input:.25,output:1.25,cacheRead:.025,cacheCreate:.3125},external:{input:0,output:0,cacheRead:0,cacheCreate:0}};function hn(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Tt(t){let e=fn[hn(t.model)],a=t.input_tokens/1e6*e.input+t.output_tokens/1e6*e.output+t.cache_read_tokens/1e6*e.cacheRead+t.cache_create_tokens/1e6*e.cacheCreate,n=(t.tier2_input_tokens??0)/1e6*e.input*.5+(t.tier2_output_tokens??0)/1e6*e.output*.5+(t.tier2_cache_read_tokens??0)/1e6*e.cacheRead*.5+(t.tier2_cache_create_tokens??0)/1e6*e.cacheCreate*.5;return a+n}function Gs(){let t=Us(process.cwd(),".agentx/db.sqlite");if(!Fs(t))return null;try{let e=new Ws(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function gn(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:a}))}function Xs(t){let e=new URL(t.url||"/","http://_"),a=parseInt(e.searchParams.get("limit")||"50",10),n=Number.isFinite(a)?Math.max(1,Math.min(500,a)):50,r=e.searchParams.get("agent")||void 0;return{limit:n,agent:r&&r.length>0?r:void 0}}function de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function xn(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Gs();if(!r)return de(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Xs(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6003
6003
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
6004
6004
  FROM route_traces
6005
6005
  ${i.length?"WHERE "+i.join(" AND "):""}
6006
6006
  ORDER BY at DESC LIMIT @limit
6007
- `,p=r.db.prepare(d).all(l);return se(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6007
+ `,p=r.db.prepare(d).all(l);return de(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6008
6008
  SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
6009
6009
  FROM rotations
6010
6010
  ${i.length?"WHERE "+i.join(" AND "):""}
6011
6011
  ORDER BY rotated_at DESC LIMIT @limit
6012
- `,p=r.db.prepare(d).all(l);return se(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6012
+ `,p=r.db.prepare(d).all(l);return de(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6013
6013
  SELECT started_at, agent_id, channel, message_preview, error
6014
6014
  FROM task_history
6015
6015
  WHERE ${i.join(" AND ")}
6016
6016
  ORDER BY started_at DESC LIMIT @limit
6017
- `,m=r.db.prepare(d).all(l).map(h=>({...h,plain:Qa(h.error)}));return se(e,200,{rows:m}),!0}if(n==="summary"||n==="overview")return se(e,200,hs(r.db)),!0;if(n==="activity")return se(e,200,fs(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Ga(i.searchParams.get("range"));return se(e,200,Xa(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Ga(i.searchParams.get("range")),d=Xa(r.db,l),p=gs(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return se(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return se(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Qa(t){let e=String(t||"");return e?/timed out|SIGTERM|exit 143|maxExecutionMinutes/i.test(e)?"Agent ran past its time limit":/ECONNREFUSED|fetch failed|getaddrinfo|ENOTFOUND/i.test(e)?"Couldn't reach a service over the network":/401|403|Unauthorized|Forbidden|invalid token|missing scope/i.test(e)?"Authentication or permission denied":/rate limit|429|too many requests/i.test(e)?"Hit a rate limit (too many calls)":/quota|insufficient_quota/i.test(e)?"Provider account out of quota or credits":/tier-?2|tier two|200K|200,000/i.test(e)?"Hit Anthropic tier-2 billing threshold":/JSON|parse|unexpected token/i.test(e)?"Got a response in the wrong shape":/permission denied|EACCES|EPERM/i.test(e)?"File permission denied":/ENOENT|no such file/i.test(e)?"Expected file is missing":/abort|cancel/i.test(e)?"Task was cancelled before it finished":e.split(`
6018
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function hs(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),m=k=>p.length?p[Math.min(p.length-1,Math.floor(p.length*k))].duration_ms:0,h=m(.5),y=m(.95),w=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((k,M)=>k+gt(M),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((k,M)=>k+gt(M),0),T=t.prepare(`
6017
+ `,u=r.db.prepare(d).all(l).map(f=>({...f,plain:vn(f.error)}));return de(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return de(e,200,Ks(r.db)),!0;if(n==="activity")return de(e,200,Js(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=un(i.searchParams.get("range"));return de(e,200,mn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=un(i.searchParams.get("range")),d=mn(r.db,l),p=Vs(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return de(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return de(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function vn(t){let e=String(t||"");return e?/timed out|SIGTERM|exit 143|maxExecutionMinutes/i.test(e)?"Agent ran past its time limit":/ECONNREFUSED|fetch failed|getaddrinfo|ENOTFOUND/i.test(e)?"Couldn't reach a service over the network":/401|403|Unauthorized|Forbidden|invalid token|missing scope/i.test(e)?"Authentication or permission denied":/rate limit|429|too many requests/i.test(e)?"Hit a rate limit (too many calls)":/quota|insufficient_quota/i.test(e)?"Provider account out of quota or credits":/tier-?2|tier two|200K|200,000/i.test(e)?"Hit Anthropic tier-2 billing threshold":/JSON|parse|unexpected token/i.test(e)?"Got a response in the wrong shape":/permission denied|EACCES|EPERM/i.test(e)?"File permission denied":/ENOENT|no such file/i.test(e)?"Expected file is missing":/abort|cancel/i.test(e)?"Task was cancelled before it finished":e.split(`
6018
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Ks(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=_=>p.length?p[Math.min(p.length-1,Math.floor(p.length*_))].duration_ms:0,f=u(.5),y=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Tt(M),0),g=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Tt(M),0),S=t.prepare(`
6019
6019
  SELECT agent_id,
6020
6020
  COUNT(*) AS tasks,
6021
6021
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -6033,12 +6033,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6033
6033
  WHERE started_at >= ?
6034
6034
  GROUP BY channel
6035
6035
  ORDER BY tasks DESC
6036
- `).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(k=>k.agent_id),f=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(k=>k.agent_id)),g=u.filter(k=>!f.has(k)),x=t.prepare(`
6036
+ `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),x=m.filter(_=>!h.has(_)),v=t.prepare(`
6037
6037
  SELECT started_at, agent_id, channel, message_preview, error
6038
6038
  FROM task_history
6039
6039
  WHERE status='error' AND started_at >= ?
6040
6040
  ORDER BY started_at DESC LIMIT 5
6041
- `).all(o).map(k=>({...k,plain:Qa(k.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:h,p95DurationMs:y,spendToday:w,spendDelta:w-E,idleAgentCount:g.length},perAgent:T,perChannel:c,idleAgents:g,recentErrors:x}}function fs(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(`
6041
+ `).all(o).map(_=>({..._,plain:vn(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:y,spendToday:T,spendDelta:T-g,idleAgentCount:x.length},perAgent:S,perChannel:c,idleAgents:x,recentErrors:v}}function Js(t,e){let a=new Date(Date.now()-864e5).toISOString(),n=new Date(Date.now()-7*864e5).toISOString(),r=e.agent?"AND agent_id = @agent":"",o=e.agent?{agent:e.agent}:{},s=t.prepare(`
6042
6042
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
6043
6043
  COUNT(*) AS tasks,
6044
6044
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6065,7 +6065,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6065
6065
  WHERE started_at >= @since
6066
6066
  GROUP BY agent_id
6067
6067
  ORDER BY tasks_24h DESC, tasks_7d DESC
6068
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function 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 Xa(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6068
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function un(t){if(!t)return 30;if(t==="all"||t==="0")return 0;let e=parseInt(t,10);return!Number.isFinite(e)||e<=0?30:Math.min(e,365)}function mn(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6069
6069
  SELECT day, agent_id, model,
6070
6070
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
6071
6071
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -6073,37 +6073,37 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6073
6073
  FROM usage_daily
6074
6074
  ${a}
6075
6075
  ORDER BY day
6076
- `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,m=0,h=0,y=0,S=0,w=0,E=0,T={},c={};for(let _ of n){let I=gt(_),L=Ja(_.model),R=Ka[L],H=(_.tier2_input_tokens||0)/1e6*R.input*.5+(_.tier2_output_tokens||0)/1e6*R.output*.5+(_.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(_.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,ee=(_.input_tokens||0)+(_.tier2_input_tokens||0),B=(_.output_tokens||0)+(_.tier2_output_tokens||0),D=(_.cache_read_tokens||0)+(_.tier2_cache_read_tokens||0),N=(_.cache_create_tokens||0)+(_.tier2_cache_create_tokens||0);m+=I,_.day>=s&&(p+=I,S+=_.tasks||0),_.day>=i&&_.day<s&&(E+=I,w+=_.tasks||0),_.day===r&&(l+=I),_.day===o&&(d+=I),_.day===r&&(h+=H),_.day>=s&&(y+=H);let G=T[_.day]||(T[_.day]={date:_.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});G.tasks+=_.tasks||0,G.input+=ee,G.output+=B,G.cacheRead+=D,G.cacheCreate+=N,G.cost+=I,G.tier2+=H;let z=G.agents[_.agent_id]||(G.agents[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});z.tasks+=_.tasks||0,z.cost+=I,z.tier2+=H,z.input+=ee,z.output+=B,z.cacheRead+=D,z.cacheCreate+=N,_.model&&(z.model=_.model);let X=c[_.agent_id]||(c[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});X.tasks+=_.tasks||0,X.cost+=I,X.tier2+=H,X.input+=ee,X.output+=B,X.cacheRead+=D,X.cacheCreate+=N,_.model&&(X.model=_.model)}let u=Object.values(T).sort((_,I)=>_.date<I.date?-1:1),f=0,g=0,b=0,x=0,k=0,M=0;for(let _ of u)f+=_.tasks,g+=_.input,b+=_.output,x+=_.cacheRead,k+=_.cacheCreate,M+=_.cost;let A=Object.entries(c).map(([_,I])=>({agent_id:_,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((_,I)=>I.cost-_.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:m,tier2Today:h,tier2_7d:y,tier2PctToday:l>0?h/l:0,spendRange:M,avgDailyRange:u.length?M/u.length:0,tasksRange:f,tokensRange:g+b+x+k,cacheHitRange:x+g>0?x/(x+g):0,costPerTaskRange:f>0?M/f:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:w>0?(S-w)/w:0},days:u,perAgent:A}}function gs(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+`
6076
+ `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,u=0,f=0,y=0,w=0,T=0,g=0,S={},c={};for(let E of n){let I=Tt(E),j=hn(E.model),R=fn[j],B=(E.tier2_input_tokens||0)/1e6*R.input*.5+(E.tier2_output_tokens||0)/1e6*R.output*.5+(E.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,te=(E.input_tokens||0)+(E.tier2_input_tokens||0),z=(E.output_tokens||0)+(E.tier2_output_tokens||0),D=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),H=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=I,E.day>=s&&(p+=I,w+=E.tasks||0),E.day>=i&&E.day<s&&(g+=I,T+=E.tasks||0),E.day===r&&(l+=I),E.day===o&&(d+=I),E.day===r&&(f+=B),E.day>=s&&(y+=B);let J=S[E.day]||(S[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});J.tasks+=E.tasks||0,J.input+=te,J.output+=z,J.cacheRead+=D,J.cacheCreate+=H,J.cost+=I,J.tier2+=B;let q=J.agents[E.agent_id]||(J.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});q.tasks+=E.tasks||0,q.cost+=I,q.tier2+=B,q.input+=te,q.output+=z,q.cacheRead+=D,q.cacheCreate+=H,E.model&&(q.model=E.model);let V=c[E.agent_id]||(c[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});V.tasks+=E.tasks||0,V.cost+=I,V.tier2+=B,V.input+=te,V.output+=z,V.cacheRead+=D,V.cacheCreate+=H,E.model&&(V.model=E.model)}let m=Object.values(S).sort((E,I)=>E.date<I.date?-1:1),h=0,x=0,k=0,v=0,_=0,M=0;for(let E of m)h+=E.tasks,x+=E.input,k+=E.output,v+=E.cacheRead,_+=E.cacheCreate,M+=E.cost;let A=Object.entries(c).map(([E,I])=>({agent_id:E,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((E,I)=>I.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:y,tier2PctToday:l>0?f/l:0,spendRange:M,avgDailyRange:m.length?M/m.length:0,tasksRange:h,tokensRange:x+k+v+_,cacheHitRange:v+x>0?v/(v+x):0,costPerTaskRange:h>0?M/h:0,spendDeltaWoW:g>0?(p-g)/g:0,tasksDeltaWoW:T>0?(w-T)/T:0},days:m,perAgent:A}}function Vs(t){let e="date,tasks,input,output,cache_read,cache_create,cost_usd,top_agent",a=t.map(n=>{let r=Object.entries(n.agents).sort(([,o],[,s])=>s.cost-o.cost)[0];return[n.date,n.tasks,n.input,n.output,n.cacheRead,n.cacheCreate,n.cost.toFixed(6),r?r[0]:""].join(",")});return e+`
6077
6077
  `+a.join(`
6078
6078
  `)+`
6079
- `}import{resolve as xs}from"path";import{existsSync as vs}from"fs";import bs from"better-sqlite3";function ys(){let t=xs(process.cwd(),".agentx/intent/ledger.sqlite");if(!vs(t))return null;try{let e=new bs(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Za>6e4&&(Za=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Za=0;function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ws(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 en(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ys();if(!r)return fe(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ws(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let m=s!==void 0?"WHERE ts >= @since":"",h=s!==void 0?"WHERE decided_at >= @since":"",y=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${h}`).get({since:s}).n,w=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${h} 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}),c=r.db.prepare(`
6079
+ `}import{resolve as Ys}from"path";import{existsSync as Qs}from"fs";import Zs from"better-sqlite3";function ei(){let t=Ys(process.cwd(),".agentx/intent/ledger.sqlite");if(!Qs(t))return null;try{let e=new Zs(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-bn>6e4&&(bn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var bn=0;function ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ti(t){if(!t)return;let e=String(t).trim().match(/^(\d+)\s*(s|m|h|d|w)?$/i);if(!e)return;let a=parseInt(e[1],10),n=(e[2]||"h").toLowerCase(),r=n==="s"?1e3:n==="m"?6e4:n==="h"?36e5:n==="d"?864e5:n==="w"?7*864e5:0;return Date.now()-a*r}async function yn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ei();if(!r)return ve(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ti(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",y=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),w=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,T=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),g=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,S=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),c=r.db.prepare(`
6080
6080
  SELECT COUNT(*) AS n FROM intent_decisions d
6081
6081
  LEFT JOIN intent_resolutions r
6082
6082
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6083
6083
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
6084
- `).get().n;return fe(e,200,{since:s??null,eventsBySource:y,totalDecisions:S,decisionsByOutcome:w,totalDivergences:E,divergencesBySource:T,inFlight:c}),!0}if(n==="events"){let m=[],h={limit:p};s!==void 0&&(m.push("ts >= @since"),h.since=s),i&&(m.push("source = @source"),h.source=i),l&&(m.push("project = @project"),h.project=l);let y=`
6084
+ `).get().n;return ve(e,200,{since:s??null,eventsBySource:y,totalDecisions:w,decisionsByOutcome:T,totalDivergences:g,divergencesBySource:S,inFlight:c}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let y=`
6085
6085
  SELECT id, ts, source, source_event_id, project, subject, intent
6086
6086
  FROM intent_events
6087
- ${m.length?"WHERE "+m.join(" AND "):""}
6087
+ ${u.length?"WHERE "+u.join(" AND "):""}
6088
6088
  ORDER BY ts DESC LIMIT @limit
6089
- `;return fe(e,200,{rows:r.db.prepare(y).all(h)}),!0}if(n==="divergences"){let m=[],h={limit:p};s!==void 0&&(m.push("ts >= @since"),h.since=s),i&&(m.push("source = @source"),h.source=i);let y=`
6089
+ `;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}if(n==="divergences"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i);let y=`
6090
6090
  SELECT ts, source, decided_by,
6091
6091
  legacy_agent_id, legacy_outcome, legacy_reason,
6092
6092
  ledger_agent_id, ledger_outcome, ledger_reason,
6093
6093
  event_id
6094
6094
  FROM intent_divergences
6095
- ${m.length?"WHERE "+m.join(" AND "):""}
6095
+ ${u.length?"WHERE "+u.join(" AND "):""}
6096
6096
  ORDER BY ts DESC LIMIT @limit
6097
- `;return fe(e,200,{rows:r.db.prepare(y).all(h)}),!0}if(n==="active"){let m=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],h={limit:p};i&&(m.push("e.source = @source"),h.source=i);let y=`
6097
+ `;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],f={limit:p};i&&(u.push("e.source = @source"),f.source=i);let y=`
6098
6098
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
6099
6099
  d.decided_by, d.decided_at, d.agent_id, d.reason
6100
6100
  FROM intent_decisions d
6101
6101
  JOIN intent_events e ON e.id = d.event_id
6102
6102
  LEFT JOIN intent_resolutions r
6103
6103
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6104
- WHERE ${m.join(" AND ")}
6104
+ WHERE ${u.join(" AND ")}
6105
6105
  ORDER BY d.decided_at DESC LIMIT @limit
6106
- `;return fe(e,200,{rows:r.db.prepare(y).all(h)}),!0}return fe(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return fe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function tn(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6106
+ `;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}return ve(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function wn(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6107
6107
  <header class="ax-led__head">
6108
6108
  <h1>Intent ledger</h1>
6109
6109
  <p class="ax-led__sub">Read-only view over <code>.agentx/intent/ledger.sqlite</code> \u2014 same source as <code>agentx ledger</code>. Replay and lineage live in the CLI for now.</p>
@@ -6308,7 +6308,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6308
6308
  }
6309
6309
  load();
6310
6310
  })();
6311
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function an(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6311
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function kn(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6312
6312
  <header class="ax-cost__head">
6313
6313
  <div>
6314
6314
  <h1>Cost</h1>
@@ -6881,7 +6881,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6881
6881
  load();
6882
6882
  setInterval(load, 30000);
6883
6883
  })();
6884
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function nn(t={}){let e=`<div class="ax-pj__root">
6884
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function _n(t={}){let e=`<div class="ax-pj__root">
6885
6885
  <aside class="ax-pj__list">
6886
6886
  <header>
6887
6887
  <h2>Projects</h2>
@@ -6908,7 +6908,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6908
6908
  </header>
6909
6909
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
6910
6910
  </section>
6911
- </div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ks,scripts:`<script>${_s}</script>`})}var ks=`
6911
+ </div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ai,scripts:`<script>${ni}</script>`})}var ai=`
6912
6912
  .ax-pj__root {
6913
6913
  display: grid;
6914
6914
  grid-template-columns: 360px 1fr;
@@ -7095,7 +7095,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7095
7095
  }
7096
7096
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
7097
7097
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
7098
- `,_s=`
7098
+ `,ni=`
7099
7099
  (function(){
7100
7100
  const $ = (sel) => document.querySelector(sel);
7101
7101
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -7745,23 +7745,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7745
7745
  load();
7746
7746
  });
7747
7747
  })();
7748
- `;import{resolve as bt,join as Ds}from"path";import{existsSync as yt,readdirSync as Ns,readFileSync as Hs}from"fs";import Bs from"better-sqlite3";var on=String.raw`[\w.-]+(?:/[\w.-]+)+`,Ss=new RegExp(`^(?:chat:)?(${on}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Es=new RegExp(`^\\[(?:GitLab|GitHub) (${on}) `);function rn(t){if(!t)return null;let e=t.match(Ss);return e?e[1]:null}function xt(t){if(!t)return null;let e=t.trimStart().match(Es);return e?e[1]:null}function Ge(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():rn(typeof n?.chatId=="string"?n.chatId:null)??rn(e)??xt(a)}function Ts(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Xe(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Cs=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,As=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ms=t=>/^issue/i.test(t)?"issue":"mr";function Is(t){let e=t.subject.match(Cs)??t.inputPreview.trimStart().match(As);return e?{kind:Ms(e[1]),n:Number(e[2])}:null}function $s(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 sn(t){if(!Ts(t.projectId))return[];let e=Is(t);return e?[e]:$s(t.inputPreview)}var js=6e4,Ls=5*6e4,Rs=40,ln=6,dn=new Map;function cn(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 sn(n)){let s=Xe(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Rs)return[...e.values()]}}return[...e.values()]}async function pn(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Xe(s.project,s.ref),l=dn.get(i);l&&n-l.at<(s.github?Ls:js)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ln)await Promise.all(o.slice(s,s+ln).map(async i=>{let l=Xe(i.project,i.ref),d=null;try{d=i.github?await Os(i,e,a):await Ps(i,e,a)}catch{}dn.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function un(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 Ps(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 un(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let i=s.head_pipeline??s.pipeline;return{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(s.title??""),state:String(s.state??"opened"),draft:!!(s.draft??s.work_in_progress),url:String(s.web_url??""),pipeline:i&&typeof i.status=="string"?{status:i.status,url:String(i.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function Os(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 un(`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 wt(){let t=bt(process.cwd(),".agentx/intent/ledger.sqlite");if(!yt(t))return null;try{let e=new Bs(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-mn>6e4&&(mn=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var mn=0;function ie(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var we={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 zs(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in we)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in we)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in we)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 we)return s}return"workflow"}return t}function gn(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 qs(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 xn(t,e,a){return Wt(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 Fs(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:F(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!vt(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!vt(r||o||"")){let l=r||o||s,d=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:l,name:o||r||l,avatar:F(i),kind:d}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!vt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",m=hn(p);return{id:d,name:l||i||d,avatar:F(l||i||d),kind:m}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:F(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:F(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:F(i),kind:hn(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 hn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function vt(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 vn(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}
7748
+ `;import{resolve as Mt,join as xi}from"path";import{existsSync as It,readdirSync as vi,readFileSync as bi}from"fs";import yi from"better-sqlite3";var Sn=String.raw`[\w.-]+(?:/[\w.-]+)+`,ri=new RegExp(`^(?:chat:)?(${Sn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),oi=new RegExp(`^\\[(?:GitLab|GitHub) (${Sn}) `);function En(t){if(!t)return null;let e=t.match(ri);return e?e[1]:null}function Ct(t){if(!t)return null;let e=t.trimStart().match(oi);return e?e[1]:null}function Ze(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():En(typeof n?.chatId=="string"?n.chatId:null)??En(e)??Ct(a)}function si(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function et(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var ii=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,li=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,di=t=>/^issue/i.test(t)?"issue":"mr";function ci(t){let e=t.subject.match(ii)??t.inputPreview.trimStart().match(li);return e?{kind:di(e[1]),n:Number(e[2])}:null}function pi(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function Tn(t){if(!si(t.projectId))return[];let e=ci(t);return e?[e]:pi(t.inputPreview)}var ui=6e4,mi=5*6e4,fi=40,Cn=6,An=new Map;function Mn(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of Tn(n)){let s=et(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=fi)return[...e.values()]}}return[...e.values()]}async function In(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=et(s.project,s.ref),l=An.get(i);l&&n-l.at<(s.github?mi:ui)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Cn)await Promise.all(o.slice(s,s+Cn).map(async i=>{let l=et(i.project,i.ref),d=null;try{d=i.github?await gi(i,e,a):await hi(i,e,a)}catch{}An.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function $n(t,e,a){let n=new AbortController,r=setTimeout(()=>n.abort(),5e3);try{let o=await a(t,{headers:e,signal:n.signal});return o.ok?await o.json():null}finally{clearTimeout(r)}}async function hi(t,e,a){let n=e.gitlab;if(!n?.host||!n.token)return null;let r=`${n.host.replace(/\/+$/,"")}/api/v4/projects/${encodeURIComponent(t.project)}`,o=t.ref.kind==="mr"?`merge_requests/${t.ref.n}`:`issues/${t.ref.n}`,s=await $n(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let i=s.head_pipeline??s.pipeline;return{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(s.title??""),state:String(s.state??"opened"),draft:!!(s.draft??s.work_in_progress),url:String(s.web_url??""),pipeline:i&&typeof i.status=="string"?{status:i.status,url:String(i.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function gi(t,e,a){let n=t.ref.kind==="mr"?`pulls/${t.ref.n}`:`issues/${t.ref.n}`,r={Accept:"application/vnd.github+json","User-Agent":"agentx-dashboard"};e.githubToken&&(r.Authorization=`Bearer ${e.githubToken}`);let o=await $n(`https://api.github.com/repos/${t.project}/${n}`,r,a);return o?{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(o.title??""),state:o.merged_at?"merged":o.state==="open"?"opened":String(o.state??"opened"),draft:!!o.draft,url:String(o.html_url??""),pipeline:null,mergedAt:o.merged_at?Date.parse(o.merged_at):null}:null}function $t(){let t=Mt(process.cwd(),".agentx/intent/ledger.sqlite");if(!It(t))return null;try{let e=new yi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ln>6e4&&(Ln=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Ln=0;function ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var _e={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},opencode:{label:"OpenCode",color:"#57606a"}};function wi(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in _e)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in _e)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in _e)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in _e)return s}return"workflow"}return t}function Pn(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function ki(t,e){if(!t)return!1;let a=e?.agents?.[t];return a&&typeof a.system=="boolean"?a.system:!!(t==="graph-agent"||t==="intent-classifier"||/-classifier$/.test(t))}function Nn(t,e,a){return oa(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function _i(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:F(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!At(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!At(r||o||"")){let l=r||o||s,d=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:l,name:o||r||l,avatar:F(i),kind:d}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!At(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=jn(p);return{id:d,name:l||i||d,avatar:F(l||i||d),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:F(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:F(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:F(i),kind:jn(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:F(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:F(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:F(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:F(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:F(o),kind:"whatsapp"}}}return null}function jn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function At(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function F(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function On(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
7749
7749
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
7750
- ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function Us(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 bn(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7750
+ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function Ei(t){if(!t)return"(no subject)";let e;return(e=t.match(/^merge_request:(\d+)(?::note:(\d+))?/))?e[2]?`MR #${e[1]} \xB7 note ${e[2]}`:`MR #${e[1]}`:(e=t.match(/^issue:(\d+)(?::note:(\d+))?/))?e[2]?`Issue #${e[1]} \xB7 note ${e[2]}`:`Issue #${e[1]}`:(e=t.match(/^chat:(.+?):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,40)}`:(e=t.match(/^mesh:agent:(.+)$/))?`\u2192 ${e[1]}`:(e=t.match(/^workflow:([^:]+):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,30)}`:t.length>60?t.slice(0,57)+"\u2026":t}function Dn(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7751
7751
  SELECT id, ts, source, project, subject, intent, raw_json
7752
7752
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
7753
- `).all(r),s=new Map,i=new Map;if(o.length>0){let x=o.map(I=>I.id),k=x.map((I,L)=>`@id${L}`).join(","),M=Object.fromEntries(x.map((I,L)=>[`id${L}`,I])),A=t.prepare(`
7753
+ `).all(r),s=new Map,i=new Map;if(o.length>0){let v=o.map(I=>I.id),_=v.map((I,j)=>`@id${j}`).join(","),M=Object.fromEntries(v.map((I,j)=>[`id${j}`,I])),A=t.prepare(`
7754
7754
  SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
7755
- FROM intent_decisions WHERE event_id IN (${k}) ORDER BY decided_at ASC
7756
- `).all(M);for(let I of A)s.has(I.event_id)||s.set(I.event_id,[]),s.get(I.event_id).push(I);let _=t.prepare(`
7755
+ FROM intent_decisions WHERE event_id IN (${_}) ORDER BY decided_at ASC
7756
+ `).all(M);for(let I of A)s.has(I.event_id)||s.set(I.event_id,[]),s.get(I.event_id).push(I);let E=t.prepare(`
7757
7757
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
7758
- FROM intent_resolutions WHERE decision_event_id IN (${k})
7759
- `).all(M);for(let I of _)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,d=new Map,p=new Map,m=new Map,h=[],y=e?.business?.projects??[],S=e?.business?.contactMap??[],w=ot(e?.business??{});for(let x of o){let k=null;try{k=JSON.parse(x.raw_json)}catch{}let M=xn(x.source,k,S),A=vn(x.source,k),_=x.project??Ge(k,x.subject,A),I=null,L=null;M?(I=M.client,L=M.project||`${M.client}/_chat`):_&&(I=$e(_,y),L=_);let R=zs(x.source,x.intent||"",k),H=we[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:H.label,color:H.color});let ee="__system",B,D=Fs(x.source,x.intent||"",k);if(D){ee=D.id,B=D.kind;let N=M?.displayName||D.name;(!m.has(D.id)||M?.displayName)&&m.set(D.id,{id:D.id,name:N,avatar:F(N),kind:D.kind})}else m.has("__system")||m.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(x.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let G=`${x.id}|${N.decided_by}`,z=i.get(G),X=N.decided_at,Rt=z?.resolved_at??null,et=Rt===null,xr=z?.duration_ms??(et?n-X:0),vr=et?"active":z?.status==="error"||z?.status==="fail"?"error":"completed",W,_e;if(I)W=I,_e=L;else{let tt=w.get(N.agent_id);tt?(W=tt,_e=`${tt}/_${x.source}`):(W="unmapped",_e=`unmapped/_${x.source}`)}l.has(W)||l.set(W,{id:W,name:W,color:gn(W),projects:[]}),d.has(W)||d.set(W,new Set),d.get(W).add(_e),h.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:W,projectId:_e,channelId:R,initiatorId:ee,initiatorKind:B,subject:Us(x.subject),intent:x.intent||"",startedAt:X,resolvedAt:Rt,duration:xr,active:et,outcome:vr,tokens:0,inputPreview:A,system:qs(N.agent_id,e)})}}let E=[...l.values()].map(x=>({...x,projects:[...d.get(x.id)||[]].sort()})).sort((x,k)=>x.id.localeCompare(k.id)),T=[],c=new Set;if(e){let x=e.business??{},k=M=>{let A=x.orgChart?.[M]?.role,_=A?x.roles?.[A]?.title:void 0;return typeof _=="string"&&_.trim()?_.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let _={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:k(M)};T.push(_),c.add(M)}}for(let x of h)c.has(x.agentId)||(T.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),c.add(x.agentId));T.sort((x,k)=>x.id.localeCompare(k.id));let u=[],f=new Set;for(let[x,k]of Object.entries(we))u.push({id:x,label:k.label,color:k.color}),f.add(x);for(let x of p.values())f.has(x.id)||u.push(x);let g=[...m.values()];g.find(x=>x.id==="__system")||g.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let b=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:T,channels:u,initiators:g,dispatches:h,forges:{gitlab:typeof b=="string"?b:void 0,github:"https://github.com"}}}function kt(t){let e=wt();if(!e)return null;try{return bn(e.db,de,t)}finally{e.close()}}function yn(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let m of p.clients){let h=e.get(m.id);if(!h)e.set(m.id,{...m,projects:[...m.projects]});else{let y=Array.from(new Set([...h.projects,...m.projects])).sort();e.set(m.id,{...h,projects:y})}}for(let m of p.agents)a.has(m.id)||a.set(m.id,m);for(let m of p.channels)n.has(m.id)||n.set(m.id,m);for(let m of p.initiators)r.has(m.id)||r.set(m.id,m);for(let m of p.dispatches){let h=Ws(m);if(h.clientId!==m.clientId&&!e.has(h.clientId)&&e.set(h.clientId,{id:h.clientId,name:h.clientId,color:gn(h.clientId),projects:[]}),h.projectId!==m.projectId){let y=e.get(h.clientId);y.projects.includes(h.projectId)||e.set(h.clientId,{...y,projects:[...y.projects,h.projectId].sort()})}o.push({...h,nodeId:d,id:`${d}::${h.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,p)=>d.id.localeCompare(p.id)),agents:[...a.values()].sort((d,p)=>d.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,p)=>p.startedAt-d.startedAt)}}function Ws(t){if(t.clientId!=="unmapped")return t;let e=xt(t.inputPreview);if(!e)return t;let a=de?.business?.projects??[];return{...t,projectId:e,clientId:$e(e,a)}}async function Ke(t){let e=de?.channels?.gitlab,a=await pn(cn(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 de=null;function wn(t){de=t}async function kn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=wt();if(!n)return ie(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=_n(parseInt(r.searchParams.get("hours")||"6",10));ie(e,200,await Ke(bn(n.db,de,o)))}catch(r){ie(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Gs=5e3;async function _t(t,e,a,n=kt){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
7758
+ FROM intent_resolutions WHERE decision_event_id IN (${_})
7759
+ `).all(M);for(let I of E)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,d=new Map,p=new Map,u=new Map,f=[],y=e?.business?.projects??[],w=e?.business?.contactMap??[],T=ht(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Nn(v.source,_,w),A=On(v.source,_),E=v.project??Ze(_,v.subject,A),I=null,j=null;M?(I=M.client,j=M.project||`${M.client}/_chat`):E&&(I=De(E,y),j=E);let R=wi(v.source,v.intent||"",_),B=_e[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:B.label,color:B.color});let te="__system",z,D=_i(v.source,v.intent||"",_);if(D){te=D.id,z=D.kind;let H=M?.displayName||D.name;(!u.has(D.id)||M?.displayName)&&u.set(D.id,{id:D.id,name:H,avatar:F(H),kind:D.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(v.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let J=`${v.id}|${H.decided_by}`,q=i.get(J),V=H.decided_at,Kt=q?.resolved_at??null,dt=Kt===null,Yr=q?.duration_ms??(dt?n-V:0),Qr=dt?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",G,Ae;if(I)G=I,Ae=j;else{let ct=T.get(H.agent_id);ct?(G=ct,Ae=`${ct}/_${v.source}`):(G="unmapped",Ae=`unmapped/_${v.source}`)}l.has(G)||l.set(G,{id:G,name:G,color:Pn(G),projects:[]}),d.has(G)||d.set(G,new Set),d.get(G).add(Ae),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:G,projectId:Ae,channelId:R,initiatorId:te,initiatorKind:z,subject:Ei(v.subject),intent:v.intent||"",startedAt:V,resolvedAt:Kt,duration:Yr,active:dt,outcome:Qr,tokens:0,inputPreview:A,system:ki(H.agent_id,e)})}}let g=[...l.values()].map(v=>({...v,projects:[...d.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),S=[],c=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,E=A?v.roles?.[A]?.title:void 0;return typeof E=="string"&&E.trim()?E.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let E={id:M,name:A.name||M,tier:A.tier==="claude-code"?"lead":"worker",model:A.model||"",role:A.systemPrompt?A.systemPrompt.split(/[.\n]/)[0].slice(0,60):A.tier||"",title:_(M)};S.push(E),c.add(M)}}for(let v of f)c.has(v.agentId)||(S.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),c.add(v.agentId));S.sort((v,_)=>v.id.localeCompare(_.id));let m=[],h=new Set;for(let[v,_]of Object.entries(_e))m.push({id:v,label:_.label,color:_.color}),h.add(v);for(let v of p.values())h.has(v.id)||m.push(v);let x=[...u.values()];x.find(v=>v.id==="__system")||x.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:S,channels:m,initiators:x,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function Lt(t){let e=$t();if(!e)return null;try{return Dn(e.db,me,t)}finally{e.close()}}function Hn(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let y=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:y})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=Si(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Pn(f.clientId),projects:[]}),f.projectId!==u.projectId){let y=e.get(f.clientId);y.projects.includes(f.projectId)||e.set(f.clientId,{...y,projects:[...y.projects,f.projectId].sort()})}o.push({...f,nodeId:d,id:`${d}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,p)=>d.id.localeCompare(p.id)),agents:[...a.values()].sort((d,p)=>d.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,p)=>p.startedAt-d.startedAt)}}function Si(t){if(t.clientId!=="unmapped")return t;let e=Ct(t.inputPreview);if(!e)return t;let a=me?.business?.projects??[];return{...t,projectId:e,clientId:De(e,a)}}async function tt(t){let e=me?.channels?.gitlab,a=await In(Mn(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var me=null;function Bn(t){me=t}async function zn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=$t();if(!n)return ce(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=qn(parseInt(r.searchParams.get("hours")||"6",10));ce(e,200,await tt(Dn(n.db,me,o)))}catch(r){ce(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Ti=5e3;async function jt(t,e,a,n=Lt){if(a!=="/api/admin/activity-graph/stream"&&!a.startsWith("/api/admin/activity-graph/stream?"))return!1;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: connected
7760
7760
 
7761
- `);let r=new URL(t.url||"/","http://_"),o=_n(parseInt(r.searchParams.get("hours")||"6",10)),s=!1,i=()=>{s=!0};t.on("close",i),t.on("error",i),e.on("close",i),e.on("error",i);let l=setInterval(()=>{if(!s)try{e.write(`: hb
7761
+ `);let r=new URL(t.url||"/","http://_"),o=qn(parseInt(r.searchParams.get("hours")||"6",10)),s=!1,i=()=>{s=!0};t.on("close",i),t.on("error",i),e.on("close",i),e.on("error",i);let l=setInterval(()=>{if(!s)try{e.write(`: hb
7762
7762
 
7763
- `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),m=p&&await Ke(p);if(s)break;m?(e.write(`event: snapshot
7764
- `),e.write(`data: ${JSON.stringify(m)}
7763
+ `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await tt(p);if(s)break;u?(e.write(`event: snapshot
7764
+ `),e.write(`data: ${JSON.stringify(u)}
7765
7765
 
7766
7766
  `)):e.write(`event: error
7767
7767
  data: ${JSON.stringify({error:"ledger not available"})}
@@ -7769,7 +7769,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
7769
7769
  `)}catch(p){e.write(`event: error
7770
7770
  data: ${JSON.stringify({error:p?.message??String(p)})}
7771
7771
 
7772
- `)}let d=Date.now();for(;!s&&Date.now()-d<Gs;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function _n(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Xs(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=bt(process.cwd(),".agentx/task-history",t,n);if(!yt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=bt(process.cwd(),".agentx/task-history",t,o);return yt(s)?fn(s,e,a):null}return fn(r,e,a)}function fn(t,e,a){let n=null,r=1/0;for(let o of Ns(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Hs(Ds(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function Sn(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 ie(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=wt();if(!l)return ie(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return ie(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return ie(e,404,{error:"decision not found"}),!0;let m=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),h=null;try{h=JSON.parse(d.raw_json)}catch{}let y=vn(d.source,h),S=h&&typeof h=="object"&&(h.text||h.message?.text||h.message?.caption||h.object_attributes?.note||h.object_attributes?.description||h.comment?.body||h.issue?.body||(typeof h.message=="string"?h.message:null)||(typeof h.prompt=="string"?h.prompt:null)||null)||y,w=null,E=null;if(p.agent_id){let b=Xs(p.agent_id,p.decided_at);if(b){typeof b.responseText=="string"&&(w=b.responseText);let x=b.transcript;Array.isArray(x)&&(E=x.length)}}let T=de?.business?.projects??[],c=de?.business?.contactMap??[],u=ot(de?.business??{}),f={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},g=xn(d.source,h,c);if(g)f={client:g.client,project:g.project||`${g.client}/_chat`,via:`contactMap (channel=${g.channel??"*"}${g.username?` username=${g.username}`:""}${g.chatId?` chatId=${g.chatId}`:""})`};else if(d.project||Ge(h,d.subject,y)){let b=d.project||Ge(h,d.subject,y);f={client:$e(b,T),project:b,via:d.project?`project namespace prefix (${b})`:`forge path in chat id / message (${b})`}}else if(p.agent_id){let b=u.get(p.agent_id);b&&(f={client:b,project:`${b}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${b})`})}ie(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:m?.resolved_at??null,durationMs:m?.duration_ms??null,input:S,response:w,transcriptLen:E,resolutionStatus:m?.status??null,resultSummary:m?.result_summary??null,attribution:f})}catch(d){ie(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Ys,readFileSync as Qs}from"fs";import{resolve as Tn}from"path";at();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=Ks.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:Js,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>${Vs}</script>`})}var Ks=`
7772
+ `)}let d=Date.now();for(;!s&&Date.now()-d<Ti;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function qn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ci(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Mt(process.cwd(),".agentx/task-history",t,n);if(!It(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Mt(process.cwd(),".agentx/task-history",t,o);return It(s)?Rn(s,e,a):null}return Rn(r,e,a)}function Rn(t,e,a){let n=null,r=1/0;for(let o of vi(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(bi(xi(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function Un(t,e,a){let n=a.match(/^\/api\/admin\/activity-graph\/dispatch\/([^/?]+)(?:\?.*)?$/);if(!n)return!1;let r=decodeURIComponent(n[1]),o=r.indexOf("|");if(o<0)return ce(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=$t();if(!l)return ce(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return ce(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return ce(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(d.raw_json)}catch{}let y=On(d.source,f),w=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||y,T=null,g=null;if(p.agent_id){let k=Ci(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(T=k.responseText);let v=k.transcript;Array.isArray(v)&&(g=v.length)}}let S=me?.business?.projects??[],c=me?.business?.contactMap??[],m=ht(me?.business??{}),h={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=Nn(d.source,f,c);if(x)h={client:x.client,project:x.project||`${x.client}/_chat`,via:`contactMap (channel=${x.channel??"*"}${x.username?` username=${x.username}`:""}${x.chatId?` chatId=${x.chatId}`:""})`};else if(d.project||Ze(f,d.subject,y)){let k=d.project||Ze(f,d.subject,y);h={client:De(k,S),project:k,via:d.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=m.get(p.agent_id);k&&(h={client:k,project:`${k}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}ce(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:w,response:T,transcriptLen:g,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:h})}catch(d){ce(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as $i,readFileSync as Li}from"fs";import{resolve as Wn}from"path";pt();function Fn(t){let e=t.agentId,a=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",n=`<script>window.AGENT_ID = ${JSON.stringify(e)};</script>`,r=Ai.replace(/__AGENT_ID__/g,P(e));return $({title:`AgentX \xB7 ${P(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${P(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Mi,headExtras:'<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">',scripts:`${n}${a}<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script><script>${Ii}</script>`})}var Ai=`
7773
7773
  <!-- Breadcrumb -->
7774
7774
  <div class="ax-crumb">
7775
7775
  <a href="/admin">Settings</a>
@@ -8358,7 +8358,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
8358
8358
  </div>
8359
8359
  </div>
8360
8360
  </div>
8361
- `,Js=`
8361
+ `,Mi=`
8362
8362
  /* Agent-specific layout + legacy styles for bits the migration left in
8363
8363
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
8364
8364
  * primitives live in components.css.ts. */
@@ -8477,7 +8477,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
8477
8477
 
8478
8478
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
8479
8479
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
8480
- `,Vs=`
8480
+ `,Ii=`
8481
8481
  const $ = (id) => document.getElementById(id);
8482
8482
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
8483
8483
 
@@ -9331,15 +9331,15 @@ document.addEventListener('keydown', (e) => {
9331
9331
  /* ===== Boot ===== */
9332
9332
  initOptsToggles();
9333
9333
  loadAgent();
9334
- `;function Cn(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 An(t,e,a){try{let n=t.method==="GET"?void 0:await yi(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){Je(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,m={"GET ":()=>Te(i),"PATCH ":()=>Zs(i,n),"PATCH capability":()=>ai(i,n),"POST mcp":()=>ei(i,n),"DELETE mcp":()=>ti(i,n),"GET identity":()=>ni(i),"GET identity/file":()=>ri(i,String(o.path||"")),"PUT identity/file":()=>oi(i,n),"GET skills":()=>si(i),"POST skills":()=>ii(i,n),"DELETE skills":()=>li(i,n),"GET skills/tree":()=>di(i,String(o.slug||"")),"GET skills/file":()=>ci(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>pi(i,n),"GET skills/deps":()=>ui(i,String(o.slug||"")),"POST skills/install":()=>mi(i,n,t),"POST skills/deps":()=>hi(i,n,t),"GET channels":()=>fi(i),"GET activity":()=>gi(i,t),"GET handovers":()=>xi(i),"POST handovers":()=>vi(i,n),"DELETE handovers":()=>bi(n)}[d];if(!m){Je(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let h=await m();Je(e,200,h)}catch(n){Je(e,400,{error:n?.message||"agent op failed"})}}function Mn(){let t=Tn(process.cwd(),"agentx.json");return Ys(t)?JSON.parse(Qs(t,"utf-8")):null}function U(t){let e=Mn();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 Te(t){let{def:e,cfg:a}=U(t),n=e.workspace?xe(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 Zs(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:Te(t)}}function ei(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:Te(t)}}function ti(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:Te(t)}}function ai(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Te(t)}}function ni(t){let{def:e}=U(t);return xe(e.workspace)}function ri(t,e){if(!e)throw new Error("path query param required");let{def:a}=U(t);return Re(a.workspace,e)}function oi(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=U(t);return Pe(n.workspace,a,String(e?.content??""))}function si(t){let{def:e}=U(t),a=xe(e.workspace);return{skills:a.skills,workspace:a.workspace}}function ii(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=U(t);return Oe(n.workspace,a,{title:e?.title,content:e?.content})}function li(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=U(t);return De(n.workspace,a)}function di(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t),n=ea(a.workspace,e),r=Ne(a.workspace,e);return{slug:e,tree:n,deps:r}}function ci(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=U(t);return ta(n.workspace,e,a)}function pi(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 aa(r.workspace,a,n,String(e?.content??""))}function ui(t,e){if(!e)throw new Error("slug query param required");let{def:a}=U(t);return Ne(a.workspace,e)}async function mi(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=In(e?.worker),{def:o}=U(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
9335
- `);return $n(a,r,s,`install-${n}:${Date.now()}`)}async function hi(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=In(e?.worker),{def:o}=U(t),s=Ne(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=Tn(o.workspace,".claude","skills",n),l=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${i}`,`Detected manifest: ${s.file}`,`Run: ${s.command}`,"Stream the install output. On success, summarise the packages installed.","On failure, report the exit code and the last 20 lines of output."].join(`
9336
- `);return $n(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function In(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 $n(t,e,a,n){let r=K(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),p;try{p=JSON.parse(d)}catch{p={content:d}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function fi(t){let e=Mn(),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 gi(t,e){try{let n=(K().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function St(){return new Nt}function xi(t){let e=St(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function vi(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=St().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function bi(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:St().remove(e,a,n)?"Released":"No active handover for that chat"}}function Je(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function yi(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 ge={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 jn=[{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 Et(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(ge)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9334
+ `;function Gn(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fn({agentId:a,peers:n,localToken:r}))}async function Xn(t,e,a){try{let n=t.method==="GET"?void 0:await el(t),r=new URL(t.url||"/","http://localhost"),o=Object.fromEntries(r.searchParams),s=a.match(/^\/api\/admin\/agent\/([a-z0-9][a-z0-9_-]*)(?:\/(.+))?$/);if(!s){at(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>$e(i),"PATCH ":()=>ji(i,n),"PATCH capability":()=>Ni(i,n),"POST mcp":()=>Ri(i,n),"DELETE mcp":()=>Pi(i,n),"GET identity":()=>Oi(i),"GET identity/file":()=>Di(i,String(o.path||"")),"PUT identity/file":()=>Hi(i,n),"GET skills":()=>Bi(i),"POST skills":()=>zi(i,n),"DELETE skills":()=>qi(i,n),"GET skills/tree":()=>Ui(i,String(o.slug||"")),"GET skills/file":()=>Fi(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Wi(i,n),"GET skills/deps":()=>Gi(i,String(o.slug||"")),"POST skills/install":()=>Xi(i,n,t),"POST skills/deps":()=>Ki(i,n,t),"GET channels":()=>Ji(i),"GET activity":()=>Vi(i,t),"GET handovers":()=>Yi(i),"POST handovers":()=>Qi(i,n),"DELETE handovers":()=>Zi(n)}[d];if(!u){at(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();at(e,200,f)}catch(n){at(e,400,{error:n?.message||"agent op failed"})}}function Kn(){let t=Wn(process.cwd(),"agentx.json");return $i(t)?JSON.parse(Li(t,"utf-8")):null}function W(t){let e=Kn();if(!e)throw new Error("agentx.json not found");let a=e.agents?.[t];if(!a)throw new Error(`Agent "${t}" not found`);return{def:a,cfg:e}}function $e(t){let{def:e,cfg:a}=W(t),n=e.workspace?ye(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function ji(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:$e(t)}}function Ri(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:$e(t)}}function Pi(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:$e(t)}}function Ni(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:$e(t)}}function Oi(t){let{def:e}=W(t);return ye(e.workspace)}function Di(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return ze(a.workspace,e)}function Hi(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return qe(n.workspace,a,String(e?.content??""))}function Bi(t){let{def:e}=W(t),a=ye(e.workspace);return{skills:a.skills,workspace:a.workspace}}function zi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ue(n.workspace,a,{title:e?.title,content:e?.content})}function qi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Fe(n.workspace,a)}function Ui(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=xa(a.workspace,e),r=We(a.workspace,e);return{slug:e,tree:n,deps:r}}function Fi(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return va(n.workspace,e,a)}function Wi(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=W(t);return ba(r.workspace,a,n,String(e?.content??""))}function Gi(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return We(a.workspace,e)}async function Xi(t,e,a){let n=String(e?.package||"").trim();if(!n||!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)?$/.test(n))throw new Error("package must be in 'owner/repo' or 'owner/repo/skill' form");let r=Jn(e?.worker),{def:o}=W(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
9335
+ `);return Vn(a,r,s,`install-${n}:${Date.now()}`)}async function Ki(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Jn(e?.worker),{def:o}=W(t),s=We(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=Wn(o.workspace,".claude","skills",n),l=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${i}`,`Detected manifest: ${s.file}`,`Run: ${s.command}`,"Stream the install output. On success, summarise the packages installed.","On failure, report the exit code and the last 20 lines of output."].join(`
9336
+ `);return Vn(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Jn(t){if(t&&typeof t=="string")return t;let e=Y();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Vn(t,e,a,n){let r=Y(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),p;try{p=JSON.parse(d)}catch{p={content:d}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Ji(t){let e=Kn(),a=[],n=e?.channels?.telegram?.accounts||{};for(let[o,s]of Object.entries(n))s?.agentBinding===t&&a.push({channel:"telegram",account:o,detail:s?.botUsername||o});e?.channels?.slack?.agentBinding===t&&a.push({channel:"slack",detail:"bound"}),e?.channels?.discord?.agentBinding===t&&a.push({channel:"discord",detail:"bound"});let r=e?.channels?.gitlab?.agentMappings||[];for(let o of r)o?.agentId===t&&a.push({channel:"gitlab",detail:(o?.gitlabUsernames||[]).join(", ")||"mapped"});return{bindings:a}}async function Vi(t,e){try{let n=(Y().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function Rt(){return new Qt}function Yi(t){let e=Rt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Qi(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=Rt().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function Zi(t){let e=String(t?.channel||"").trim(),a=String(t?.chatId||"").trim();if(!e||!a)throw new Error("channel and chatId required");let n=t?.accountId?String(t.accountId):void 0;return{summary:Rt().remove(e,a,n)?"Released":"No active handover for that chat"}}function at(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function el(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var be={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var Yn=[{term:"Agent",definition:'An AI worker with its own role, instructions, and channels it responds on. Think of each agent as a job title \u2014 "support", "devops", "sales".'},{term:"Trigger word",alias:"mention",definition:"A word that activates an agent. When the trigger appears in a message (e.g. @support), AgentX routes the message to that agent."},{term:"Channel",definition:"Where messages come from \u2014 Telegram, WhatsApp, Discord, GitLab comments, a scheduled cron, or an HTTP webhook."},{term:"AI engine",alias:"tier",definition:"Which backend answers: Claude Code, Codex CLI, Anthropic Agent SDK, or AgentX's provider-agnostic orchestrator."},{term:"Agent folder",alias:"workspace",definition:"The directory on disk where the agent lives. It holds the agent's personality (CLAUDE.md), its knowledge (wiki), and the tools it can use."},{term:"Team network",alias:"mesh",definition:'When you run AgentX on more than one machine, the machines find each other and share work. Each machine is a "node"; together they are your team network.'},{term:"Status check-in",alias:"heartbeat",definition:"A lightweight ping between machines so each one knows the others are alive and responsive."},{term:"Board",definition:"A Kanban view of tasks (issues, tickets) pulled from GitLab. Drag cards between columns to move work forward \u2014 the labels update upstream automatically."},{term:"Task",definition:"A single conversation or job an agent handles, from trigger message to final reply. Every task is logged and replayable."},{term:"Schedule",alias:"cron",definition:'A recurring job \u2014 e.g. "every Monday at 9am" \u2014 that nudges an agent without a human trigger.'},{term:"Status label",alias:"scopedLabel",definition:"A GitLab label that moves an issue between Kanban columns (e.g. Status::Doing). Labels are mutually exclusive by prefix."}];function Pt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(be)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9337
9337
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
9338
9338
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
9339
9339
  <section id="statstrip" class="ax-statstrip"></section>
9340
9340
  <main id="grid" class="ax-live__body"></main>
9341
9341
  </div>
9342
- `;return $({title:`${ge.brand} \xB7 ${ge.subtitle}`,activeTab:"live",subtitle:ge.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:wi,scripts:e+`<script>${ki}</script>`,headExtras:`<script>
9342
+ `;return $({title:`${be.brand} \xB7 ${be.subtitle}`,activeTab:"live",subtitle:be.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:tl,scripts:e+`<script>${al}</script>`,headExtras:`<script>
9343
9343
  // rightExtras for the topbar are injected at runtime \u2014 they reference
9344
9344
  // IDs (#ts, #conn-dot) that the script below addresses directly.
9345
9345
  document.addEventListener('DOMContentLoaded', () => {
@@ -9350,7 +9350,7 @@ loadAgent();
9350
9350
  extras.innerHTML = ${JSON.stringify(a)};
9351
9351
  right.insertBefore(extras, right.firstChild);
9352
9352
  });
9353
- </script>`})}var wi=`
9353
+ </script>`})}var tl=`
9354
9354
  /* --- Page frame --- */
9355
9355
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
9356
9356
 
@@ -9369,6 +9369,10 @@ loadAgent();
9369
9369
  .ax-node__tag--wait { color: var(--ax-warn, var(--ax-text-2)); border-color: currentColor; }
9370
9370
  .ax-node__name { font-weight: 600; font-size: 14px; }
9371
9371
  .ax-node__url { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 11px; }
9372
+ .ax-node__sessions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 10px 16px 0; font-size: 12px; color: var(--ax-muted); }
9373
+ .ax-node__session { display: inline-flex; gap: 6px; align-items: center; padding: 2px 8px; border: 1px solid var(--ax-line, currentColor); border-radius: 999px; color: var(--ax-text-2, inherit); }
9374
+ .ax-node__session.is-bound { color: var(--ax-text, inherit); border-color: var(--ax-accent, currentColor); }
9375
+ .ax-node__session.is-waiting { border-style: dashed; }
9372
9376
  .ax-node__tag {
9373
9377
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px;
9374
9378
  padding: 2px 7px; border-radius: 3px; border: 1px solid var(--ax-border-2);
@@ -9553,7 +9557,7 @@ loadAgent();
9553
9557
  border-top-color: var(--ax-accent); border-radius: 50%;
9554
9558
  animation: ax-spin 800ms linear infinite; display: inline-block;
9555
9559
  }
9556
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,ki=`
9560
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,al=`
9557
9561
  'use strict';
9558
9562
 
9559
9563
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -9705,13 +9709,16 @@ function runningBodyHtml(rows) {
9705
9709
  function renderNode(node) {
9706
9710
  const sec = document.createElement('section');
9707
9711
  sec.className = 'ax-node';
9708
- const tag = node.reachable
9712
+ // #193 \u2014 a briefly slow node keeps its last good data, marked stale.
9713
+ const tag = node.stale
9714
+ ? '<span class="ax-node__tag ax-node__tag--wait" role="status" title="' + escapeHtml(node.error || '') + '">not responding \xB7 data from ' + escapeHtml(fmtAgo(node.staleSince)) + '</span>'
9715
+ : node.reachable
9709
9716
  ? '<span class="ax-node__tag ax-node__tag--up">online \xB7 ' + (node.uptimeSec ? Math.round(node.uptimeSec / 60) + 'm' : '\u2014') + '</span>'
9710
9717
  : '<span class="ax-node__tag ax-node__tag--down">offline \u2014 ' + escapeHtml(node.error || 'unreachable') + '</span>';
9711
9718
  sec.innerHTML = '<header>' +
9712
9719
  '<span class="ax-node__name">' + escapeHtml(node.name) + '</span>' +
9713
9720
  '<span class="ax-node__url">' + escapeHtml(node.url) + '</span>' +
9714
- tag + restartHtml(node) + '</header><div class="ax-grid--agents"></div>';
9721
+ tag + (node.stale ? '' : restartHtml(node)) + '</header>' + sessionsHtml(node) + '<div class="ax-grid--agents"></div>';
9715
9722
  const g = sec.querySelector('.ax-grid--agents');
9716
9723
  if (!node.reachable || node.agents.length === 0) {
9717
9724
  const empty = document.createElement('div');
@@ -9725,6 +9732,22 @@ function renderNode(node) {
9725
9732
  return sec;
9726
9733
  }
9727
9734
 
9735
+ // #193 \u2014 Claude Code sessions registered with this node's attach hooks. A
9736
+ // bound one says which agent it answers for; "waiting" means the binding is
9737
+ // saved but the session has not reported since a restart or an idle spell.
9738
+ function sessionsHtml(node) {
9739
+ const rows = node.attachSessions || [];
9740
+ if (!rows.length) return '';
9741
+ const chips = rows.map(r => {
9742
+ const who = r.agentIds.length ? 'as ' + r.agentIds.join(', ') : 'not attached';
9743
+ const when = r.waiting ? 'waiting for session' : 'seen ' + fmtAgo(new Date(r.lastSeenAt).toISOString());
9744
+ const cls = 'ax-node__session' + (r.agentIds.length ? ' is-bound' : '') + (r.waiting ? ' is-waiting' : '');
9745
+ return '<span class="' + cls + '" title="session ' + escapeHtml(r.session) + ' \xB7 ' + escapeHtml(r.mode) + (r.pending ? ' \xB7 ' + r.pending + ' queued' : '') + '">' +
9746
+ '<b>' + escapeHtml(r.project || r.session) + '</b> ' + escapeHtml(who) + ' \xB7 ' + escapeHtml(when) + '</span>';
9747
+ }).join('');
9748
+ return '<div class="ax-node__sessions" aria-label="Claude Code sessions"><span>Claude Code sessions</span>' + chips + '</div>';
9749
+ }
9750
+
9728
9751
  // "Restart when idle": the node restarts itself once no task is running.
9729
9752
  // Only nodes that report restart state (GET /health) offer it.
9730
9753
  function restartHtml(node) {
@@ -9838,7 +9861,9 @@ function renderAgent(a, node) {
9838
9861
  '</div>'
9839
9862
  : (busy ? '' : '<div class="ax-agent__summary"><div class="ax-agent__summary-caption">' + escapeHtml(L.idle || 'idle') + '</div><div class="ax-agent__summary-text" style="font-style:italic;color:var(--ax-muted)">' + escapeHtml(L.neverRan || 'awaiting first task') + '</div></div>');
9840
9863
 
9841
- const lastActiveText = a.lastActive ? 'last active ' + fmtAgo(a.lastActive) : (L.neverRan || 'not used yet');
9864
+ const lastActiveText = (a.attached && !a.attached.waiting)
9865
+ ? 'Claude Code \xB7 ' + a.attached.project + ' \xB7 active ' + fmtAgo(new Date(a.attached.lastSeenAt).toISOString())
9866
+ : a.lastActive ? 'last active ' + fmtAgo(a.lastActive) : (L.neverRan || 'not used yet');
9842
9867
  const lastActiveAttr = a.lastActive ? ' data-last-active="' + escapeHtml(a.lastActive) + '"' : '';
9843
9868
  const recentLink = nodeUrl
9844
9869
  ? '<button class="ax-linkbtn" data-agent-id="' + escapeHtml(a.id) + '" data-agent-name="' + escapeHtml(a.name || a.id) + '" data-node-url="' + escapeHtml(nodeUrl) + '" data-recent="1">history \u2192</button>'
@@ -9850,6 +9875,12 @@ function renderAgent(a, node) {
9850
9875
  ? '<span class="ax-badge ax-badge--mono ax-badge--live"><span class="ax-dot ax-dot--live ax-dot--pulse"></span> live</span>'
9851
9876
  : (errored ? '<span class="ax-badge ax-badge--mono ax-badge--warn">errored</span>' : '<span class="ax-badge ax-badge--mono ax-badge--ghost">idle</span>');
9852
9877
  const tierBadge = tierDisplay ? '<span class="ax-badge ax-badge--mono ax-badge--ghost" title="AI engine">' + escapeHtml(tierDisplay) + '</span>' : '';
9878
+ // #193 \u2014 the Claude Code session answering for this agent.
9879
+ const at = a.attached;
9880
+ const attachBadge = at
9881
+ ? '<span class="ax-badge ax-badge--mono ' + (at.waiting ? 'ax-badge--ghost' : 'ax-badge--live') + '" title="Claude Code session ' + escapeHtml(at.session) + ' in ' + escapeHtml(at.project) + ' \xB7 ' + escapeHtml(at.mode) + '">' +
9882
+ (at.waiting ? 'waiting' : 'attached') + '</span>'
9883
+ : '';
9853
9884
 
9854
9885
  const head =
9855
9886
  '<div class="ax-agent__head">' +
@@ -9857,7 +9888,7 @@ function renderAgent(a, node) {
9857
9888
  '<span class="ax-mention">' + escapeHtml(mention) + '</span>' +
9858
9889
  '<span class="ax-agent__name">' + escapeHtml(a.name || a.id) + '</span>' +
9859
9890
  '</div>' +
9860
- '<div class="ax-agent__tier">' + tierBadge + liveBadge + '</div>' +
9891
+ '<div class="ax-agent__tier">' + attachBadge + tierBadge + liveBadge + '</div>' +
9861
9892
  '</div>';
9862
9893
 
9863
9894
  // An idle agent collapses to one line.
@@ -10097,7 +10128,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10097
10128
  });
10098
10129
  }
10099
10130
 
10100
- `;var Ln=`
10131
+ `;var Qn=`
10101
10132
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
10102
10133
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
10103
10134
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -10271,7 +10302,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10271
10302
  .mx-summary{max-width:56vw}
10272
10303
  }
10273
10304
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
10274
- `;var Rn=`<script>
10305
+ `;var Zn=`<script>
10275
10306
  window.MX=(function(){
10276
10307
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
10277
10308
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -10380,7 +10411,7 @@ window.MX=(function(){
10380
10411
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
10381
10412
  setHealth:setHealth,get:get};
10382
10413
  })();
10383
- </script>`;var Pn=`<script>
10414
+ </script>`;var er=`<script>
10384
10415
  window.MXD=(function(){
10385
10416
  function el(id){return document.getElementById(id)}
10386
10417
  function tz(){return -new Date().getTimezoneOffset()}
@@ -10594,7 +10625,7 @@ window.MXD=(function(){
10594
10625
 
10595
10626
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
10596
10627
  })();
10597
- </script>`;var On=`<script>
10628
+ </script>`;var tr=`<script>
10598
10629
  (function(){
10599
10630
  var LANES=[
10600
10631
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -10910,7 +10941,7 @@ window.MXD=(function(){
10910
10941
  window.addEventListener('scroll',hideTip,{passive:true});
10911
10942
  load();
10912
10943
  })();
10913
- </script>`;var Dn=`<script>
10944
+ </script>`;var ar=`<script>
10914
10945
  (function(){
10915
10946
  var showAll=document.getElementById('mx-show-all'),expanded=false;
10916
10947
  var esc=MX.esc;
@@ -11088,7 +11119,7 @@ window.MXD=(function(){
11088
11119
  }
11089
11120
  load();setInterval(load,5000);
11090
11121
  })();
11091
- </script>`;var Nn=`
11122
+ </script>`;var nr=`
11092
11123
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
11093
11124
  .mx-rt-wrap{border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-lg);background:var(--ax-surface);overflow-x:auto}
11094
11125
  .mx-rt-wrap > .mx-empty{border:0}
@@ -11129,7 +11160,7 @@ window.MXD=(function(){
11129
11160
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
11130
11161
  .mx-rt-name{max-width:100%}
11131
11162
  }
11132
- `,Hn=`<script>
11163
+ `,rr=`<script>
11133
11164
  (function(){
11134
11165
  var root=document.getElementById('mx-routines');
11135
11166
  var bar=document.getElementById('mx-rt-filter');
@@ -11256,17 +11287,92 @@ window.MXD=(function(){
11256
11287
  syncBar();
11257
11288
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
11258
11289
  })();
11259
- </script>`;var Q={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function Z(t,e,a,n,r=""){return q({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var _i=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Si=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Ei=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Bn(t){let e=He({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Be([{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">
11290
+ </script>`;var or=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],sr=`<script>
11291
+ (function(){
11292
+ var root=document.getElementById('mx-feed');
11293
+ if(!root)return;
11294
+ var esc=MX.esc,filter='all',expanded=false,events=[],local='',SHOWN=8;
11295
+ var more=document.getElementById('mx-feed-more');
11296
+ try{var saved=localStorage.getItem('mx-feed-filter');if(saved)filter=saved}catch(e){}
11297
+ var chips=Array.prototype.slice.call(document.querySelectorAll('[data-feed-filter]'));
11298
+ function pressChips(){chips.forEach(function(c){c.setAttribute('aria-pressed',String(c.dataset.feedFilter===filter))})}
11299
+ chips.forEach(function(c){c.addEventListener('click',function(){
11300
+ filter=c.dataset.feedFilter;pressChips();render();
11301
+ try{localStorage.setItem('mx-feed-filter',filter)}catch(e){}
11302
+ })});
11303
+ pressChips();
11304
+ more.addEventListener('click',function(){expanded=!expanded;render()});
11305
+
11306
+ function initials(v){return String(v||'?').split(/[-_. ]+/).slice(0,2).map(function(x){return x.charAt(0)}).join('').toUpperCase()}
11307
+ function problem(e){
11308
+ return e.type==='feed:down'||e.type==='feed:gap'||e.type==='failed'||e.type==='timeout'
11309
+ ||e.type==='lost'||(e.type==='task:completed'&&/^failed/.test(e.summary||''));
11310
+ }
11311
+ function label(e){
11312
+ if(e.kind==='announce')return 'Announcement';
11313
+ if(e.type==='feed:down')return 'Unreachable';
11314
+ if(e.type==='feed:up')return 'Back';
11315
+ if(e.type==='feed:gap')return 'Gap';
11316
+ if(e.type==='lost')return 'Lost';
11317
+ if(problem(e))return 'Failed';
11318
+ return e.kind;
11319
+ }
11320
+ function badge(e){
11321
+ var kind=problem(e)?'ax-badge--err':e.kind==='announce'?'ax-badge--warn':e.type==='feed:up'?'ax-badge--live':'ax-badge--ghost';
11322
+ return '<span class="ax-badge '+kind+'">'+esc(label(e))+'</span>';
11323
+ }
11324
+ function keep(e){
11325
+ if(filter==='peers')return e.node!==local;
11326
+ if(filter==='announce')return e.kind==='announce';
11327
+ if(filter==='problems')return problem(e);
11328
+ return true;
11329
+ }
11330
+ function render(){
11331
+ var list=events.filter(keep).slice().reverse();
11332
+ document.getElementById('mx-feed-count').textContent=MX.plural(list.length,'event');
11333
+ more.hidden=list.length<=SHOWN;
11334
+ more.textContent=expanded?'Show less':'Show all';
11335
+ if(!list.length){root.innerHTML='<div class="mx-empty">'+(events.length?'Nothing matches this filter.':'No events yet.')+'</div>';return}
11336
+ var shown=expanded?list:list.slice(0,SHOWN);
11337
+ root.innerHTML=shown.map(function(e,i){
11338
+ var who=e.agentId?'<code>'+esc(e.agentId)+'</code>':'';
11339
+ return '<button type="button" class="ax-row-card mx-item" data-feed="'+i+'">'
11340
+ +'<span class="ax-avatar '+(e.node===local?'ax-avatar--plain':'ax-avatar--blue')+'">'+esc(initials(e.node))+'</span>'
11341
+ +'<span class="ax-row-card__info"><span class="ax-name">'+esc(e.node)
11342
+ +(e.node===local?' <span class="ax-slug">this machine</span>':'')+'</span>'
11343
+ +'<span class="ax-sub">'+who+'<span class="mx-summary">'+esc(e.summary||e.type)+'</span></span></span>'
11344
+ +'<span class="ax-row-card__actions">'+badge(e)+'<span class="mx-node-meta">'+esc(MX.age(e.at))+'</span></span></button>';
11345
+ }).join('');
11346
+ root.querySelectorAll('[data-feed]').forEach(function(el){
11347
+ el.addEventListener('click',function(){
11348
+ var e=shown[Number(el.dataset.feed)];
11349
+ MX.open('Mesh event',label(e)+' on '+e.node,'<div class="mx-detail">'+MX.fields([
11350
+ ['Machine',e.node],['Kind',e.kind],['Type',e.type],['Agent',e.agentId||'-'],
11351
+ ['Time',new Date(e.at).toLocaleString()],['Record',e.ref||'-'],['Root',e.rootId]
11352
+ ])+'<pre>'+esc(e.summary||'')+'</pre></div>');
11353
+ });
11354
+ });
11355
+ }
11356
+ function load(){
11357
+ MX.get('/api/mesh/feed?limit=50').then(function(r){
11358
+ events=r.events||[];local=r.node||'';render();
11359
+ }).catch(function(e){
11360
+ root.innerHTML='<div class="mx-empty">Mesh feed unavailable: '+esc(e.message)+'</div>';
11361
+ });
11362
+ }
11363
+ load();setInterval(load,5000);
11364
+ })();
11365
+ </script>`;var X={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function K(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var nl=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],rl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],ol=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function ir(t){let e=Ge({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Xe([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
11260
11366
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
11261
- ${Si.map((i,l)=>`<button class="mx-tab" type="button" role="tab" id="mx-tab-${i.id}" aria-controls="mx-view-${i.id}" aria-selected="${l===0}" data-view="${i.id}">${i.label}</button>`).join("")}
11367
+ ${rl.map((i,l)=>`<button class="mx-tab" type="button" role="tab" id="mx-tab-${i.id}" aria-controls="mx-view-${i.id}" aria-selected="${l===0}" data-view="${i.id}">${i.label}</button>`).join("")}
11262
11368
  </div>
11263
11369
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
11264
- ${Ei.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11370
+ ${ol.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11265
11371
  </div>
11266
11372
  </div>
11267
11373
  <p id="mx-analytics-updated" class="mx-updated" aria-live="polite">Reading node histories...</p>`,n=`<div class="mx-view" id="mx-view-activity" role="tabpanel" aria-labelledby="mx-tab-activity">
11268
11374
  <section class="mx-section" aria-labelledby="mx-lanes-title">
11269
- ${Z(Q.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")}
11375
+ ${K(X.activity,"What ran","One lane per origin. Each lane is scaled to its own peak so a quiet channel stays readable next to a busy one. Select a column for the day behind it.","mx-lanes-title")}
11270
11376
  <div id="mx-lanes"><div class="mx-empty">Loading activity...</div></div>
11271
11377
  <div class="mx-axis" id="mx-axis"></div>
11272
11378
  <p class="mx-note">Coloured bars are runs that finished; the red cap on a column is the failures inside that day. Select any column for what ran that day, down to a single conversation.</p>
@@ -11274,32 +11380,32 @@ window.MXD=(function(){
11274
11380
 
11275
11381
  <div class="mx-two">
11276
11382
  <section class="mx-section" aria-labelledby="mx-origins-title">
11277
- ${Z(Q.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
11383
+ ${K(X.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
11278
11384
  <div class="mx-bars" id="mx-origins"><div class="mx-empty">Loading...</div></div>
11279
11385
  </section>
11280
11386
  <section class="mx-section" aria-labelledby="mx-causes-title">
11281
- ${Z(Q.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
11387
+ ${K(X.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
11282
11388
  <div class="mx-bars" id="mx-causes"><div class="mx-empty">Loading...</div></div>
11283
11389
  <p class="mx-note" id="mx-cause-note"></p>
11284
11390
  </section>
11285
11391
  </div>
11286
11392
 
11287
11393
  <section class="mx-section" aria-labelledby="mx-scatter-title">
11288
- ${Z(Q.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")}
11394
+ ${K(X.effort,"Effort against output","Every recurring job, plotted as runtime spent against tokens produced on its successful runs. Both axes are logarithmic.","mx-scatter-title")}
11289
11395
  <div class="mx-scatter" id="mx-scatter"><div class="mx-empty">Loading jobs...</div></div>
11290
11396
  <div class="mx-legend" id="mx-scatter-legend"></div>
11291
11397
  <p class="mx-note">Bubble size is the number of runs. Anything not healthy is labelled on the chart; select it for the attempt history behind the verdict.</p>
11292
11398
  </section>
11293
11399
  </div>`,r=`<div class="mx-view" id="mx-view-lifetime" role="tabpanel" aria-labelledby="mx-tab-lifetime" hidden>
11294
11400
  <section class="mx-section" aria-labelledby="mx-threads-title">
11295
- ${Z(Q.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")}
11401
+ ${K(X.lifetime,"Thread lifetimes","A thread is one agent talking on one channel in one conversation. The bar is its real first-to-last span; each tick is a session cut. Select one for its turns, tokens and time.","mx-threads-title")}
11296
11402
  <div class="mx-chips" id="mx-thread-chips"></div>
11297
11403
  <div id="mx-threads"><div class="mx-empty">Loading threads...</div></div>
11298
11404
  <p class="mx-note">Select a thread to walk its runs, then a run to see which tools it touched. Grey ticks are stale cuts, amber ticks are context-full cuts.</p>
11299
11405
  </section>
11300
11406
 
11301
11407
  <section class="mx-section" aria-labelledby="mx-rot-title">
11302
- ${Z(Q.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
11408
+ ${K(X.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
11303
11409
  <div class="mx-bars" id="mx-rotations"><div class="mx-empty">Loading...</div></div>
11304
11410
  <p class="mx-note" id="mx-rot-note"></p>
11305
11411
  </section>
@@ -11307,31 +11413,39 @@ window.MXD=(function(){
11307
11413
  <p id="mx-updated" class="mx-updated" aria-live="polite">Connecting to the fleet...</p>
11308
11414
 
11309
11415
  <section class="mx-section" aria-labelledby="mx-auto-title">
11310
- ${Z(Q.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>')}
11416
+ ${K(X.schedules,"Today's automations","Persisted attempts are authoritative. Select a schedule to inspect its latest result and runtime.","mx-auto-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-run-count">0 schedules</span><button class="ax-btn ax-btn--ghost mx-show-all" id="mx-show-all" type="button" hidden>Show all</button></div>')}
11311
11417
  <div class="ax-stack" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
11312
11418
  </section>
11313
11419
 
11314
11420
  <section class="mx-section" aria-labelledby="mx-routines-title">
11315
- ${Z(Q.routines,"Routines","Everything that runs on its own: schedules and cron- or event-triggered workflows, per node. Flags mark routines that keep failing, went quiet, never ran, or sat disabled.","mx-routines-title",'<span class="ax-tab-count" id="mx-rt-count">0 routines</span>')}
11421
+ ${K(X.routines,"Routines","Everything that runs on its own: schedules and cron- or event-triggered workflows, per node. Flags mark routines that keep failing, went quiet, never ran, or sat disabled.","mx-routines-title",'<span class="ax-tab-count" id="mx-rt-count">0 routines</span>')}
11316
11422
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
11317
- ${_i.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11423
+ ${nl.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11318
11424
  </div>
11319
11425
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
11320
11426
  </section>
11321
11427
 
11428
+ <section class="mx-section" aria-labelledby="mx-feed-title">
11429
+ ${K(X.feed,"Mesh feed","The newest events from this machine and every machine it follows. Unreachable machines and announcements show here too. Select an event for its details.","mx-feed-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-feed-count">0 events</span><button class="ax-btn ax-btn--ghost" id="mx-feed-more" type="button" hidden>Show all</button></div>')}
11430
+ <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
11431
+ ${or.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11432
+ </div>
11433
+ <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
11434
+ </section>
11435
+
11322
11436
  <div class="mx-columns">
11323
11437
  <section class="mx-section" aria-labelledby="mx-active-title">
11324
- ${Z(Q.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>')}
11438
+ ${K(X.activity,"Activity provenance","Who initiated current work and where it is running.","mx-active-title",'<span class="ax-tab-count" id="mx-active-count">0 active</span>')}
11325
11439
  <div class="ax-stack" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
11326
11440
  </section>
11327
11441
  <section class="mx-section" aria-labelledby="mx-nodes-title">
11328
- ${Z(Q.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
11442
+ ${K(X.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
11329
11443
  <div class="ax-stack" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
11330
11444
  </section>
11331
11445
  </div>
11332
11446
 
11333
11447
  <section class="mx-section" aria-labelledby="mx-agents-title">
11334
- ${Z(Q.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>')}
11448
+ ${K(X.agents,"Agents and skills","Runtime, model, installed skills, and task totals by node.","mx-agents-title",'<span class="ax-tab-count" id="mx-agent-count">0 agents</span>')}
11335
11449
  <div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
11336
11450
  </section>
11337
11451
  </div>`,s=`${e}<main class="mx-content">
@@ -11347,7 +11461,7 @@ window.MXD=(function(){
11347
11461
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
11348
11462
  </header>
11349
11463
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
11350
- </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ln+Nn,scripts:Rn+Ti+Pn+On+Hn+Dn})}var Ti=`<script>
11464
+ </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Qn+nr,scripts:Zn+sl+er+tr+rr+ar+sr})}var sl=`<script>
11351
11465
  (function(){
11352
11466
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
11353
11467
  var range=document.getElementById('mx-range');
@@ -11375,7 +11489,7 @@ window.MXD=(function(){
11375
11489
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
11376
11490
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
11377
11491
  })();
11378
- </script>`;async function zn(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Ci(s,e.days)}function Ci(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,p=0,m=0,h=0,y=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 c of T.days){let u=n.get(c.day)||{day:c.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let f of["cron","workflow","direct"])u[f][0]+=c[f]?.[0]||0,u[f][1]+=c[f]?.[1]||0;n.set(c.day,u)}for(let c of T.origins){let u=r.get(c.channel)||{channel:c.channel,runs:0,errors:0,hours:0};u.runs+=c.runs,u.errors+=c.errors,u.hours+=c.hours,r.set(c.channel,u)}for(let c of T.causes){let u=o.get(c.cause)||{cause:c.cause,count:0,agents:[],example:""};u.count+=c.count;for(let f of c.agents)u.agents.includes(f)||u.agents.push(f);u.example||(u.example=c.example),o.set(c.cause,u)}for(let c of T.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=T.rotations.total,p+=T.rotations.tokenSum||0,m+=T.rotations.tokenSamples||0,h=Math.max(h,T.rotations.maxTokens),y+=T.retention.traces,S+=T.retention.tracesWithSteps;for(let c of T.jobs)i.push({...c,node:E.name,nodeUrl:E.url});for(let c of T.threads)l.push({...c,node:E.name,nodeUrl:E.url})}let w=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:w.length?Math.min(...w):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:i.sort((E,T)=>T.hours-E.hours),threads:l.sort((E,T)=>T.lastAt-T.firstAt-(E.lastAt-E.firstAt)||T.runs-E.runs),rotations:{total:d,byReason:[...s.entries()].map(([E,T])=>({reason:E,count:T})).sort((E,T)=>T.count-E.count),tokenSum:p,tokenSamples:m,maxTokens:h},retention:{traces:y,tracesWithSteps:S}}}async function qn(t,e,a,n){let r=a.replace(/\/+$/,""),o=e.find(i=>i.url.replace(/\/+$/,"")===r);if(!o){t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"node not in dashboard allowlist",target:r}));return}let s={Accept:"application/json"};o.token&&(s.Authorization=`Bearer ${o.token}`);try{let i=await fetch(r+n,{headers:s}),l=await i.text();t.writeHead(i.status,{"Content-Type":"application/json; charset=utf-8"}),t.end(l)}catch(i){t.writeHead(502,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:i?.message||"upstream fetch failed"}))}}async function Fn(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Ai(s,e.day)}function Ai(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function Un(t={}){let e=`
11492
+ </script>`;async function lr(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return il(s,e.days)}function il(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,p=0,u=0,f=0,y=0,w=0;for(let{node:g,data:S}of t)if(S){a.runs+=S.totals.runs,a.errors+=S.totals.errors,a.hours+=S.totals.hours,a.agents+=S.totals.agents,a.threads+=S.totals.threads;for(let c of S.days){let m=n.get(c.day)||{day:c.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])m[h][0]+=c[h]?.[0]||0,m[h][1]+=c[h]?.[1]||0;n.set(c.day,m)}for(let c of S.origins){let m=r.get(c.channel)||{channel:c.channel,runs:0,errors:0,hours:0};m.runs+=c.runs,m.errors+=c.errors,m.hours+=c.hours,r.set(c.channel,m)}for(let c of S.causes){let m=o.get(c.cause)||{cause:c.cause,count:0,agents:[],example:""};m.count+=c.count;for(let h of c.agents)m.agents.includes(h)||m.agents.push(h);m.example||(m.example=c.example),o.set(c.cause,m)}for(let c of S.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=S.rotations.total,p+=S.rotations.tokenSum||0,u+=S.rotations.tokenSamples||0,f=Math.max(f,S.rotations.maxTokens),y+=S.retention.traces,w+=S.retention.tracesWithSteps;for(let c of S.jobs)i.push({...c,node:g.name,nodeUrl:g.url});for(let c of S.threads)l.push({...c,node:g.name,nodeUrl:g.url})}let T=t.filter(g=>g.data).map(g=>g.data.since).filter(g=>Number.isFinite(g));return{generatedAt:Date.now(),windowDays:e,since:T.length?Math.min(...T):Date.now()-e*864e5,nodes:t.map(g=>({name:g.node.name,url:g.node.url,ok:!!g.data,error:g.error,runs:g.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((g,S)=>g.day.localeCompare(S.day)),origins:[...r.values()].map(g=>({...g,hours:Math.round(g.hours*100)/100})).sort((g,S)=>S.runs-g.runs),causes:[...o.values()].sort((g,S)=>S.count-g.count),jobs:i.sort((g,S)=>S.hours-g.hours),threads:l.sort((g,S)=>S.lastAt-S.firstAt-(g.lastAt-g.firstAt)||S.runs-g.runs),rotations:{total:d,byReason:[...s.entries()].map(([g,S])=>({reason:g,count:S})).sort((g,S)=>S.count-g.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:y,tracesWithSteps:w}}}async function dr(t,e,a,n){let r=a.replace(/\/+$/,""),o=e.find(i=>i.url.replace(/\/+$/,"")===r);if(!o){t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"node not in dashboard allowlist",target:r}));return}let s={Accept:"application/json"};o.token&&(s.Authorization=`Bearer ${o.token}`);try{let i=await fetch(r+n,{headers:s}),l=await i.text();t.writeHead(i.status,{"Content-Type":"application/json; charset=utf-8"}),t.end(l)}catch(i){t.writeHead(502,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:i?.message||"upstream fetch failed"}))}}async function cr(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return ll(s,e.day)}function ll(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function pr(t={}){let e=`
11379
11493
  <select id="boardPicker" title="Switch board"></select>
11380
11494
  <div class="search">
11381
11495
  <span class="icon">\u2315</span>
@@ -11476,7 +11590,7 @@ window.MXD=(function(){
11476
11590
  </footer>
11477
11591
  </div>
11478
11592
  </div>
11479
- <script src="/sortable.min.js"></script>`;return $({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Mi,scripts:`<script>${Ii}</script>`,headExtras:`<script>
11593
+ <script src="/sortable.min.js"></script>`;return $({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:dl,scripts:`<script>${cl}</script>`,headExtras:`<script>
11480
11594
  // The boards page has its own connection dot + wants body height:100%
11481
11595
  // for the full-viewport kanban layout. Inject the dot into the topbar
11482
11596
  // and override body height at runtime so the shared shell doesn't
@@ -11492,7 +11606,7 @@ window.MXD=(function(){
11492
11606
  right.insertBefore(dot, right.firstChild);
11493
11607
  }
11494
11608
  });
11495
- </script>`})}var Mi=`
11609
+ </script>`})}var dl=`
11496
11610
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
11497
11611
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
11498
11612
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -11745,7 +11859,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
11745
11859
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
11746
11860
  .draft-box .draft-row .hint.err { color: var(--red); }
11747
11861
  .draft-box .draft-row .hint.ok { color: var(--green); }
11748
- `,Ii=`
11862
+ `,cl=`
11749
11863
  'use strict';
11750
11864
  const state = {
11751
11865
  boards: [], current: null, items: {},
@@ -12798,9 +12912,9 @@ function appendEvents(events) {
12798
12912
  }
12799
12913
 
12800
12914
  loadBoards().catch(e => toast('Init failed: ' + e.message));
12801
- `;function Wn(t={}){let a=`<h1>Plain-English glossary</h1>
12915
+ `;function ur(t={}){let a=`<h1>Plain-English glossary</h1>
12802
12916
  <p class="lead">What the terms on the dashboard mean. Schema keys (shown in the pill on the right of each term) are what you'd write in <code>agentx.json</code> \u2014 the dashboard just relabels them for readability.</p>
12803
- ${jn.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:`${ge.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:$i})}var $i=`
12917
+ ${Yn.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${P(n.alias)}</span>`:"";return`<article class="term"><h3>${P(n.term)}${r}</h3><p>${P(n.definition)}</p></article>`}).join("")}`;return $({title:`${be.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:pl})}var pl=`
12804
12918
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
12805
12919
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
12806
12920
  .lead {
@@ -12830,7 +12944,7 @@ article.term .alias {
12830
12944
  }
12831
12945
  article.term p {
12832
12946
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
12833
- }`;function Gn(t={}){let e=`<div class="ax-wf__root">
12947
+ }`;function mr(t={}){let e=`<div class="ax-wf__root">
12834
12948
  <aside class="ax-wf__list">
12835
12949
  <header>
12836
12950
  <h2>Workflows</h2>
@@ -12907,7 +13021,7 @@ article.term p {
12907
13021
  </aside>
12908
13022
  </div>
12909
13023
 
12910
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return $({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ji,scripts:`<script>${ve({workflowHealth:Ut})}${Li}</script>`})}var ji=`
13024
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return $({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ul,scripts:`<script>${ue({workflowHealth:ra})}${ml}</script>`})}var ul=`
12911
13025
  .ax-wf__root {
12912
13026
  display: grid;
12913
13027
  grid-template-columns: 340px 1fr;
@@ -13291,7 +13405,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13291
13405
  font-size: 12px; z-index: 50;
13292
13406
  }
13293
13407
  .hint { color: var(--ax-muted); font-size: 11px; }
13294
- `,Li=`
13408
+ `,ml=`
13295
13409
  (() => {
13296
13410
  const $ = (sel) => document.querySelector(sel)
13297
13411
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -14080,7 +14194,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14080
14194
  setInterval(refresh, 15000)
14081
14195
  })
14082
14196
  })();
14083
- `;function Xn(t={}){let e=`<div class="ax-proc__root">
14197
+ `;function fr(t={}){let e=`<div class="ax-proc__root">
14084
14198
  <header class="ax-proc__header">
14085
14199
  <h1>Procedures</h1>
14086
14200
  <p class="hint">Reusable building blocks workflows compose. See <a href="/admin/wiki/architecture/three-tier" target="_blank">three-tier model</a> for how this fits with System and Processes.</p>
@@ -14124,7 +14238,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14124
14238
  <p class="hint">AgentX is layered: <strong>System</strong> (agents, channels, mesh) \u2192 <strong>Processes</strong> (workflows that turn intent into work) \u2192 <strong>Procedures</strong> (this page: reusable steps a process composes). Higher tiers depend on lower; never the reverse.</p>
14125
14239
  <p class="hint">Adding a new procedure is a code change (a new <code>action.builtin</code> module under <code>src/actions/builtin/</code> or a new template YAML in <code>src/workflows/templates/</code>) \u2014 not a UI flow. This page is the read-only catalog.</p>
14126
14240
  </section>
14127
- </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ri,scripts:`<script>${Pi}</script>`})}var Ri=`
14241
+ </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:fl,scripts:`<script>${hl}</script>`})}var fl=`
14128
14242
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
14129
14243
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
14130
14244
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -14150,7 +14264,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14150
14264
  .ax-proc__req { display: inline-block; padding: 1px 6px; font-size: 10px; font-family: var(--ax-mono); border: 1px solid color-mix(in oklch, var(--ax-warn, #f59e0b) 40%, var(--ax-border)); border-radius: 3px; color: var(--ax-warn, #f59e0b); }
14151
14265
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
14152
14266
  .ax-proc__link:hover { text-decoration: underline; }
14153
- `,Pi=`
14267
+ `,hl=`
14154
14268
  (function(){
14155
14269
  function $(sel){ return document.querySelector(sel) }
14156
14270
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -14250,7 +14364,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14250
14364
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
14251
14365
  else bootAll()
14252
14366
  })();
14253
- `;function Kn(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14367
+ `;function hr(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14254
14368
  data-task-id="${P(t.taskId)}"
14255
14369
  data-agent-id="${P(t.agentId)}"
14256
14370
  data-node-url="${P(t.nodeUrl)}"
@@ -14293,7 +14407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14293
14407
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
14294
14408
  </div>
14295
14409
  </footer>
14296
- </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Oi,scripts:`<script>${Di}</script>`})}var Oi=`
14410
+ </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:gl,scripts:`<script>${xl}</script>`})}var gl=`
14297
14411
  /* The shell gives <main> no padding, so page content butted straight against
14298
14412
  the sticky topbar. Breathe. */
14299
14413
  .ax-task-page {
@@ -14435,7 +14549,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14435
14549
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
14436
14550
  }
14437
14551
 
14438
- `,Di=`
14552
+ `,xl=`
14439
14553
  (function () {
14440
14554
  var root = document.querySelector('.ax-task-page');
14441
14555
  if (!root) return;
@@ -14820,7 +14934,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14820
14934
  });
14821
14935
 
14822
14936
  })();
14823
- `;function Jn(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14937
+ `;function gr(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14824
14938
  data-agent-id="${P(t.agentId)}"
14825
14939
  data-agent-name="${P(e)}"
14826
14940
  data-node-url="${P(t.nodeUrl)}">
@@ -14849,7 +14963,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14849
14963
  <div class="ax-history__list" id="hist-list">
14850
14964
  <div class="ax-history__empty">loading\u2026</div>
14851
14965
  </div>
14852
- </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ni,scripts:`<script>${Hi}</script>`})}var Ni=`
14966
+ </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vl,scripts:`<script>${bl}</script>`})}var vl=`
14853
14967
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
14854
14968
  flush against the sticky topbar. */
14855
14969
  .ax-history {
@@ -14901,7 +15015,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14901
15015
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
14902
15016
  }
14903
15017
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
14904
- `,Hi=`
15018
+ `,bl=`
14905
15019
  (function () {
14906
15020
  var root = document.querySelector('.ax-history');
14907
15021
  if (!root) return;
@@ -15001,11 +15115,24 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15001
15115
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15002
15116
  });
15003
15117
  })();
15004
- `;function Yn(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?j(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return ke(t,e,l=>Vn(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:zi(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?ke(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return j(e,200,{ok:!0,emission:d})}):j(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?j(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?ke(t,e,l=>{try{let d=a.layouts.save(s,l);return j(e,200,{layout:d})}catch(d){return j(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?ke(t,e,l=>{let d=nt.safeParse(l);if(!d.success)return j(e,200,{ok:!1,issues:d.error.issues.map(m=>({path:m.path.join("."),message:m.message}))});let p=rt(d.data).map(m=>({path:"",message:m}));return j(e,200,{ok:p.length===0,issues:p,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?j(e,200,{workflow:l}):j(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return ke(t,e,p=>Vn(e,a,p,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),j(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return j(e,404,{error:"unknown workflows endpoint",path:n})}var Bi=["mesh"];function Vn(t,e,a,n){let r=nt.safeParse(a);if(!r.success)return j(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=rt(o);if(s.length>0)return j(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return j(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return j(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,d=e.store.get(n.id);if(d)for(let p of Bi)!(p in l)&&p in d&&(o[p]=d[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),p=l?.yamlPath,m=!!p||/yaml round-trip failed/.test(d);return j(t,m?409:500,{error:m?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:m?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),j(t,200,{workflow:i})}function zi(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",m=a.runs.list({workflowId:d,limit:l});if(!p)return j(e,200,{runs:m});let h=m.map(y=>({id:y.id,workflowId:y.workflowId,workflowVersion:y.workflowVersion,homeNode:y.homeNode,status:y.status,pending:y.pending,entityRef:y.entityRef,history:(y.history||[]).slice(-5),parentRunId:y.parentRunId,parentNodeId:y.parentNodeId,rootRunId:y.rootRunId,depth:y.depth,createdAt:y.createdAt,updatedAt:y.updatedAt}));return j(e,200,{runs:h})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return j(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return ke(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?j(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?j(e,200,{ok:!0,runId:l,status:p}):j(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return qi(t,e,a,l);let d=a.runs.get(l);return d?j(e,200,{run:d}):j(e,404,{error:"run not found"})}return j(e,404,{error:"unknown runs endpoint"})}function qi(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)}
15118
+ `;function vr(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?L(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return Ee(t,e,l=>xr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:wl(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return L(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Ee(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return L(e,200,{ok:!0,emission:d})}):L(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?L(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Ee(t,e,l=>{try{let d=a.layouts.save(s,l);return L(e,200,{layout:d})}catch(d){return L(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ee(t,e,l=>{let d=mt.safeParse(l);if(!d.success)return L(e,200,{ok:!1,issues:d.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=ft(d.data).map(u=>({path:"",message:u}));return L(e,200,{ok:p.length===0,issues:p,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?L(e,200,{workflow:l}):L(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ee(t,e,p=>xr(e,a,p,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),L(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return L(e,404,{error:"unknown workflows endpoint",path:n})}var yl=["mesh"];function xr(t,e,a,n){let r=mt.safeParse(a);if(!r.success)return L(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=ft(o);if(s.length>0)return L(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return L(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return L(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,d=e.store.get(n.id);if(d)for(let p of yl)!(p in l)&&p in d&&(o[p]=d[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(d);return L(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),L(t,200,{workflow:i})}function wl(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:d,limit:l});if(!p)return L(e,200,{runs:u});let f=u.map(y=>({id:y.id,workflowId:y.workflowId,workflowVersion:y.workflowVersion,homeNode:y.homeNode,status:y.status,pending:y.pending,entityRef:y.entityRef,history:(y.history||[]).slice(-5),parentRunId:y.parentRunId,parentNodeId:y.parentNodeId,rootRunId:y.rootRunId,depth:y.depth,createdAt:y.createdAt,updatedAt:y.updatedAt}));return L(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Ee(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?L(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?L(e,200,{ok:!0,runId:l,status:p}):L(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return kl(t,e,a,l);let d=a.runs.get(l);return d?L(e,200,{run:d}):L(e,404,{error:"run not found"})}return L(e,404,{error:"unknown runs endpoint"})}function kl(t,e,a,n){let r=a.runs.get(n);if(!r)return L(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
15119
+
15120
+ `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
15121
+
15122
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==d&&(d=u.updatedAt,i(u))},2e3);return!0}function Ee(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){L(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{L(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{L(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>L(e,400,{error:"body read failed",message:r.message})),!0}function L(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{deflateSync as _l}from"zlib";var El=[41,121,255],Sl=[255,255,255],br=new Map;function Ot(t){let e=br.get(t);return e||(e=Cl(t,Tl(t)),br.set(t,e)),e}function Tl(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,d=i*i+l*l<=r*r?Sl:El;a.set(d,o*e+1+s*3)}return a}function Cl(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Nt("IHDR",a),Nt("IDAT",_l(e)),Nt("IEND",Buffer.alloc(0))])}function Nt(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(Ml(n)),Buffer.concat([a,n,r])}var Al=Array.from({length:256},(t,e)=>{let a=e;for(let n=0;n<8;n++)a=a&1?3988292384^a>>>1:a>>>1;return a>>>0});function Ml(t){let e=4294967295;for(let a of t)e=Al[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function nt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Il(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:nt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:nt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:nt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function $l(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:nt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Ll=/^\/api\/app\/tasks\/(cancel|followup)$/;async function yr(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let y=jl(s.searchParams.get("timezone")),w=await o.snapshot({date:Rl(y),timezone:y});return a==="/api/app/activity"?re(e,200,{ts:w.ts,tasks:$l(w.nodes)}):re(e,200,{ts:w.ts,nodes:w.nodes.map(Il)})}if(n==="GET"&&a==="/api/app/approvals")return re(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Ll);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let d;try{d=await je(t)}catch(y){return re(e,400,{error:y.message})}let p=Le(d.node);if(!p)return re(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let y=Le(d.taskId);if(!y)return re(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(y)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Le(d.message);if(!T)return re(e,400,{error:"message is required"});f=await o.nodePost(p,w,{message:T,sender:u})}}else if(a==="/api/app/nodes/restart")f=await o.nodePost(p,d.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")f=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let y=Le(d.cronId);if(!y||typeof d.enabled!="boolean")return re(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(y)}/enabled`,{enabled:d.enabled})}else{let y=Le(d.key),w=d.action;if(!y||w!=="yes"&&w!=="no"&&w!=="later")return re(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,y,w,u)}return re(e,f.status,f.body)}function Le(t){return typeof t=="string"?t.trim():""}function jl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Rl(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function je(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function re(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Pl=2048,wr=/^[A-Za-z0-9_-]{8,256}$/;async function kr(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return oe(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(y=>y.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return oe(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return oe(e,404,{error:"not found"});if(!s||l)return oe(e,503,{error:l});let d;try{d=await je(t)}catch(y){return oe(e,400,{error:y.message})}let p=Nl(d.endpoint,o.allowedHosts);if(!p){let y="";try{y=new URL(String(d.endpoint)).hostname}catch{}return oe(e,400,{error:`not a known push service${y?`: ${y}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return oe(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=d.keys?.p256dh,f=d.keys?.auth;return typeof u!="string"||!wr.test(u)||typeof f!="string"||!wr.test(f)?oe(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?oe(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),oe(e,200,{ok:!0}))}function Nl(t,e){if(typeof t!="string"||t.length>Pl)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function oe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ol=50;function Dl(t){let e={channel:"app",chatId:t.chatId};return t.node==="local"?{path:"/task",body:{agent:t.agent,message:t.message,stream:!0,context:e}}:{path:"/mesh/task",body:{peer:t.node,agent:t.agent,message:t.message,stream:!0,context:e}}}async function _r(t,e,a,n){let{path:r,body:o}=Dl(e),s="",i=[],l=new Map,d=(p,u,f)=>{let{cleanText:y,ui:w}=p==="done"?sa(u):{cleanText:u,ui:void 0},T=Bl(w);return{status:p,text:y,tools:i,...T?{ui:T}:{},...f?{error:f}:{}}};try{let p=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let u=await p.json().then(f=>f?.error).catch(()=>"");return d("error",s,u||`AgentX answered HTTP ${p.status}.`)}for await(let u of zl(p.body)){n(u.event,u.data);let f=u.data??{};if(u.event==="text"&&typeof f.text=="string")s+=f.text;else if(u.event==="tool"&&f.status==="start"&&i.length<Ol){let y={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(y),f.id&&l.set(String(f.id),y)}else if(u.event==="tool"&&f.status==="result"&&f.error===!0&&l.has(String(f.id)))l.get(String(f.id)).error=!0;else{if(u.event==="done")return d("done",typeof f.content=="string"&&f.content?f.content:s);if(u.event==="error")return d("error",s,Hl(f.error))}}return a.aborted?d("stopped",s):d("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?d("stopped",s):d("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function Hl(t){let e=String(t||"The agent could not answer.");return e.startsWith("__queued__")?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function Bl(t){if(!t)return;let e=r=>/^https?:\/\//i.test(r)&&r.length<=2048,a={},n=(t.buttons??[]).filter(r=>e(r.url)).slice(0,8).map(r=>({label:r.label.slice(0,80),url:r.url}));return n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(r=>r.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}}),Object.keys(a).length?a:void 0}async function*zl(t){let e=t.getReader(),a=new TextDecoder,n="";try{for(;;){let{done:r,value:o}=await e.read();if(r)break;n+=a.decode(o,{stream:!0}).replace(/\r\n/g,`
15123
+ `);let s;for(;(s=n.indexOf(`
15124
+
15125
+ `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
15126
+ `))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&d.push(p.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
15127
+ `))}}catch{}}}}finally{e.releaseLock()}}var rt=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];orphaned=!1;listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
15128
+ data: ${JSON.stringify(s)}
15129
+
15130
+ `)},r=setInterval(()=>{a()&&e.write(`: ping
15005
15131
 
15006
- `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=m=>{if(!o)try{e.write(`data: ${JSON.stringify(m)}
15132
+ `)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};var Sr=8e3,ql=/^[A-Za-z0-9_.:-]{1,64}$/,Se=new Map;async function Tr(t,e,a,n,r,o){if(a!=="/api/app/agents"&&a!=="/api/app/chat"&&a!=="/api/app/chat/stop"&&a!=="/api/app/chat/attach"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;if(n==="GET"&&a==="/api/app/agents")return O(e,200,{nodes:await Cr(o)});let s=o.store();if(!s)return O(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return O(e,200,{conversations:s.list(r.id)});let i=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(i){let d=s.get(r.id,decodeURIComponent(i[1]));if(!d)return O(e,404,{error:"no such conversation"});let p=Se.get(d.id);return O(e,200,{...d,running:!!p,...p?{partial:{text:p.text,tools:p.tools}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=s.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=d&&Se.get(d.id);if(!d||!p)return O(e,404,{error:"nothing is running in this conversation"});Ar(e);let{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g}=d;return e.write(Dt("conversation",{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g})),e.write(Dt("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return O(e,404,{error:"not found"});let l;try{l=await je(t,64*1024)}catch(d){return O(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=s.get(r.id,String(l.conversationId??""));if(!d)return O(e,404,{error:"no such conversation"});let p=Se.get(d.id);return p?(p.ac.abort(),Ht(d,o,r.name),O(e,200,{stopped:!0})):await Ht(d,o,r.name)?O(e,200,{stopped:!0}):O(e,404,{error:"nothing is running in this conversation"})}return await Fl(e,l,r,s,o),!0}function Ul(t,e,a){let n=Te(e.url),r=new Set,o=[];for(let s of t){let i=Te(s.url),l=a.find(u=>Te(u.peerUrl)===i);l&&r.add(l.peer);let d=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Cr(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Ul(e.nodes,t.daemon,a)}async function Fl(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Sr){O(t,400,{error:`message must be 1\u2013${Sr} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){O(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!ql.test(T)){O(t,400,{error:"pick an agent"});return}let g=(await Cr(r)).find(c=>c.target===w);if(!g){O(t,400,{error:`unknown node "${w}"`});return}if(!g.online){O(t,409,{error:`${g.name} is offline`});return}let S=g.agents.find(c=>c.id===T);if(!S){O(t,400,{error:`no agent "${T}" on ${g.name}`});return}s=n.create(a.id,{node:w,nodeName:g.name,agent:T,agentName:S.name},o)}if(Se.has(s.id)){O(t,409,{error:"The agent is still answering in this conversation."});return}let i=new rt(r.orphanLimitMs??18e5);Se.set(s.id,i),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()});let{id:l,title:d,node:p,nodeName:u,agent:f,agentName:y}=s;Ar(t),t.write(Dt("conversation",{id:l,title:d,node:p,nodeName:u,agent:f,agentName:y})),i.attach(t);try{let w=await _r(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`},i.ac.signal,(T,g)=>i.broadcast(T,g));i.orphaned&&(w.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ht(s,r,a.name)),n.append(a.id,l,{role:"assistant",content:w.text,status:w.status,at:Date.now(),...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{},...w.tools.length?{tools:w.tools}:{}}),i.broadcast("final",{status:w.status,content:w.text,...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{}})}finally{Se.delete(l),i.finish()}}function Ar(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Dt(t,e){return`event: ${t}
15133
+ data: ${JSON.stringify(e)}
15007
15134
 
15008
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let m=a.runs.get(n);m&&m.updatedAt!==d&&(d=m.updatedAt,i(m))},2e3);return!0}function ke(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){j(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{j(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{j(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>j(e,400,{error:"body read failed",message:r.message})),!0}function j(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{deflateSync as Fi}from"zlib";var Ui=[41,121,255],Wi=[255,255,255],Qn=new Map;function Ct(t){let e=Qn.get(t);return e||(e=Xi(t,Gi(t)),Qn.set(t,e)),e}function Gi(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,d=i*i+l*l<=r*r?Wi:Ui;a.set(d,o*e+1+s*3)}return a}function Xi(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Tt("IHDR",a),Tt("IDAT",Fi(e)),Tt("IEND",Buffer.alloc(0))])}function Tt(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(Ji(n)),Buffer.concat([a,n,r])}var Ki=Array.from({length:256},(t,e)=>{let a=e;for(let n=0;n<8;n++)a=a&1?3988292384^a>>>1:a>>>1;return a>>>0});function Ji(t){let e=4294967295;for(let a of t)e=Ki[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function Ve(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Vi(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:Ve(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:Ve(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:Ve(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Yi(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:Ve(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Qi=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Zn(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let y=Zi(s.searchParams.get("timezone")),S=await o.snapshot({date:el(y),timezone:y});return a==="/api/app/activity"?ne(e,200,{ts:S.ts,tasks:Yi(S.nodes)}):ne(e,200,{ts:S.ts,nodes:S.nodes.map(Vi)})}if(n==="GET"&&a==="/api/app/approvals")return ne(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Qi);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let d;try{d=await tl(t)}catch(y){return ne(e,400,{error:y.message})}let p=Ce(d.node);if(!p)return ne(e,400,{error:"node is required"});let m=`operator (phone: ${r})`,h;if(i){let y=Ce(d.taskId);if(!y)return ne(e,400,{error:"taskId is required"});let S=`/api/tasks/${encodeURIComponent(y)}/${i[1]}`;if(i[1]==="cancel")h=await o.nodePost(p,S,{reason:`cancelled by ${m}`});else{let w=Ce(d.message);if(!w)return ne(e,400,{error:"message is required"});h=await o.nodePost(p,S,{message:w,sender:m})}}else if(a==="/api/app/nodes/restart")h=await o.nodePost(p,d.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")h=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let y=Ce(d.cronId);if(!y||typeof d.enabled!="boolean")return ne(e,400,{error:"cronId and enabled (true or false) are required"});h=await o.nodePost(p,`/crons/${encodeURIComponent(y)}/enabled`,{enabled:d.enabled})}else{let y=Ce(d.key),S=d.action;if(!y||S!=="yes"&&S!=="no"&&S!=="later")return ne(e,400,{error:"key and action (yes, no or later) are required"});h=await o.decide(p,y,S,m)}return ne(e,h.status,h.body)}function Ce(t){return typeof t=="string"?t.trim():""}function Zi(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function el(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function tl(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function ne(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var er=`
15135
+ `}async function Ht(t,e,a){try{let n=Te(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Te(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Te(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Te(t){return t.replace(/\/+$/,"")}function O(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Mr=`
15009
15136
  (function () {
15010
15137
  var fleetPanel = document.getElementById('panel-fleet');
15011
15138
  var activityPanel = document.getElementById('panel-activity');
@@ -15249,7 +15376,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15249
15376
  setInterval(refresh, 15000);
15250
15377
  refresh();
15251
15378
  })();
15252
- `;var tr=`
15379
+ `;var Ir=`
15253
15380
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
15254
15381
  .fx-head h2 { margin: 4px 0 0; }
15255
15382
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -15306,7 +15433,769 @@ details[open] > summary::before { transform: rotate(90deg); }
15306
15433
  }
15307
15434
  .fx-error:empty { display: none; }
15308
15435
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
15309
- `;var al="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})();</script>";function At(t){return`<meta charset="utf-8">
15436
+ `;var $r=`
15437
+ (function () {
15438
+ var panel = document.getElementById('panel-alerts');
15439
+ if (!panel) return;
15440
+ panel.innerHTML = '<h2>Alerts</h2>' +
15441
+ '<div class="fx-card"><div class="fx-row"><h3>Notifications on this phone</h3><span id="al-pill" class="fx-pill"></span></div>' +
15442
+ '<p id="al-text" class="fx-muted">Checking\u2026</p>' +
15443
+ '<div class="fx-row fx-gap"><button type="button" id="al-btn" class="fx-btn fx-primary" hidden></button></div>' +
15444
+ '<p id="al-error" class="fx-error fx-bad" role="alert"></p></div>' +
15445
+ '<h3 class="fx-sub">Recent</h3><ul id="al-list" class="fx-list"></ul>';
15446
+ var pill = document.getElementById('al-pill');
15447
+ var text = document.getElementById('al-text');
15448
+ var btn = document.getElementById('al-btn');
15449
+ var err = document.getElementById('al-error');
15450
+ var list = document.getElementById('al-list');
15451
+ var server = null;
15452
+ var busy = false;
15453
+
15454
+ function esc(s) {
15455
+ return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
15456
+ return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
15457
+ });
15458
+ }
15459
+ function ago(ms) {
15460
+ var s = Math.max(0, (Date.now() - ms) / 1000);
15461
+ if (s < 60) return 'just now';
15462
+ if (s < 3600) return Math.round(s / 60) + ' min ago';
15463
+ if (s < 86400) return Math.round(s / 3600) + ' h ago';
15464
+ return Math.round(s / 86400) + ' d ago';
15465
+ }
15466
+ function api(method, path, body) {
15467
+ return fetch(path, {
15468
+ method: method,
15469
+ credentials: 'same-origin',
15470
+ headers: body ? { 'Content-Type': 'application/json' } : {},
15471
+ body: body ? JSON.stringify(body) : undefined,
15472
+ }).then(function (r) {
15473
+ if (r.status === 401) { location.reload(); throw new Error('not paired'); }
15474
+ return r.json().catch(function () { return {}; }).then(function (b) {
15475
+ if (!r.ok) throw new Error(b.error || ('HTTP ' + r.status));
15476
+ return b;
15477
+ });
15478
+ });
15479
+ }
15480
+ // The VAPID key arrives base64url-encoded; the Push API wants bytes.
15481
+ function keyBytes(b64) {
15482
+ var s = b64.replace(/-/g, '+').replace(/_/g, '/');
15483
+ while (s.length % 4) s += '=';
15484
+ var raw = atob(s);
15485
+ var out = new Uint8Array(raw.length);
15486
+ for (var i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);
15487
+ return out;
15488
+ }
15489
+ function supported() {
15490
+ return 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window;
15491
+ }
15492
+ // The key this phone subscribed with. When the computer's keys are
15493
+ // replaced, the old subscription can never be delivered to, so it is
15494
+ // dropped and the card offers Turn on again.
15495
+ function savedKey() { try { return localStorage.getItem('ax-push-key'); } catch (e) { return null; } }
15496
+ function saveKey(k) { try { if (k) localStorage.setItem('ax-push-key', k); else localStorage.removeItem('ax-push-key'); } catch (e) {} }
15497
+ function register(sub) {
15498
+ var body = sub.toJSON();
15499
+ body.publicKey = server.publicKey;
15500
+ return api('POST', '/api/app/push/subscribe', body).then(function () { saveKey(server.publicKey); });
15501
+ }
15502
+ function currentSub() {
15503
+ return navigator.serviceWorker.ready.then(function (reg) { return reg.pushManager.getSubscription(); });
15504
+ }
15505
+ function show(state, message, action) {
15506
+ pill.textContent = state === 'on' ? 'On' : state === 'off' ? 'Off' : 'Unavailable';
15507
+ pill.className = 'fx-pill ' + (state === 'on' ? 'fx-on' : state === 'off' ? 'fx-warn' : 'fx-off');
15508
+ text.textContent = message;
15509
+ btn.hidden = !action;
15510
+ if (action) { btn.textContent = action; btn.className = 'fx-btn ' + (action === 'Turn off' ? 'fx-danger-o' : 'fx-primary'); }
15511
+ }
15512
+
15513
+ function refresh() {
15514
+ err.textContent = '';
15515
+ if (!supported()) {
15516
+ show('na', 'This browser can\u2019t receive notifications here. On an iPhone, add the app to the Home Screen first (Share, then Add to Home Screen), then open it from there.');
15517
+ return Promise.resolve();
15518
+ }
15519
+ return api('GET', '/api/app/push').then(function (s) {
15520
+ server = s;
15521
+ if (!s.available) { show('na', s.reason || 'Notifications are not set up on this computer.'); return; }
15522
+ if (Notification.permission === 'denied') {
15523
+ show('na', 'Notifications are blocked for this app. Allow them in the phone\u2019s settings for this app, then come back.');
15524
+ return;
15525
+ }
15526
+ return currentSub().then(function (sub) {
15527
+ var offer = function () { show('off', 'Turn on to get a notification when an agent needs you.', 'Turn on'); };
15528
+ if (!sub) { offer(); return; }
15529
+ if (savedKey() !== s.publicKey) {
15530
+ // Made with keys this computer no longer has: it can't be used.
15531
+ saveKey(null);
15532
+ return sub.unsubscribe().then(offer, offer);
15533
+ }
15534
+ // The computer may have lost it (the phone was re-paired): send it again.
15535
+ var sync = s.subscriptions > 0 ? Promise.resolve() : register(sub);
15536
+ return sync.then(function () { show('on', 'This phone gets a notification when an agent needs you.', 'Turn off'); });
15537
+ });
15538
+ }).catch(function (e) { show('na', 'Could not check notifications: ' + e.message); });
15539
+ }
15540
+
15541
+ function turnOn() {
15542
+ return Notification.requestPermission().then(function (p) {
15543
+ if (p !== 'granted') throw new Error('Notifications were not allowed.');
15544
+ return navigator.serviceWorker.ready;
15545
+ }).then(function (reg) {
15546
+ // A subscription made with older keys can't be reused; replace it.
15547
+ return reg.pushManager.getSubscription().then(function (old) {
15548
+ return old ? old.unsubscribe() : null;
15549
+ }).then(function () {
15550
+ return reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: keyBytes(server.publicKey) });
15551
+ });
15552
+ }).then(register);
15553
+ }
15554
+ function turnOff() {
15555
+ return currentSub().then(function (sub) {
15556
+ if (!sub) return null;
15557
+ var endpoint = sub.endpoint;
15558
+ saveKey(null);
15559
+ return sub.unsubscribe().then(function () { return api('POST', '/api/app/push/unsubscribe', { endpoint: endpoint }); });
15560
+ });
15561
+ }
15562
+ btn.addEventListener('click', function () {
15563
+ if (busy) return;
15564
+ busy = true;
15565
+ btn.disabled = true;
15566
+ err.textContent = '';
15567
+ (btn.textContent === 'Turn off' ? turnOff() : turnOn())
15568
+ .catch(function (e) { err.textContent = e.message; })
15569
+ .then(refresh)
15570
+ .then(function () { busy = false; btn.disabled = false; });
15571
+ });
15572
+
15573
+ function loadRecent() {
15574
+ return api('GET', '/api/app/alerts').then(function (b) {
15575
+ var items = b.items || [];
15576
+ if (!items.length) { list.innerHTML = '<li class="fx-muted">No notifications yet.</li>'; return; }
15577
+ list.innerHTML = items.map(function (it) {
15578
+ // Only web links: a button URL comes from an agent's message.
15579
+ var link = /^https?:/i.test(it.url || '')
15580
+ ? ' <a href="' + esc(it.url) + '" target="_blank" rel="noopener noreferrer">Open</a>' : '';
15581
+ return '<li><div class="fx-row"><strong>' + esc(it.title) + '</strong><span class="fx-muted">' + esc(ago(it.at)) + '</span></div>' +
15582
+ '<p>' + esc(it.body) + link + '</p></li>';
15583
+ }).join('');
15584
+ }).catch(function (e) { list.innerHTML = '<li class="fx-bad">Could not load notifications: ' + esc(e.message) + '</li>'; });
15585
+ }
15586
+
15587
+ if ('serviceWorker' in navigator) {
15588
+ navigator.serviceWorker.addEventListener('message', function (ev) {
15589
+ var d = ev.data || {};
15590
+ if (d.type === 'agentx-push') loadRecent();
15591
+ if (d.type === 'agentx-open' && d.url) location.href = d.url;
15592
+ });
15593
+ }
15594
+ document.addEventListener('visibilitychange', function () { if (!document.hidden) loadRecent(); });
15595
+ refresh();
15596
+ loadRecent();
15597
+ })();
15598
+ `;var Lr=`
15599
+ (function () {
15600
+ var panel = document.getElementById('panel-chat');
15601
+ var V = window.AXChatView;
15602
+ if (!panel || !V) return;
15603
+ // The head (agent, History, New) and its two sheets stay pinned at the top
15604
+ // of a long conversation, as the composer stays at the bottom.
15605
+ panel.innerHTML = '<h2 class="cx-sr">Chat</h2><div class="cx"><div class="cx-top">' +
15606
+ '<div class="cx-head"><button type="button" id="cx-pick" class="cx-pick" aria-controls="cx-picker" aria-expanded="false">' +
15607
+ '<span class="cx-pick-label">Choose an agent</span><span class="cx-pick-sub">Tap to see the agents on your machines</span></button>' +
15608
+ '<button type="button" id="cx-history-btn" class="fx-btn" aria-controls="cx-history" aria-expanded="false">History</button>' +
15609
+ '<button type="button" id="cx-new" class="fx-btn">New</button></div>' +
15610
+ '<div id="cx-picker" class="cx-sheet" role="region" aria-label="Agents" hidden></div>' +
15611
+ '<div id="cx-history" class="cx-sheet" role="region" aria-label="Past conversations" hidden></div></div>' +
15612
+ '<p id="cx-empty" class="soon">Pick an agent, then ask it anything. Its answer appears here as it writes.</p>' +
15613
+ '<div id="cx-log" class="cx-log" role="log" aria-live="polite"></div>' +
15614
+ '<form id="cx-form" class="cx-composer"><label for="cx-input" class="cx-sr">Message</label>' +
15615
+ '<textarea id="cx-input" rows="1" placeholder="Message" enterkeyhint="send" autocomplete="off"></textarea>' +
15616
+ '<button type="button" id="cx-stop" class="fx-btn fx-danger" hidden>Stop</button>' +
15617
+ '<button type="submit" id="cx-send" class="cx-send">Send</button></form></div>';
15618
+
15619
+ function $(id) { return document.getElementById(id); }
15620
+ var log = $('cx-log'), empty = $('cx-empty'), form = $('cx-form'), input = $('cx-input'), stopBtn = $('cx-stop');
15621
+ var pickBtn = $('cx-pick'), picker = $('cx-picker'), hist = $('cx-history'), histBtn = $('cx-history-btn'), newBtn = $('cx-new');
15622
+ var state = { conv: null, target: null, busy: false, queue: [], stopWanted: false, view: 0 };
15623
+ var NOTES = { stopped: 'Stopped. What the agent wrote so far is kept.', error: 'The agent could not answer.',
15624
+ running: 'Still answering. The answer appears here when it is ready.',
15625
+ lost: 'Connection lost. The agent keeps answering; the answer appears here when the phone is back online.' };
15626
+
15627
+ function remember(k, v) { try { if (v == null) localStorage.removeItem(k); else localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} }
15628
+ function recall(k) { try { return JSON.parse(localStorage.getItem(k) || 'null'); } catch (e) { return null; } }
15629
+ function api(path, opts) {
15630
+ return fetch(path, Object.assign({ credentials: 'same-origin' }, opts || {})).then(function (r) {
15631
+ if (r.status === 401) { location.reload(); throw new Error('not paired'); }
15632
+ return r;
15633
+ });
15634
+ }
15635
+ function post(path, body, signal) {
15636
+ return api(path, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), signal: signal });
15637
+ }
15638
+
15639
+ // --- The log ---
15640
+ function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
15641
+ function clearLog() { log.innerHTML = ''; empty.hidden = false; }
15642
+ function bubble(cls) {
15643
+ var el = document.createElement('div');
15644
+ el.className = 'cx-msg ' + cls;
15645
+ log.appendChild(el);
15646
+ empty.hidden = true;
15647
+ return el;
15648
+ }
15649
+ function userMsg(text) { var el = bubble('cx-user'); el.textContent = text; return el; }
15650
+ function agentMsg() {
15651
+ var el = bubble('cx-agent');
15652
+ el.innerHTML = '<div class="md cx-typing">Thinking\u2026</div><div class="cx-ui"></div><p class="cx-note" hidden></p>';
15653
+ return el;
15654
+ }
15655
+ function setBody(el, text) { el.replaceChild(V.md(text), el.querySelector('.md')); }
15656
+ function setNote(el, text, bad) {
15657
+ var n = el.querySelector('.cx-note');
15658
+ n.hidden = !text; n.textContent = text || ''; n.className = 'cx-note' + (bad ? ' cx-bad' : '');
15659
+ }
15660
+ function renderUi(el, ui) { V.renderUi(el.querySelector('.cx-ui'), ui, send); }
15661
+ function renderConversation(conv) {
15662
+ clearLog();
15663
+ (conv.messages || []).forEach(function (m) {
15664
+ if (m.role === 'user') { userMsg(m.content); return; }
15665
+ var el = agentMsg();
15666
+ setBody(el, m.content || '');
15667
+ V.setTools(el, m.tools);
15668
+ renderUi(el, m.ui);
15669
+ if (m.status && m.status !== 'done') setNote(el, m.error || NOTES[m.status] || '', m.status === 'error');
15670
+ });
15671
+ var live = null;
15672
+ if (conv.running) {
15673
+ // What the agent has written so far; the live stream carries on from it.
15674
+ live = agentMsg();
15675
+ if (conv.partial && conv.partial.text) setBody(live, V.preview(conv.partial.text));
15676
+ V.setTools(live, conv.partial && conv.partial.tools);
15677
+ setNote(live, NOTES.running);
15678
+ }
15679
+ // Follow-ups typed while it answers stay below, waiting to be sent.
15680
+ state.queue.forEach(function (x) { log.appendChild(x.el); });
15681
+ scrollDown();
15682
+ return live;
15683
+ }
15684
+
15685
+ // --- Agent, conversation and the sheets ---
15686
+ function showTarget(t) {
15687
+ pickBtn.querySelector('.cx-pick-label').textContent = t ? (t.agentName || t.agent) : 'Choose an agent';
15688
+ pickBtn.querySelector('.cx-pick-sub').textContent = t ? 'on ' + t.nodeName : 'Tap to see the agents on your machines';
15689
+ }
15690
+ function useConversation(conv) {
15691
+ state.conv = conv;
15692
+ state.target = { node: conv.node, nodeName: conv.nodeName, agent: conv.agent, agentName: conv.agentName };
15693
+ showTarget(state.target);
15694
+ remember('ax-chat-conv', conv.id);
15695
+ remember('ax-chat-target', state.target);
15696
+ }
15697
+ function toggle(sheet, open) {
15698
+ [[picker, pickBtn], [hist, histBtn]].forEach(function (p) {
15699
+ var on = p[0] === sheet && open;
15700
+ p[0].hidden = !on; p[1].setAttribute('aria-expanded', on ? 'true' : 'false');
15701
+ });
15702
+ }
15703
+ function loadPicker() {
15704
+ picker.innerHTML = '<p class="cx-note">Looking for agents\u2026</p>';
15705
+ api('/api/app/agents').then(function (r) { return r.json(); }).then(function (data) {
15706
+ var nodes = picker._data = data.nodes || [];
15707
+ if (!nodes.length) { picker.innerHTML = '<p class="cx-note">No machines answered. Check that AgentX is running.</p>'; return; }
15708
+ picker.innerHTML = nodes.map(function (n, i) {
15709
+ var can = n.target && n.online;
15710
+ var why = !n.target ? 'Not linked to this computer\u2019s mesh' : n.online ? 'Online' : 'Offline';
15711
+ var rows = n.agents.length ? n.agents.map(function (a, j) {
15712
+ return '<li><button type="button" data-n="' + i + '" data-a="' + j + '"' + (can ? '' : ' disabled') + '>' +
15713
+ '<span>' + V.esc(a.name) + '<span class="cx-sub">' + V.esc(a.id) + '</span></span>' +
15714
+ '<span class="cx-state' + (a.busy ? ' cx-busy' : '') + '">' + (a.busy ? 'busy' + (a.running > 1 ? ' \xB7 ' + a.running : '') : 'idle') + '</span></button></li>';
15715
+ }).join('') : '<li class="cx-note">No agents</li>';
15716
+ return '<h3><span class="cx-dot' + (n.online ? ' cx-on' : '') + '"></span>' + V.esc(n.name) + ' <span class="cx-sub">' + V.esc(why) + '</span></h3><ul>' + rows + '</ul>';
15717
+ }).join('');
15718
+ }).catch(function () { picker.innerHTML = '<p class="cx-note cx-bad">Could not load agents. Check the connection and try again.</p>'; });
15719
+ }
15720
+ picker.addEventListener('click', function (ev) {
15721
+ var b = ev.target.closest('button[data-a]');
15722
+ if (!b || !picker._data) return;
15723
+ var n = picker._data[+b.getAttribute('data-n')], a = n.agents[+b.getAttribute('data-a')];
15724
+ state.target = { node: n.target, nodeName: n.name, agent: a.id, agentName: a.name };
15725
+ remember('ax-chat-target', state.target);
15726
+ startNew();
15727
+ toggle(picker, false);
15728
+ input.focus();
15729
+ });
15730
+ function startNew() {
15731
+ if (state.busy) return;
15732
+ state.view++;
15733
+ clearTimeout(pollTimer);
15734
+ state.conv = null;
15735
+ remember('ax-chat-conv', null);
15736
+ showTarget(state.target);
15737
+ clearLog();
15738
+ setBusy(false);
15739
+ }
15740
+ function when(ms) { var d = new Date(ms); return isNaN(d.getTime()) ? '' : d.toLocaleString(); }
15741
+ function loadHistory() {
15742
+ hist.innerHTML = '<p class="cx-note">Loading\u2026</p>';
15743
+ api('/api/app/conversations').then(function (r) { if (!r.ok) throw new Error(); return r.json(); })
15744
+ .then(function (d) { paintHistory(d.conversations || [], false); })
15745
+ .catch(function () { V.cacheAll().then(function (all) { paintHistory(all, true); }); });
15746
+ }
15747
+ function paintHistory(list, offline) {
15748
+ if (!list.length) { hist.innerHTML = '<p class="cx-note">' + (offline ? 'Offline, and nothing is saved on this phone yet.' : 'No conversations yet.') + '</p>'; return; }
15749
+ hist.innerHTML = (offline ? '<p class="cx-note">Offline: showing the conversations saved on this phone.</p>' : '') + '<ul>' + list.map(function (c) {
15750
+ return '<li><button type="button" data-c="' + V.esc(c.id) + '"><span>' + V.esc(c.title) +
15751
+ '<span class="cx-sub">' + V.esc((c.agentName || c.agent) + ' \xB7 ' + c.nodeName + ' \xB7 ' + when(c.updatedAt)) + '</span></span></button></li>';
15752
+ }).join('') + '</ul>';
15753
+ }
15754
+ hist.addEventListener('click', function (ev) {
15755
+ var b = ev.target.closest('button[data-c]');
15756
+ if (!b) return;
15757
+ toggle(hist, false);
15758
+ openConversation(b.getAttribute('data-c'));
15759
+ });
15760
+ var pollTimer = 0;
15761
+ function openConversation(id) {
15762
+ if (state.busy) return;
15763
+ clearTimeout(pollTimer);
15764
+ // The phone's copy first, so it opens at once and offline; the server's
15765
+ // copy replaces it when it arrives. A load that finishes after the user
15766
+ // moved on (New, another conversation, a send) is dropped.
15767
+ var mine = ++state.view, fromServer = false;
15768
+ V.cacheGet(id).then(function (c) { if (c && !fromServer && mine === state.view) { useConversation(c); renderConversation(c); } });
15769
+ return api('/api/app/conversations/' + encodeURIComponent(id)).then(function (r) {
15770
+ if (mine !== state.view) return null;
15771
+ if (r.status === 404) { fromServer = true; V.cacheDrop(id); startNew(); return null; }
15772
+ return r.ok ? r.json() : null;
15773
+ }).then(function (c) {
15774
+ if (!c || mine !== state.view) return;
15775
+ fromServer = true;
15776
+ useConversation(c);
15777
+ var live = renderConversation(c);
15778
+ if (!c.running) { V.cachePut(c); return; }
15779
+ // Still running: pick the live stream up where it is.
15780
+ follow(api('/api/app/chat/attach?conversationId=' + encodeURIComponent(id)), live, c.partial || {});
15781
+ }).catch(function () {});
15782
+ }
15783
+
15784
+ // --- Sending, streaming, stopping ---
15785
+ function setBusy(on) {
15786
+ state.busy = on;
15787
+ stopBtn.hidden = !on;
15788
+ newBtn.disabled = on;
15789
+ log.setAttribute('aria-busy', on ? 'true' : 'false');
15790
+ }
15791
+ function send(text) {
15792
+ text = String(text || '').trim();
15793
+ if (!text) return;
15794
+ if (state.busy) {
15795
+ // A follow-up while the agent answers: shown now, sent as the next
15796
+ // turn so its answer streams here as well.
15797
+ var q = userMsg(text);
15798
+ q.classList.add('cx-queued');
15799
+ state.queue.push({ text: text, el: q });
15800
+ input.value = ''; input.style.height = '';
15801
+ scrollDown();
15802
+ return;
15803
+ }
15804
+ if (!navigator.onLine) { flash('Offline. Messages can be sent once the phone is connected again.'); return; }
15805
+ if (!state.conv && !state.target) { toggle(picker, true); loadPicker(); return; }
15806
+ var body = state.conv
15807
+ ? { conversationId: state.conv.id, message: text }
15808
+ : { node: state.target.node, agent: state.target.agent, message: text };
15809
+ state.stopWanted = false;
15810
+ userMsg(text);
15811
+ input.value = ''; input.style.height = '';
15812
+ follow(post('/api/app/chat', body), agentMsg(), null);
15813
+ }
15814
+ // Streams one turn into the bubble el, from a send or from attaching
15815
+ // to a turn that is still running. The phone losing its connection does
15816
+ // not stop the agent: the answer is saved and shown when the phone is back.
15817
+ function follow(request, el, partial) {
15818
+ clearTimeout(pollTimer);
15819
+ state.view++;
15820
+ var raw = (partial && partial.text) || '', tools = ((partial && partial.tools) || []).slice(), ended = false, frame = 0;
15821
+ function paint() { frame = 0; if (!ended && raw) { setBody(el, V.preview(raw)); scrollDown(); } }
15822
+ function finish(content, note, bad, ui) {
15823
+ ended = true;
15824
+ setBody(el, content || '');
15825
+ renderUi(el, ui);
15826
+ setNote(el, note, bad);
15827
+ scrollDown();
15828
+ }
15829
+ setBusy(true);
15830
+ scrollDown();
15831
+ return request.then(function (r) {
15832
+ // Attaching just after the turn ended: reload the saved answer.
15833
+ if (r.status === 404 && partial) { ended = true; return; }
15834
+ if (!r.ok) return r.json().catch(function () { return {}; }).then(function (j) { finish(raw, j.error || ('Failed (HTTP ' + r.status + ')'), true); });
15835
+ return V.readStream(r.body, function (ev, d) {
15836
+ if (ev === 'conversation') { useConversation(d); if (state.stopWanted) { state.stopWanted = false; stop(); } }
15837
+ else if (ev === 'resume') { raw = d.text || ''; tools = (d.tools || []).slice(); V.setTools(el, tools); setNote(el, ''); paint(); }
15838
+ else if (ev === 'text' && typeof d.text === 'string') { raw += d.text; if (!frame) frame = requestAnimationFrame(paint); }
15839
+ else if (ev === 'tool' && d.status === 'start') { tools.push({ id: d.id, name: d.name, arg: d.arg }); V.setTools(el, tools); }
15840
+ else if (ev === 'tool' && d.error) { tools.forEach(function (t) { if (t.id === d.id) t.error = true; }); V.setTools(el, tools); }
15841
+ else if (ev === 'final') finish(d.content, d.status === 'done' ? '' : (d.error || NOTES[d.status]), d.status === 'error', d.ui);
15842
+ });
15843
+ }).catch(function () {}).then(function () {
15844
+ setBusy(false);
15845
+ if (!ended) {
15846
+ // The stream broke before the answer: the agent carries on.
15847
+ setNote(el, state.conv ? NOTES.lost : 'Could not reach AgentX. Check the connection and try again.', !state.conv);
15848
+ if (state.conv) { var id = state.conv.id; pollTimer = setTimeout(function () { if (state.conv && state.conv.id === id) openConversation(id); }, 5000); }
15849
+ return;
15850
+ }
15851
+ if (state.queue.length) {
15852
+ var next = state.queue.splice(0);
15853
+ next.forEach(function (x) { x.el.remove(); });
15854
+ send(next.map(function (x) { return x.text; }).join(V.NL + V.NL));
15855
+ } else if (state.conv) openConversation(state.conv.id);
15856
+ });
15857
+ }
15858
+ function stop() {
15859
+ // Only Stop cancels. Before the conversation exists, wait for its id.
15860
+ if (!state.conv) { state.stopWanted = true; return; }
15861
+ post('/api/app/chat/stop', { conversationId: state.conv.id }).catch(function () {});
15862
+ }
15863
+ function flash(text) {
15864
+ var el = bubble('cx-agent');
15865
+ el.innerHTML = '<p class="cx-note cx-bad"></p>';
15866
+ el.firstChild.textContent = text;
15867
+ scrollDown();
15868
+ }
15869
+
15870
+ form.addEventListener('submit', function (e) { e.preventDefault(); send(input.value); });
15871
+ input.addEventListener('keydown', function (e) {
15872
+ if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); send(input.value); }
15873
+ });
15874
+ input.addEventListener('input', function () { input.style.height = ''; input.style.height = Math.min(input.scrollHeight, 240) + 'px'; });
15875
+ stopBtn.addEventListener('click', stop);
15876
+ pickBtn.addEventListener('click', function () { var open = picker.hidden; toggle(picker, open); if (open) loadPicker(); });
15877
+ histBtn.addEventListener('click', function () { var open = hist.hidden; toggle(hist, open); if (open) loadHistory(); });
15878
+ newBtn.addEventListener('click', function () { startNew(); input.focus(); });
15879
+
15880
+ window.addEventListener('online', function () { if (state.conv && !state.busy) openConversation(state.conv.id); });
15881
+ state.target = recall('ax-chat-target');
15882
+ showTarget(state.target);
15883
+ var last = recall('ax-chat-conv');
15884
+ if (last) openConversation(last);
15885
+ })();
15886
+ `;var jr=`
15887
+ window.AXChatView = (function () {
15888
+ var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
15889
+ // Cut a half-written agentx:ui block from a streaming reply so its raw
15890
+ // JSON never flashes; the finished reply arrives with it parsed.
15891
+ var PREVIEW_CUT = new RegExp('(^|' + NL + ')[ ' + TAB + ']*' + FENCE + '[ ' + TAB + ']*agentx:ui', 'i');
15892
+ var KEEP = 100;
15893
+
15894
+ function esc(v) {
15895
+ return String(v == null ? '' : v).replace(/[&<>"']/g, function (c) {
15896
+ return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
15897
+ });
15898
+ }
15899
+ function httpUrl(u) {
15900
+ try { var x = new URL(String(u || ''), location.href); return x.protocol === 'https:' || x.protocol === 'http:' ? x.href : ''; } catch (e) { return ''; }
15901
+ }
15902
+ function preview(text) { var m = PREVIEW_CUT.exec(text); return m ? text.slice(0, m.index) : text; }
15903
+
15904
+ function md(text) {
15905
+ var d = document.createElement('div');
15906
+ d.className = 'md';
15907
+ try { d.innerHTML = markdownToHtml(String(text || '')); } catch (e) { d.textContent = text; }
15908
+ Array.prototype.slice.call(d.querySelectorAll('a')).forEach(function (a) {
15909
+ var h = /^https?:/i.test(a.getAttribute('href') || '') ? httpUrl(a.getAttribute('href')) : '';
15910
+ if (h) { a.href = h; a.target = '_blank'; a.rel = 'noopener noreferrer'; }
15911
+ else a.replaceWith(document.createTextNode(a.textContent));
15912
+ });
15913
+ return d;
15914
+ }
15915
+
15916
+ function setTools(el, tools) {
15917
+ if (!tools || !tools.length) return;
15918
+ var box = el.querySelector('.cx-tools');
15919
+ if (!box) {
15920
+ box = document.createElement('details');
15921
+ box.className = 'cx-tools';
15922
+ box.innerHTML = '<summary></summary><ul></ul>';
15923
+ el.insertBefore(box, el.firstChild);
15924
+ }
15925
+ var last = tools[tools.length - 1], bad = tools.filter(function (t) { return t.error; }).length;
15926
+ box.querySelector('summary').textContent = tools.length + (tools.length === 1 ? ' tool' : ' tools') +
15927
+ ' \xB7 ' + last.name + (last.arg ? ' (' + last.arg + ')' : '') + (bad ? ' \xB7 ' + bad + ' failed' : '');
15928
+ box.querySelector('ul').innerHTML = tools.map(function (t) {
15929
+ return '<li' + (t.error ? ' class="cx-bad"' : '') + '>' + esc(t.name) + (t.arg ? ' \xB7 ' + esc(t.arg) : '') + '</li>';
15930
+ }).join('');
15931
+ }
15932
+
15933
+ function link(href, label) {
15934
+ var a = document.createElement('a');
15935
+ a.className = 'cx-ui-btn'; a.href = href; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.textContent = label;
15936
+ return a;
15937
+ }
15938
+ function renderUi(box, ui, send) {
15939
+ box.innerHTML = '';
15940
+ if (!ui) return;
15941
+ var m = ui.media, u = m && httpUrl(m.url);
15942
+ if (u) {
15943
+ var node;
15944
+ if (m.type === 'image') { node = document.createElement('img'); node.loading = 'lazy'; node.alt = m.caption || 'Picture from the agent'; node.referrerPolicy = 'no-referrer'; node.src = u; }
15945
+ else if (m.type === 'video' || m.type === 'audio') { node = document.createElement(m.type); node.controls = true; node.preload = 'metadata'; node.src = u; }
15946
+ else node = link(u, m.caption || 'Open document');
15947
+ box.appendChild(node);
15948
+ if (m.caption && node.tagName !== 'A') { var c = document.createElement('p'); c.className = 'cx-note'; c.textContent = m.caption; box.appendChild(c); }
15949
+ }
15950
+ var btns = (ui.buttons || []).filter(function (b) { return httpUrl(b.url); });
15951
+ if (btns.length) {
15952
+ var row = document.createElement('div');
15953
+ row.className = 'cx-ui-row';
15954
+ btns.forEach(function (b) { row.appendChild(link(httpUrl(b.url), b.label)); });
15955
+ box.appendChild(row);
15956
+ }
15957
+ if (ui.poll && ui.poll.options) {
15958
+ // A poll answer is simply the next message in the conversation.
15959
+ var fs = document.createElement('fieldset'), lg = document.createElement('legend'), opts = document.createElement('div');
15960
+ lg.textContent = ui.poll.question; fs.appendChild(lg);
15961
+ opts.className = 'cx-ui-row'; fs.appendChild(opts);
15962
+ ui.poll.options.forEach(function (o) {
15963
+ if (ui.poll.multiple) {
15964
+ var l = document.createElement('label'), cb = document.createElement('input');
15965
+ cb.type = 'checkbox'; cb.value = o; l.appendChild(cb); l.appendChild(document.createTextNode(o)); opts.appendChild(l);
15966
+ } else {
15967
+ var b = document.createElement('button');
15968
+ b.type = 'button'; b.className = 'cx-ui-btn'; b.textContent = o;
15969
+ b.addEventListener('click', function () { send(o); });
15970
+ opts.appendChild(b);
15971
+ }
15972
+ });
15973
+ if (ui.poll.multiple) {
15974
+ var go = document.createElement('button');
15975
+ go.type = 'button'; go.className = 'cx-ui-btn'; go.textContent = 'Send answer';
15976
+ go.addEventListener('click', function () {
15977
+ var picked = Array.prototype.slice.call(fs.querySelectorAll('input:checked')).map(function (i) { return i.value; });
15978
+ if (picked.length) send(picked.join(', '));
15979
+ });
15980
+ fs.appendChild(go);
15981
+ }
15982
+ box.appendChild(fs);
15983
+ }
15984
+ }
15985
+
15986
+ // Reads the agentx SSE wire from a fetch body: event: <kind>, data: <json>.
15987
+ function readStream(body, onEvent) {
15988
+ var reader = body.getReader(), dec = new TextDecoder(), buf = '';
15989
+ function pump() {
15990
+ return reader.read().then(function (r) {
15991
+ if (r.done) return;
15992
+ buf += dec.decode(r.value, { stream: true });
15993
+ var i;
15994
+ while ((i = buf.indexOf(NL + NL)) >= 0) {
15995
+ var rec = buf.slice(0, i), ev = 'message', data = '';
15996
+ buf = buf.slice(i + 2);
15997
+ rec.split(NL).forEach(function (line) {
15998
+ if (line.indexOf('event:') === 0) ev = line.slice(6).trim();
15999
+ else if (line.indexOf('data:') === 0) data += line.slice(5).trim();
16000
+ });
16001
+ if (data) { try { onEvent(ev, JSON.parse(data)); } catch (e) {} }
16002
+ }
16003
+ return pump();
16004
+ });
16005
+ }
16006
+ return pump();
16007
+ }
16008
+
16009
+ // --- IndexedDB: whole conversations keyed by id, newest KEEP kept ---
16010
+ var dbp = null;
16011
+ function db() {
16012
+ if (!window.indexedDB) return Promise.reject(new Error('no indexedDB'));
16013
+ if (!dbp) dbp = new Promise(function (ok, no) {
16014
+ var r = indexedDB.open('agentx-app-chat', 1);
16015
+ r.onupgradeneeded = function () { r.result.createObjectStore('conversations', { keyPath: 'id' }); };
16016
+ r.onsuccess = function () { ok(r.result); };
16017
+ r.onerror = function () { no(r.error); };
16018
+ });
16019
+ return dbp;
16020
+ }
16021
+ function idb(mode, fn) {
16022
+ return db().then(function (d) {
16023
+ return new Promise(function (ok) {
16024
+ var tx = d.transaction('conversations', mode), req = fn(tx.objectStore('conversations'));
16025
+ tx.oncomplete = function () { ok(req && req.result); };
16026
+ tx.onerror = tx.onabort = function () { ok(null); };
16027
+ });
16028
+ }).catch(function () { return null; });
16029
+ }
16030
+ function cacheAll() {
16031
+ return idb('readonly', function (s) { return s.getAll(); }).then(function (a) {
16032
+ return (a || []).sort(function (x, y) { return y.updatedAt - x.updatedAt; });
16033
+ });
16034
+ }
16035
+ function cachePut(conv) {
16036
+ return idb('readwrite', function (s) { s.put(conv); }).then(cacheAll).then(function (all) {
16037
+ var old = all.slice(KEEP);
16038
+ if (old.length) return idb('readwrite', function (s) { old.forEach(function (c) { s.delete(c.id); }); });
16039
+ });
16040
+ }
16041
+ function cacheGet(id) { return idb('readonly', function (s) { return s.get(id); }); }
16042
+ function cacheDrop(id) { return idb('readwrite', function (s) { s.delete(id); }); }
16043
+
16044
+ return { NL: NL, esc: esc, httpUrl: httpUrl, md: md, preview: preview, setTools: setTools, renderUi: renderUi, readStream: readStream,
16045
+ cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
16046
+ })();
16047
+ `;var Rr=`
16048
+ body { height: 100dvh; }
16049
+ main { min-height: 0; }
16050
+ #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
16051
+ .cx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
16052
+ .cx { display: flex; flex-direction: column; flex: 1; gap: 10px; }
16053
+ .cx-top {
16054
+ position: sticky; top: -16px; z-index: 1; display: grid; gap: 8px;
16055
+ margin: -16px 0 0; padding: 16px 0 8px; background: var(--ax-bg);
16056
+ }
16057
+ .cx-head { display: flex; gap: 8px; align-items: stretch; }
16058
+ .cx-head .fx-btn { border-radius: var(--ax-radius); min-height: 48px; }
16059
+ .cx-pick {
16060
+ flex: 1; min-width: 0; min-height: 48px; text-align: left; cursor: pointer;
16061
+ display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 6px 12px;
16062
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius);
16063
+ background: var(--ax-surface); color: var(--ax-text); font: inherit;
16064
+ }
16065
+ .cx-pick-label { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
16066
+ .cx-pick-sub { font-size: var(--ax-fs-xs); color: var(--ax-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
16067
+ .cx-sheet {
16068
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius);
16069
+ background: var(--ax-surface); padding: 4px 12px 12px; max-height: 60vh; overflow-y: auto;
16070
+ }
16071
+ .cx-sheet h3 { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); margin: 12px 0 6px; }
16072
+ .cx-sheet ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
16073
+ .cx-sheet li button {
16074
+ width: 100%; min-height: 48px; display: flex; justify-content: space-between; align-items: center; gap: 8px;
16075
+ padding: 8px 12px; text-align: left; cursor: pointer; font: inherit;
16076
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm);
16077
+ background: var(--ax-surface-2); color: var(--ax-text);
16078
+ }
16079
+ .cx-sheet li button:disabled { opacity: 0.55; cursor: not-allowed; }
16080
+ .cx-sub { display: block; font-size: var(--ax-fs-xs); color: var(--ax-text-2); font-weight: 400; }
16081
+ .cx-sheet h3 .cx-sub { display: inline; }
16082
+ .cx-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ax-muted); flex: none; }
16083
+ .cx-dot.cx-on { background: var(--ax-green); }
16084
+ .cx-state { font-size: var(--ax-fs-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--ax-radius-pill); background: var(--ax-surface-3); color: var(--ax-text-2); white-space: nowrap; }
16085
+ .cx-state.cx-busy { background: var(--ax-amber-t); color: var(--ax-amber-ink); }
16086
+ .cx-log { display: flex; flex-direction: column; gap: 10px; flex: 1; }
16087
+ .cx-msg { max-width: 92%; padding: 10px 12px; border-radius: var(--ax-radius); line-height: 1.5; overflow-wrap: anywhere; }
16088
+ .cx-user { align-self: flex-end; background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); border: var(--ax-border-w) solid color-mix(in oklch, var(--ax-accent) 45%, var(--ax-border)); white-space: pre-wrap; }
16089
+ .cx-queued { opacity: 0.7; }
16090
+ .cx-queued::after { content: "Sent when the agent finishes"; display: block; font-size: var(--ax-fs-xs); color: var(--ax-text-2); margin-top: 4px; }
16091
+ .cx-agent { align-self: flex-start; background: var(--ax-surface); border: var(--ax-border-w) solid var(--ax-border); }
16092
+ .cx-msg .md > :first-child { margin-top: 0; }
16093
+ .cx-msg .md > :last-child { margin-bottom: 0; }
16094
+ .cx-msg .md pre { overflow-x: auto; background: var(--ax-surface-3); padding: 8px; border-radius: var(--ax-radius-sm); }
16095
+ .cx-msg .md table { display: block; overflow-x: auto; border-collapse: collapse; }
16096
+ .cx-msg .md th, .cx-msg .md td { border: 1px solid var(--ax-border); padding: 4px 8px; }
16097
+ .cx-msg .md a { color: var(--ax-accent); }
16098
+ .cx-typing { color: var(--ax-text-2); }
16099
+ .cx-tools { font-size: var(--ax-fs-xs); color: var(--ax-text-2); margin: 0 0 6px; }
16100
+ .cx-tools summary { min-height: 32px; font-weight: 600; }
16101
+ .cx-tools ul { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }
16102
+ .cx-tools li { font-family: var(--ax-mono); background: var(--ax-surface-3); border-radius: var(--ax-radius-pill); padding: 2px 8px; }
16103
+ .cx-tools li.cx-bad { background: var(--ax-red-t); color: var(--ax-red-ink); }
16104
+ .cx-note { margin: 6px 0 0; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
16105
+ .cx-bad { color: var(--ax-red-ink); }
16106
+ .cx-ui { display: grid; gap: 8px; margin-top: 8px; }
16107
+ .cx-ui:empty { display: none; }
16108
+ .cx-ui img, .cx-ui video { max-width: 100%; border-radius: var(--ax-radius-sm); }
16109
+ .cx-ui audio { width: 100%; }
16110
+ .cx-ui-row { display: flex; flex-wrap: wrap; gap: 6px; }
16111
+ .cx-ui-btn {
16112
+ display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px; cursor: pointer; font: inherit; font-weight: 600;
16113
+ border: var(--ax-border-w) solid color-mix(in oklch, var(--ax-accent) 50%, var(--ax-border)); border-radius: var(--ax-radius-pill);
16114
+ background: color-mix(in oklch, var(--ax-accent) 12%, var(--ax-surface)); color: var(--ax-accent); text-decoration: none;
16115
+ }
16116
+ .cx-ui fieldset { border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm); margin: 0; padding: 8px 10px; display: grid; gap: 8px; }
16117
+ .cx-ui legend { font-weight: 600; padding: 0 4px; }
16118
+ .cx-ui label { display: flex; align-items: center; gap: 8px; min-height: 44px; }
16119
+ .cx-composer { position: sticky; bottom: -16px; z-index: 1; display: flex; gap: 8px; align-items: flex-end; margin: 0 0 -16px; padding: 8px 0 16px; background: var(--ax-bg); }
16120
+ .cx-composer textarea {
16121
+ flex: 1; min-width: 0; min-height: 44px; max-height: 40vh; resize: none; padding: 10px 12px; font: inherit; font-size: 16px; box-sizing: border-box;
16122
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); color: var(--ax-text);
16123
+ }
16124
+ .cx-send {
16125
+ min-width: 72px; min-height: 44px; cursor: pointer; font: inherit; font-weight: 700;
16126
+ border: var(--ax-border-w) solid color-mix(in oklch, var(--ax-accent) 50%, var(--ax-border)); border-radius: var(--ax-radius);
16127
+ background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
16128
+ }
16129
+ .cx-composer .fx-btn { border-radius: var(--ax-radius); }
16130
+ `;var Bt=`
16131
+ var CACHE = 'agentx-app-v2';
16132
+ var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
16133
+ self.addEventListener('install', function (e) {
16134
+ e.waitUntil(caches.open(CACHE).then(function (c) { return c.addAll(STATIC); }).then(function () { return self.skipWaiting(); }));
16135
+ });
16136
+ self.addEventListener('activate', function (e) {
16137
+ e.waitUntil(caches.keys().then(function (keys) {
16138
+ return Promise.all(keys.filter(function (k) { return k !== CACHE; }).map(function (k) { return caches.delete(k); }));
16139
+ }).then(function () { return self.clients.claim(); }));
16140
+ });
16141
+ self.addEventListener('fetch', function (e) {
16142
+ var req = e.request;
16143
+ var url = new URL(req.url);
16144
+ if (req.method !== 'GET' || url.origin !== self.location.origin) return;
16145
+ if (url.pathname.indexOf('/api/') === 0) return;
16146
+ if (req.mode === 'navigate' && url.pathname === '/app') {
16147
+ e.respondWith(fetch(req).then(function (res) {
16148
+ var copy = res.clone();
16149
+ caches.open(CACHE).then(function (c) { return res.ok ? c.put('/app', copy) : res.status === 401 ? c.delete('/app') : null; });
16150
+ return res;
16151
+ }).catch(function () {
16152
+ return caches.match('/app').then(function (hit) { return hit || Response.error(); });
16153
+ }));
16154
+ return;
16155
+ }
16156
+ if (STATIC.indexOf(url.pathname) >= 0) {
16157
+ e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
16158
+ }
16159
+ });
16160
+ function safeUrl(u) {
16161
+ try {
16162
+ var abs = new URL(u || '/app#alerts', self.location.origin);
16163
+ return abs.protocol === 'https:' || abs.protocol === 'http:' ? abs.href : null;
16164
+ } catch (x) { return null; }
16165
+ }
16166
+ self.addEventListener('push', function (e) {
16167
+ var d = {};
16168
+ try { d = e.data ? e.data.json() : {}; } catch (x) { d = { body: e.data ? e.data.text() : '' }; }
16169
+ var actions = Array.isArray(d.actions) ? d.actions : [];
16170
+ var urls = {};
16171
+ actions.forEach(function (a) { urls[a.action] = a.url; });
16172
+ e.waitUntil(self.registration.showNotification(d.title || 'AgentX', {
16173
+ body: d.body || '',
16174
+ icon: '/app/icon-192.png',
16175
+ badge: '/app/icon-192.png',
16176
+ data: { url: d.url, urls: urls },
16177
+ actions: actions.map(function (a) { return { action: a.action, title: a.title }; }),
16178
+ }).then(function () {
16179
+ return self.clients.matchAll({ type: 'window' });
16180
+ }).then(function (cs) {
16181
+ cs.forEach(function (c) { c.postMessage({ type: 'agentx-push' }); });
16182
+ }));
16183
+ });
16184
+ self.addEventListener('notificationclick', function (e) {
16185
+ e.notification.close();
16186
+ var data = e.notification.data || {};
16187
+ var target = safeUrl((e.action && data.urls && data.urls[e.action]) || data.url) || safeUrl('/app#alerts');
16188
+ var inApp = new URL(target).origin === self.location.origin;
16189
+ e.waitUntil(self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (cs) {
16190
+ var app = inApp ? cs.filter(function (c) { return new URL(c.url).pathname === '/app'; })[0] : null;
16191
+ if (app) {
16192
+ app.postMessage({ type: 'agentx-open', url: target });
16193
+ return app.focus();
16194
+ }
16195
+ return self.clients.openWindow(target);
16196
+ }));
16197
+ });
16198
+ `;var Wl="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})();</script>";function zt(t){return`<meta charset="utf-8">
15310
16199
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
15311
16200
  <meta name="theme-color" content="#2979FF">
15312
16201
  <meta name="referrer" content="no-referrer">
@@ -15317,13 +16206,13 @@ details[open] > summary::before { transform: rotate(90deg); }
15317
16206
  <link rel="icon" type="image/png" href="/app/icon-192.png">
15318
16207
  <link rel="apple-touch-icon" href="/app/icon-192.png">
15319
16208
  <title>${t}</title>
15320
- ${al}
15321
- <style>${oa}${ol}</style>`}var ar=[{id:"chat",label:"Chat",soon:"Talking to your agents from this phone arrives in the next update."},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Notifications on this phone arrive in a later update."}];function nr(){let t=ar.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}">${a.label}</button>`).join(""),e=ar.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
16209
+ ${Wl}
16210
+ <style>${_a}${Kl}</style>`}var Pr=[{id:"chat",label:"Chat",soon:"Loading your conversations\u2026"},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Loading notifications\u2026"}];function Nr(){let t=Pr.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}">${a.label}</button>`).join(""),e=Pr.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
15322
16211
  <h2>${a.label}</h2>
15323
16212
  <p class="soon">${a.soon}</p>
15324
16213
  </section>`).join("");return`<!doctype html>
15325
16214
  <html lang="en">
15326
- <head>${At("AgentX")}<style>${sl}${tr}</style></head>
16215
+ <head>${zt("AgentX")}<style>${Jl}${Ir}${Rr}</style></head>
15327
16216
  <body>
15328
16217
  <header class="bar">
15329
16218
  <div>
@@ -15335,22 +16224,24 @@ ${al}
15335
16224
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
15336
16225
  <main>${e}</main>
15337
16226
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
15338
- <script>${nl}</script>
15339
- <script>${er}</script>
16227
+ <script>${Gl}</script>
16228
+ <script>${Mr}</script>
16229
+ <script>${$r}</script>
16230
+ <script>${ue({markdownToHtml:Ea})}${jr}${Lr}</script>
15340
16231
  </body>
15341
- </html>`}function rr(){return`<!doctype html>
16232
+ </html>`}function Or(){return`<!doctype html>
15342
16233
  <html lang="en">
15343
- <head>${At("Pair \xB7 AgentX")}</head>
16234
+ <head>${zt("Pair \xB7 AgentX")}</head>
15344
16235
  <body>
15345
16236
  <main class="card">
15346
16237
  <h1>Pairing this phone\u2026</h1>
15347
16238
  <p id="msg" role="status">One moment.</p>
15348
16239
  </main>
15349
- <script>${rl}</script>
16240
+ <script>${Xl}</script>
15350
16241
  </body>
15351
- </html>`}function or(){return`<!doctype html>
16242
+ </html>`}function Dr(){return`<!doctype html>
15352
16243
  <html lang="en">
15353
- <head>${At("Not paired \xB7 AgentX")}</head>
16244
+ <head>${zt("Not paired \xB7 AgentX")}</head>
15354
16245
  <body>
15355
16246
  <main class="card">
15356
16247
  <h1>This phone isn't paired</h1>
@@ -15358,37 +16249,7 @@ ${al}
15358
16249
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
15359
16250
  </main>
15360
16251
  </body>
15361
- </html>`}function sr(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var ir=`
15362
- var CACHE = 'agentx-app-v1';
15363
- var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
15364
- self.addEventListener('install', function (e) {
15365
- e.waitUntil(caches.open(CACHE).then(function (c) { return c.addAll(STATIC); }).then(function () { return self.skipWaiting(); }));
15366
- });
15367
- self.addEventListener('activate', function (e) {
15368
- e.waitUntil(caches.keys().then(function (keys) {
15369
- return Promise.all(keys.filter(function (k) { return k !== CACHE; }).map(function (k) { return caches.delete(k); }));
15370
- }).then(function () { return self.clients.claim(); }));
15371
- });
15372
- self.addEventListener('fetch', function (e) {
15373
- var req = e.request;
15374
- var url = new URL(req.url);
15375
- if (req.method !== 'GET' || url.origin !== self.location.origin) return;
15376
- if (url.pathname.indexOf('/api/') === 0) return;
15377
- if (req.mode === 'navigate' && url.pathname === '/app') {
15378
- e.respondWith(fetch(req).then(function (res) {
15379
- var copy = res.clone();
15380
- caches.open(CACHE).then(function (c) { return res.ok ? c.put('/app', copy) : res.status === 401 ? c.delete('/app') : null; });
15381
- return res;
15382
- }).catch(function () {
15383
- return caches.match('/app').then(function (hit) { return hit || Response.error(); });
15384
- }));
15385
- return;
15386
- }
15387
- if (STATIC.indexOf(url.pathname) >= 0) {
15388
- e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
15389
- }
15390
- });
15391
- `,nl=`
16252
+ </html>`}function Hr(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Gl=`
15392
16253
  (function () {
15393
16254
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
15394
16255
  function select(tab, focus) {
@@ -15412,8 +16273,12 @@ self.addEventListener('fetch', function (e) {
15412
16273
  if (next) { ev.preventDefault(); select(next, true); }
15413
16274
  });
15414
16275
  });
15415
- var start = tabs.filter(function (t) { return '#' + t.dataset.tab === location.hash; })[0];
15416
- if (start) select(start, false);
16276
+ function fromHash() {
16277
+ var t = tabs.filter(function (t) { return '#' + t.dataset.tab === location.hash; })[0];
16278
+ if (t) select(t, false);
16279
+ }
16280
+ fromHash();
16281
+ window.addEventListener('hashchange', fromHash);
15417
16282
 
15418
16283
  var root = document.documentElement;
15419
16284
  var themeBtn = document.getElementById('theme');
@@ -15450,7 +16315,7 @@ self.addEventListener('fetch', function (e) {
15450
16315
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
15451
16316
  }
15452
16317
  })();
15453
- `,rl=`
16318
+ `,Xl=`
15454
16319
  (function () {
15455
16320
  var msg = document.getElementById('msg');
15456
16321
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -15467,7 +16332,7 @@ self.addEventListener('fetch', function (e) {
15467
16332
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
15468
16333
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
15469
16334
  })();
15470
- `,ol=`
16335
+ `,Kl=`
15471
16336
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
15472
16337
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
15473
16338
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -15479,7 +16344,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
15479
16344
  .card h1 { font-size: 22px; margin: 0 0 12px; }
15480
16345
  .muted { color: var(--ax-text-2); }
15481
16346
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
15482
- `,sl=`
16347
+ `,Jl=`
15483
16348
  body { display: flex; flex-direction: column; }
15484
16349
  .bar {
15485
16350
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -15516,21 +16381,38 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
15516
16381
  }
15517
16382
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
15518
16383
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
15519
- `;var dr="agentx_app",il=400*86400;async function cr(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new V;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ce(e,200,"application/manifest+json",sr());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ce(e,200,"text/javascript; charset=utf-8",ir);if(a==="/app/icon-192.png")return ce(e,200,"image/png",Ct(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ce(e,200,"image/png",Ct(512),"public, max-age=86400");if(a==="/app/pair")return ce(e,200,"text/html; charset=utf-8",rr())}if(n==="POST"&&a==="/api/app/session"){let i=lr(Mt(t),o);return i?(e.setHeader("Set-Cookie",`${dr}=${Mt(t)}; Path=/; Max-Age=${il}; HttpOnly; Secure; SameSite=Strict`),Ae(e,200,{device:i.name})):Ae(e,401,{error:"invalid or revoked device token"})}let s=lr(ll(t),o);return s?n==="GET"&&a==="/app"?ce(e,200,"text/html; charset=utf-8",nr()):n==="GET"&&a==="/api/app/me"?Ae(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Zn(t,e,a,n,s.name,r.fleet)?!0:Ae(e,404,{error:"not found"}):a==="/app"?ce(e,401,"text/html; charset=utf-8",or()):Ae(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function lr(t,e){if(!t)return null;let a=e.verify(t);return a&&me(a,"app")?a:null}function ll(t){return Mt(t)??dl(t,dr)}function Mt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function dl(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function ce(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ae(t,e,a){return ce(t,e,"application/json",JSON.stringify(a))}function lu(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let y of a)try{s.set(y.id,wl(y,t))}catch(S){console.error(` Board "${y.id}" failed to initialize: ${S.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Me(process.cwd(),t.workflows.dir):void 0,d=new Ht(l?{baseDir:l}:void 0),p=new Bt(l?{baseDir:l,nodeId:i}:{nodeId:i}),m=new zt(l?{baseDir:l}:void 0);wn(t),Yt({business:t.business?.enabled===!0}),cl(async(y,S)=>{try{await xl(y,S,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:m})}catch(w){v(S,500,{error:w.message||"internal error"})}}).listen(n,r,()=>{let y=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
16384
+ `;var zr="agentx_app",Vl=400*86400;async function qr(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Q;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",Hr());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",Bt);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Ot(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Ot(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",Or())}if(n==="POST"&&a==="/api/app/session"){let i=Br(qt(t),o);return i?(e.setHeader("Set-Cookie",`${zr}=${qt(t)}; Path=/; Max-Age=${Vl}; HttpOnly; Secure; SameSite=Strict`),Re(e,200,{device:i.name})):Re(e,401,{error:"invalid or revoked device token"})}let s=Br(Yl(t),o);return s?n==="GET"&&a==="/app"?fe(e,200,"text/html; charset=utf-8",Nr()):n==="GET"&&a==="/api/app/me"?Re(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await yr(t,e,a,n,s.name,r.fleet)||r.push&&await kr(t,e,a,n,s,r.push)||r.chat&&await Tr(t,e,a,n,s,r.chat)?!0:Re(e,404,{error:"not found"}):a==="/app"?fe(e,401,"text/html; charset=utf-8",Dr()):Re(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function Br(t,e){if(!t)return null;let a=e.verify(t);return a&&ge(a,"app")?a:null}function Yl(t){return qt(t)??Ql(t,zr)}function qt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ql(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Re(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Zl}from"crypto";var Ce={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},ed=/^c[a-z0-9]{8,32}$/;function td(t){return ed.test(t)}var ot=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
16385
+ id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
16386
+ node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
16387
+ created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
16388
+ CREATE INDEX IF NOT EXISTS app_chat_conversations_device ON app_chat_conversations(device_id, updated_at);
16389
+ CREATE TABLE IF NOT EXISTS app_chat_messages (
16390
+ id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id TEXT NOT NULL, role TEXT NOT NULL,
16391
+ content TEXT NOT NULL, status TEXT, error TEXT, ui TEXT, tools TEXT, at INTEGER NOT NULL);
16392
+ CREATE INDEX IF NOT EXISTS app_chat_messages_conversation ON app_chat_messages(conversation_id, id);`)}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${Zl(4).toString("hex")}`,s={id:o,title:nd(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
16393
+ (id, device_id, title, node, node_name, agent, agent_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,s.title,s.node,s.nodeName,s.agent,s.agentName??null,r,r),this.pruneDevice(e),s}get(e,a){if(!td(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(ad);return{...Ur(n),messages:r}}list(e,a=Ce.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
16394
+ (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
16395
+ (SELECT substr(m.content, 1, 240) FROM app_chat_messages m WHERE m.conversation_id = c.id ORDER BY m.id DESC LIMIT 1) AS last
16396
+ FROM app_chat_conversations c WHERE c.device_id = ? ORDER BY c.updated_at DESC, c.rowid DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>{let o=typeof r.last=="string"?r.last.replace(/\s+/g," ").trim().slice(0,120):"";return{...Ur(r),messages:r.n,...o?{last:o}:{}}})}append(e,a,n){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return!1;let o=n.content.length>Ce.content?n.content.slice(0,Ce.content)+`
16397
+
16398
+ [Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,Ce.toolsPerMessage);return this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, at)
16399
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,o,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,s?.length?JSON.stringify(s):null,n.at),this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
16400
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ce.messagesPerConversation),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),!0}pruneDevice(e){let a=this.db.prepare(`SELECT id FROM app_chat_conversations WHERE device_id = ?
16401
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ce.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function Ur(t){return{id:t.id,title:t.title,node:t.node,nodeName:t.node_name,agent:t.agent,...t.agent_name?{agentName:t.agent_name}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function ad(t){let e=r=>{if(r)try{return JSON.parse(r)}catch{return}},a=e(t.ui),n=e(t.tools);return{role:t.role,content:t.content,at:t.at,...t.status?{status:t.status}:{},...t.error?{error:t.error}:{},...a?{ui:a}:{},...n?{tools:n}:{}}}function nd(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function Bm(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let y of a)try{s.set(y.id,hd(y,t))}catch(w){console.error(` Board "${y.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Pe(process.cwd(),t.workflows.dir):void 0,d=new Zt(l?{baseDir:l}:void 0),p=new ea(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new ta(l?{baseDir:l}:void 0);Bn(t),fa({business:t.business?.enabled===!0}),rd(async(y,w)=>{try{await pd(y,w,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(T){b(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let y=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
15520
16402
  Live dashboard: http://${y}:${n}
15521
16403
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
15522
16404
  Kanban dashboard: http://${y}:${n}
15523
- `),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 gl=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function xl(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(Jt(t.headers)==="foreign"&&Vt(o)){v(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await cr(t,e,r,o,{nodeName:a.config.node?.name,fleet:$l(a.config)}))return;if(o==="GET"&&gl.has(r)&&ga("page",r),o==="GET"&&r==="/"){let c=ca();if(!c.configExists||c.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Et({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Un({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Et({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await pe(a.config);if(!c){v(e,503,{error:"no node available"});return}let u=await new Promise(g=>{let b="";t.on("data",x=>b+=x),t.on("end",()=>g(b)),t.on("error",()=>g(""))}),f=await fetch(c.url+r,{method:"POST",headers:{"Content-Type":"application/json",...c.token?{Authorization:`Bearer ${c.token}`}:{}},body:u||"{}"});e.writeHead(f.status,{"Content-Type":"application/json"}),e.end(await f.text())}catch(c){v(e,502,{error:"could not reach the node",message:String(c?.message||c)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let c=await pe(a.config),u=o==="POST"?void 0:n.searchParams.get("node"),f=o==="POST"?await le(t):void 0,g=f?.node??u,b=g?c.find(M=>M.url===g):c[0];if(!b){v(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",k=await fetch(b.url+r+x,{method:o,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}},...o==="POST"?{body:JSON.stringify({...f,node:void 0})}:{}});v(e,k.status,await k.json().catch(()=>({error:`HTTP ${k.status}`})))}catch(c){v(e,502,{error:"could not reach the node",message:c?.message||String(c)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let c=await le(t),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${f}/api/workflows/editor/chat`,{method:"POST",headers:u,body:JSON.stringify(c??{})}),b=await g.json().catch(()=>({error:`HTTP ${g.status}`}));v(e,g.status,b)}catch(c){v(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await pe(a.config);if(!c){v(e,200,{configured:!1,workflows:[]});return}let u=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});v(e,u.status,await u.json().catch(()=>({configured:!1,workflows:[]})))}catch{v(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ta({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ea({peers:O(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wa({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,u=setTimeout(()=>c.abort(),8e3);try{let f=Ft(await pe(a.config,c.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(f.map(async A=>{try{let _=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!_.ok)throw new Error(`HTTP ${_.status}`);return{name:A.name,url:A.url,ok:!0,data:await _.json()}}catch(_){return{name:A.name,url:A.url,ok:!1,error:_.message}}}));v(e,200,{nodes:M});return}let g=f.find(M=>M.url===n.searchParams.get("node"));if(!g){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 qt(t)):void 0,k=await fetch(g.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:c.signal,headers:{"Content-Type":"application/json",...g.token?{Authorization:`Bearer ${g.token}`}:{}}});v(e,k.status,await k.json())}catch(f){v(e,502,{error:f.message})}finally{clearTimeout(u)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bn({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wn({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gn({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xn({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(da({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let c=n.searchParams.get("agent")||"",u=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!c){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Kn({taskId:decodeURIComponent(i[1]),agentId:c,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:u,peers:O(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Jn({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){pa(t,e);return}if(o==="POST"&&r==="/api/setup"){await ua(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await ma(t,e);return}if(o==="GET"&&r==="/admin"){$a(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Fa(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Na(t,e,O(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Va(t,e,O(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let c=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(c==="fleet"){if(r==="/api/admin/activity-graph"){await Dl(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await _t(t,e,r,f=>gr(f,a.config));return}let u=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(u){let f=decodeURIComponent(u[1]),g=f.indexOf("::");if(g>0){let b=f.slice(0,g),x=f.slice(g+2),k=a.config.node?.id||a.config.node?.name||"local";if(b===k)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=Ie(M.url.replace(/\/+$/,""),a.config);if(A){await ur(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(c&&c!=="primary"){let u=Ie(c,a.config);if(!u){v(e,404,{error:`unknown peer: ${c}`});return}let f=(n.search||"").replace(/[?&]peer=[^&]*/g,b=>b.startsWith("?")?"?":"");await ur(t,e,u,r+(f==="?"?"":f));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ya(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Nl(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-J6RCHFVE.js"),f=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",g=await c({running:f});v(e,200,g)}catch(c){v(e,500,{error:c?.message||String(c)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(tn({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await en(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(an({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(nn({peers:O(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await _l(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 kn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await _t(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Sn(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){Cn(t,e,d[1],O(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let c=t.headers.authorization||"",u=c.startsWith("Bearer ")?c.slice(7):"";if(u!==a.token){let f=new V,g=u?f.verify(u):null;if(!g||!me(g,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ja(t,e);return}if(r.startsWith("/api/admin/approvals")){await Ua(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await Ha(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await An(t,e,r);return}if(r.startsWith("/api/admin/")){await La(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(Ca);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){v(e,400,{error:"invalid asset name"});return}let u=Pl("web/"+c);try{let f=await Ol(u),g=c.endsWith(".map")?"application/json; charset=utf-8":c.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",b=n.searchParams.has("v");e.writeHead(200,{"Content-Type":g,"Cache-Control":b?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(f)}catch{v(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await Qe(a.config);v(e,200,c)}catch(c){v(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let c=n.searchParams.get("date")||new Date().toISOString().slice(0,10),u=n.searchParams.get("timezone")||"UTC",f=await Qe(a.config,{date:c,timezone:u});v(e,200,f)}catch(c){v(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(u,f,g,b)=>{let x=parseInt(n.searchParams.get(u)||"",10);return Number.isFinite(x)?Math.max(g,Math.min(b,x)):f};try{let u=await pe(a.config);v(e,200,await zn(u,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(u){v(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let c=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(c)){v(e,400,{error:"day=YYYY-MM-DD query param required"});return}let u=(f,g,b,x)=>{let k=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(k)?Math.max(b,Math.min(x,k)):g};try{let f=await pe(a.config);v(e,200,await Fn(f,{day:c,tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",40,1,200)}))}catch(f){v(e,502,{error:f.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let c=n.searchParams.get("node");if(!c){v(e,400,{error:"node query param required"});return}let u=n.searchParams,f;if(r==="/api/mesh/thread"){let[g,b,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!g||!b||!x){v(e,400,{error:"agent, channel, chat required"});return}f=`/analytics/thread?agent=${encodeURIComponent(g)}&channel=${encodeURIComponent(b)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[g,b]=[u.get("kind"),u.get("key")];if(!g||!b){v(e,400,{error:"kind and key required"});return}f=`/analytics/job?kind=${encodeURIComponent(g)}&key=${encodeURIComponent(b)}&limit=${encodeURIComponent(u.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[g,b,x]=[u.get("agent"),u.get("channel"),u.get("chat")];if(!g||!b||!x){v(e,400,{error:"agent, channel, chat required"});return}f=`/analytics/conversation?agent=${encodeURIComponent(g)}&channel=${encodeURIComponent(b)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(u.get("tzOffset")||"0")}`}else{let g=u.get("task");if(!g){v(e,400,{error:"task required"});return}f=`/analytics/run/${encodeURIComponent(g)}`}try{await qn(e,await pe(a.config),c,f)}catch(g){v(e,502,{error:g.message})}return}if(o==="GET"&&r==="/api/live/stream"){El(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let c=new URL(t.url||"/","http://localhost"),u=c.searchParams.get("node"),f=c.searchParams.get("agent"),g=c.searchParams.get("task");if(!u||!f||!g){v(e,400,{error:"node, agent, task query params required"});return}await Tl(t,e,a,u,f,g);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),u=c.searchParams.get("node"),f=c.searchParams.get("agent"),g=c.searchParams.get("task"),b=c.searchParams.get("limit")||"50";if(!u||!f){v(e,400,{error:"node and agent query params required"});return}await Ml(e,a,u,f,g,b);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),u=c.searchParams.get("node"),f=c.searchParams.get("task"),g=c.searchParams.get("kind");if(!u||!f||g!=="cancel"&&g!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Il(t,e,a,u,f,g);return}if(o==="POST"&&r==="/api/voice/stop"){let c=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!c){v(e,400,{error:"node query param required"});return}await Lt(t,e,a,c,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:c});if(!u.ok)throw new Error(`HTTP ${u.status}`);let f=await u.json();v(e,200,f)}catch(c){v(e,502,{error:c.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let u=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:c});if(!u.ok){v(e,u.status,{error:`HTTP ${u.status}`});return}v(e,200,await u.json())}catch(c){v(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await le(t);try{let u=await Ll(a.config,c);v(e,200,u)}catch(u){v(e,502,{error:u.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let c=p[1];if(!Cl(t,e,[`agent:${c}`]))return;await Al(t,e,a.config,c);return}if(r.startsWith("/api/")&&a.token){let c=t.headers.authorization||"",u=c.startsWith("Bearer ")?c.slice(7):"";if(u!==a.token){let f=new V,g=u?f.verify(u):null;if(!g||!me(g,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){v(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let c=n.searchParams.get("node");if(!c){v(e,400,{error:"node query param required"});return}await Lt(t,e,a,c,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let u=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let f=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(k=>({name:k.name,url:k.url,token:k.token}))],g={flag:!1},b=[];t.on("close",()=>{g.flag=!0;for(let k of b)try{k.abort()}catch{}});let x=setInterval(()=>{if(!g.flag)try{e.write(`: ping
16405
+ `),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var cd=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function pd(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ua(t.headers)==="foreign"&&ma(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await qr(t,e,r,o,{nodeName:a.config.node?.name,fleet:Kr(a.config),push:$d(a.config),chat:Ld(a.config)}))return;if(o==="GET"&&cd.has(r)&&Pa("page",r),o==="GET"&&r==="/"){let c=Ma();if(!c.configExists||c.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pt({peers:N(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pr({peers:N(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pt({peers:N(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await he(a.config);if(!c){b(e,503,{error:"no node available"});return}let m=await new Promise(x=>{let k="";t.on("data",v=>k+=v),t.on("end",()=>x(k)),t.on("error",()=>x(""))}),h=await fetch(c.url+r,{method:"POST",headers:{"Content-Type":"application/json",...c.token?{Authorization:`Bearer ${c.token}`}:{}},body:m||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(c){b(e,502,{error:"could not reach the node",message:String(c?.message||c)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let c=await he(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await pe(t):void 0,x=h?.node??m,k=x?c.find(M=>M.url===x):c[0];if(!k){b(e,400,{error:"unknown node"});return}let v=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",_=await fetch(k.url+r+v,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});b(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(c){b(e,502,{error:"could not reach the node",message:c?.message||String(c)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let c=await pe(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await he(a.config);if(!c){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wa({peers:N(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fa({peers:N(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ba({peers:N(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,m=setTimeout(()=>c.abort(),8e3);try{let h=na(await he(a.config,c.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(h.map(async A=>{try{let E=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:A.name,url:A.url,ok:!0,data:await E.json()}}catch(E){return{name:A.name,url:A.url,ok:!1,error:E.message}}}));b(e,200,{nodes:M});return}let x=h.find(M=>M.url===n.searchParams.get("node"));if(!x){b(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){b(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await aa(t)):void 0,_=await fetch(x.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:v,signal:c.signal,headers:{"Content-Type":"application/json",...x.token?{Authorization:`Bearer ${x.token}`}:{}}});b(e,_.status,await _.json())}catch(h){b(e,502,{error:h.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ir({peers:N(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({peers:N(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mr({peers:N(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fr({peers:N(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Aa({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let c=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!c){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hr({taskId:decodeURIComponent(i[1]),agentId:c,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers:N(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gr({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:N(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Ia(t,e);return}if(o==="POST"&&r==="/api/setup"){await $a(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await La(t,e);return}if(o==="GET"&&r==="/admin"){Va(t,e,N(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){dn(e,N(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){nn(t,e,N(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}gn(t,e,N(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let c=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(c==="fleet"){if(r==="/api/admin/activity-graph"){await Dd(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await jt(t,e,r,h=>Vr(h,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let h=decodeURIComponent(m[1]),x=h.indexOf("::");if(x>0){let k=h.slice(0,x),v=h.slice(x+2),_=a.config.node?.id||a.config.node?.name||"local";if(k===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===k);if(M){let A=Oe(M.url.replace(/\/+$/,""),a.config);if(A){await Wr(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}b(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=Oe(c,a.config);if(!m){b(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Wr(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await xn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Hd(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-IBWQVQV4.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:h});b(e,200,x)}catch(c){b(e,500,{error:c?.message||String(c)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wn({peers:N(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await yn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kn({peers:N(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({peers:N(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await xd(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){e.writeHead(302,{Location:"/activity?view=map"}),e.end();return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await zn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await jt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Un(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){Gn(t,e,d[1],N(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let c=t.headers.authorization||"",m=c.startsWith("Bearer ")?c.slice(7):"";if(m!==a.token){let h=new Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ya(t,e);return}if(r.startsWith("/api/admin/approvals")){await cn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await rn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Xn(t,e,r);return}if(r.startsWith("/api/admin/")){await Qa(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(Ga);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){b(e,400,{error:"invalid asset name"});return}let m=Nd("web/"+c);try{let h=await Od(m),x=c.endsWith(".map")?"application/json; charset=utf-8":c.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":x,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await Ne(a.config);b(e,200,c)}catch(c){b(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let c=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",h=await Ne(a.config,{date:c,timezone:m});b(e,200,h)}catch(c){b(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(m,h,x,k)=>{let v=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(v)?Math.max(x,Math.min(k,v)):h};try{let m=await he(a.config);b(e,200,await lr(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let c=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(c)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(h,x,k,v)=>{let _=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(_)?Math.max(k,Math.min(v,_)):x};try{let h=await he(a.config);b(e,200,await cr(h,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(h){b(e,502,{error:h.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let c=n.searchParams.get("node");if(!c){b(e,400,{error:"node query param required"});return}let m=n.searchParams,h;if(r==="/api/mesh/thread"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){b(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[x,k]=[m.get("kind"),m.get("key")];if(!x||!k){b(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(x)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){b(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let x=m.get("task");if(!x){b(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(x)}`}try{await dr(e,await he(a.config),c,h)}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Sd(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("agent"),x=c.searchParams.get("task");if(!m||!h||!x){b(e,400,{error:"node, agent, task query params required"});return}await Td(t,e,a,m,h,x);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("agent"),x=c.searchParams.get("task"),k=c.searchParams.get("limit")||"50";if(!m||!h){b(e,400,{error:"node and agent query params required"});return}await Md(e,a,m,h,x,k);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("task"),x=c.searchParams.get("kind");if(!m||!h||x!=="cancel"&&x!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Id(t,e,a,m,h,x);return}if(o==="POST"&&r==="/api/voice/stop"){let c=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!c){b(e,400,{error:"node query param required"});return}await Xt(t,e,a,c,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:c});if(!m.ok)throw new Error(`HTTP ${m.status}`);let h=await m.json();b(e,200,h)}catch(c){b(e,502,{error:c.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:c});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(c){b(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await pe(t);try{let m=await Rd(a.config,c);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let c=p[1];if(!Cd(t,e,[`agent:${c}`]))return;await Ad(t,e,a.config,c);return}if(r.startsWith("/api/")&&a.token){let c=t.headers.authorization||"",m=c.startsWith("Bearer ")?c.slice(7):"";if(m!==a.token){let h=new Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await bd(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let c=n.searchParams.get("node");if(!c){b(e,400,{error:"node query param required"});return}await Xt(t,e,a,c,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(_=>({name:_.name,url:_.url,token:_.token}))],x={flag:!1},k=[];t.on("close",()=>{x.flag=!0;for(let _ of k)try{_.abort()}catch{}});let v=setInterval(()=>{if(!x.flag)try{e.write(`: ping
15524
16406
 
15525
- `)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let k of f)(async()=>{let M={Accept:"text/event-stream"};k.token&&(M.Authorization=`Bearer ${k.token}`);let A=new AbortController;b.push(A);try{let _=await fetch(`${k.url.replace(/\/+$/,"")}/events${u?`?${u}`:""}`,{headers:M,signal:A.signal});if(!_.ok||!_.body)return;let I=_.body.getReader(),L=new TextDecoder,R="";for(;!g.flag;){let{done:H,value:ee}=await I.read();if(H)break;R+=L.decode(ee,{stream:!0});let B;for(;(B=R.indexOf(`
16407
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let _ of h)(async()=>{let M={Accept:"text/event-stream"};_.token&&(M.Authorization=`Bearer ${_.token}`);let A=new AbortController;k.push(A);try{let E=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:A.signal});if(!E.ok||!E.body)return;let I=E.body.getReader(),j=new TextDecoder,R="";for(;!x.flag;){let{done:B,value:te}=await I.read();if(B)break;R+=j.decode(te,{stream:!0});let z;for(;(z=R.indexOf(`
15526
16408
 
15527
- `))>=0;){let D=R.slice(0,B);if(R=R.slice(B+2),g.flag)break;try{e.write(D+`
16409
+ `))>=0;){let D=R.slice(0,z);if(R=R.slice(z+2),x.flag)break;try{e.write(D+`
15528
16410
 
15529
- `)}catch{g.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let c=new URL(t.url||"/","http://localhost"),u=Math.max(1,Math.min(500,Number(c.searchParams.get("limit")||50))),f=c.searchParams.get("workflowId")||void 0,g=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",b=a.workflowRuns.list({limit:u,workflowId:f}),x=`?limit=${u}${f?`&workflowId=${encodeURIComponent(f)}`:""}${g?"&summary=1":""}`,k=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],M=await Promise.all(k.map(async L=>{let R={};L.token&&(R.Authorization=`Bearer ${L.token}`);try{let H=new AbortController,ee=setTimeout(()=>H.abort(),5e3);try{let B=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:R,signal:H.signal});if(!B.ok)return[];let D=await B.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(ee)}}catch{return[]}})),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 _=Array.from(A.values()).sort((L,R)=>L.updatedAt<R.updatedAt?1:-1).slice(0,u),I=g?_.map(L=>yl(L)):_;v(e,200,{runs:I})}catch(c){v(e,502,{error:"runs fetch failed",message:c.message||String(c)})}return}let h=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(h){let c=decodeURIComponent(h[1]),u=a.workflowRuns.get(c);if(u){v(e,200,{run:u});return}let f=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(g=>({url:g.url,token:g.token}))];for(let g of f)try{let b={};g.token&&(b.Authorization=`Bearer ${g.token}`);let x=await fetch(`${g.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(c)}`,{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 c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let u=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${u}/api/actions/builtin`,{headers:c}),g=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,g)}catch(c){v(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let y=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(y){try{let c=await le(t).catch(()=>({})),u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${f}/workflows/${encodeURIComponent(y[1])}/run`,{method:"POST",headers:u,body:JSON.stringify(c??{})}),b=await g.json().catch(()=>({error:`HTTP ${g.status}`}));v(e,g.status,b)}catch(c){v(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&Yn(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(u,f,g)=>{if(a.token)return!0;let b=st(u);if(!b)return!0;let x=new V().verify(b);if(!x)return v(f,401,{error:"invalid or revoked token"}),!1;for(let k of g)if(!me(x,k))return v(f,403,{error:`token missing scope: ${k}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){v(e,200,a.boards.map(c=>({id:c.id,name:c.name,source:c.source,primaryToolLabel:c.primaryToolLabel,labels:c.labels,columns:c.columns,timeRangeDays:c.timeRangeDays})));return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(S&&o==="GET"){let c=a.sources.get(S[1]);if(!c){v(e,404,{error:"unknown board"});return}try{let u=typeof c.listMembers=="function"?await c.listMembers():[];v(e,200,u)}catch(u){v(e,502,{error:u.message})}return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(w&&o==="GET"){let c=a.sources.get(w[1]);if(!c){v(e,404,{error:"unknown board"});return}try{let u=typeof c.listMilestones=="function"?await c.listMilestones():[];v(e,200,u)}catch(u){v(e,502,{error:u.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,c,u]=E,f=decodeURIComponent(u),g=a.boards.find(A=>A.id===c);if(!g){v(e,404,{error:`unknown board: ${c}`});return}let b=a.sources.get(c);if(!b){v(e,503,{error:`board "${c}" source unavailable`});return}let x=await le(t),k=g.columns.find(A=>A.id===x.to),M=g.columns.find(A=>A.id===x.from);if(!k){v(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await bl(b,f,M,k),It({actor:$t(t),action:"move",boardId:c,itemId:f,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[,c,u]=T,f=u?decodeURIComponent(u):void 0,g=a.boards.find(x=>x.id===c);if(!g){v(e,404,{error:`unknown board: ${c}`});return}let b=a.sources.get(c);if(!b){v(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!f){let{columns:x,totals:k}=await vl(g,b,n.searchParams);v(e,200,{columns:x,totals:k});return}if(o==="GET"&&f){try{let x=typeof b.getItem=="function"?await b.getItem(f):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"&&f){let x=await le(t);try{let k=typeof b.updateItem=="function"?await b.updateItem(f,x):null;if(!k){v(e,501,{error:"update unsupported"});return}It({actor:$t(t),action:"update",boardId:c,itemId:f,payload:x}),v(e,200,k)}catch(k){v(e,502,{error:k.message})}return}if(o==="POST"&&!f){let x=await le(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 k=await b.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});It({actor:$t(t),action:"create",boardId:c,itemId:k.id,payload:{title:x.title}}),v(e,201,k)}catch(k){v(e,502,{error:k.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let c=r.replace(/^\/+|\/+$/g,""),f={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[c];if(f){e.writeHead(302,{Location:f}),e.end();return}}v(e,404,{error:"not found",path:r})}async function vl(t,e,a){if(!e.capabilities.listAll||!e.listAll){let c={};for(let u of t.columns)c[u.id]=[];return{columns:c,totals:Object.fromEntries(t.columns.map(u=>[u.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(c=>c.kind!=="closed"),m=t.columns.some(c=>c.kind==="closed"),h=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],y=m?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],S={};for(let c of t.columns)S[c.id]=[];let w=t.columns.find(c=>c.kind==="closed");for(let c of y)w&&S[w.id].push({...c,stage:w.id});let E=t.columns.filter(c=>c.kind!=="closed");for(let c of h){let u=Pt(c,E);if(!u)continue;let f=S[u];f&&f.push({...c,stage:u})}if(i)for(let c of Object.keys(S))S[c]=S[c].filter(u=>u.assignee===i);for(let c of Object.keys(S))S[c].sort((u,f)=>{let g=(u.priority??99)-(f.priority??99);return g!==0?g:(f.updatedAt||"").localeCompare(u.updatedAt||"")});let T=Object.fromEntries(Object.entries(S).map(([c,u])=>[c,u.length]));return{columns:S,totals:T}}async function bl(t,e,a,n){let r=Ot(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 yl(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 wl(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 Zt(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function It(t){try{let e=Me(process.cwd(),".agentx");mr(e)||ul(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
15530
- `;pl(Me(e,"board-audit.jsonl"),a)}catch{}}function $t(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function kl(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",[i,l,d,p,m,h,y]=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(!l||!l.ok)return o.error=l?`HTTP ${l.status}`:"unreachable",o;let S=await l.json();if(o.agents=S.map(w=>({id:w.id,name:w.name,tier:w.tier,model:w.model,skillCount:Number.isFinite(w.skillCount)?w.skillCount:void 0,active:w.active||0,total:w.total||0,errors:w.errors||0,lastActive:w.lastActive,lastSummary:w.lastSummary,hourlyTasks:Array.isArray(w.hourlyTasks)?w.hourlyTasks:void 0,runningTasks:Array.isArray(w.runningTasks)?w.runningTasks:[]})),i&&i.ok){let w=await i.json();o.uptimeSec=w.uptime,typeof w.inflight?.total=="number"&&(o.inflight=w.inflight.total),w.restart&&typeof w.restart.state=="string"&&(o.restart=w.restart),o.name=w.node?.name||w.node?.id||t,o.id=w.node?.id||t,w.usage&&(o.usage=w.usage)}if(p&&p.ok){let w=await p.json();o.crons=w.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 w=await m.json();o.cronRuns=Array.isArray(w.runs)?w.runs:[]}if(y&&y.ok){let w=await y.json().catch(()=>null);w&&Array.isArray(w.routines)&&(o.routines=w.routines.slice(0,Gt.routines))}if(h&&h.ok){let w=await h.json().catch(()=>null);w?.active&&w.kind==="lesson"&&(o.lesson={agentId:w.agentId??null,mode:String(w.mode||"teach"),goal:String(w.goal||""),step:Number(w.step)||0,saying:String(w.saying||""),startedAt:String(w.startedAt||"")})}o.reachable=!0,o._peers=Array.isArray(d&&await Sl(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Ye=null;function _l(t){if(Ye)return Ye;let e=Me(process.cwd(),".agentx/wiki");return Ye=ba({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Ye}var jt=new WeakMap;async function Sl(t){if(jt.has(t))return jt.get(t);try{let e=t.ok?await t.json():null;return jt.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 pe(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=ue(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:ue(a,l)})}let s=await Ze(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:ue(a,i.url)});return[...o.values()]}async function Qe(t,e){let a=new AbortController,n=setTimeout(()=>a.abort(),3e3);try{let r=await pe(t,a.signal),o=await Promise.all(r.map(s=>kl(s.url,s.token,a.signal,e)));return{ts:new Date().toISOString(),nodes:o}}finally{clearTimeout(n)}}function El(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=(i,l)=>{n||e.write(`event: ${i}
15531
- data: ${JSON.stringify(l)}
16411
+ `)}catch{x.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let c=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(c.searchParams.get("limit")||50))),h=c.searchParams.get("workflowId")||void 0,x=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:m,workflowId:h}),v=`?limit=${m}${h?`&workflowId=${encodeURIComponent(h)}`:""}${x?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(j=>({url:j.url,token:j.token}))],M=await Promise.all(_.map(async j=>{let R={};j.token&&(R.Authorization=`Bearer ${j.token}`);try{let B=new AbortController,te=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${j.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:R,signal:B.signal});if(!z.ok)return[];let D=await z.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(te)}}catch{return[]}})),A=new Map;for(let j of k)A.set(j.id,j);for(let j of M)for(let R of j)A.set(R.id,R);let E=Array.from(A.values()).sort((j,R)=>j.updatedAt<R.updatedAt?1:-1).slice(0,m),I=x?E.map(j=>fd(j)):E;b(e,200,{runs:I})}catch(c){b(e,502,{error:"runs fetch failed",message:c.message||String(c)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let c=decodeURIComponent(f[1]),m=a.workflowRuns.get(c);if(m){b(e,200,{run:m});return}let h=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))];for(let x of h)try{let k={};x.token&&(k.Authorization=`Bearer ${x.token}`);let v=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(c)}`,{headers:k});if(v.ok){b(e,200,await v.json());return}}catch{}b(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${m}/api/actions/builtin`,{headers:c}),x=await h.json().catch(()=>({error:`HTTP ${h.status}`}));b(e,h.status,x)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let y=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(y){try{let c=await pe(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${h}/workflows/${encodeURIComponent(y[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&vr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,h,x)=>{if(a.token)return!0;let k=gt(m);if(!k)return!0;let v=new Q().verify(k);if(!v)return b(h,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!ge(v,_))return b(h,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(e,200,a.boards.map(c=>({id:c.id,name:c.name,source:c.source,primaryToolLabel:c.primaryToolLabel,labels:c.labels,columns:c.columns,timeRangeDays:c.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let c=a.sources.get(w[1]);if(!c){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(T&&o==="GET"){let c=a.sources.get(T[1]);if(!c){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(g&&o==="PATCH"){let[,c,m]=g,h=decodeURIComponent(m),x=a.boards.find(A=>A.id===c);if(!x){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}let v=await pe(t),_=x.columns.find(A=>A.id===v.to),M=x.columns.find(A=>A.id===v.from);if(!_){b(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await md(k,h,M,_),Ut({actor:Ft(t),action:"move",boardId:c,itemId:h,payload:{from:v.from,to:v.to}}),b(e,200,{ok:!0})}catch(A){b(e,502,{error:A.message||"transition failed"})}return}if(S){let[,c,m]=S,h=m?decodeURIComponent(m):void 0,x=a.boards.find(v=>v.id===c);if(!x){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!h){let{columns:v,totals:_}=await ud(x,k,n.searchParams);b(e,200,{columns:v,totals:_});return}if(o==="GET"&&h){try{let v=typeof k.getItem=="function"?await k.getItem(h):null;if(!v){b(e,404,{error:"not found"});return}b(e,200,v)}catch(v){b(e,502,{error:v.message})}return}if(o==="PATCH"&&h){let v=await pe(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(h,v):null;if(!_){b(e,501,{error:"update unsupported"});return}Ut({actor:Ft(t),action:"update",boardId:c,itemId:h,payload:v}),b(e,200,_)}catch(_){b(e,502,{error:_.message})}return}if(o==="POST"&&!h){let v=await pe(t);if(!v.title){b(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){b(e,400,{error:`source ${k.type} does not support create`});return}try{let _=await k.create({title:v.title,description:v.description,labels:v.labels,assigneeUsernames:v.assigneeUsernames,milestoneTitle:v.milestoneTitle,projectHint:v.projectHint});Ut({actor:Ft(t),action:"create",boardId:c,itemId:_.id,payload:{title:v.title}}),b(e,201,_)}catch(_){b(e,502,{error:_.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let c=r.replace(/^\/+|\/+$/g,""),h={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[c];if(h){e.writeHead(302,{Location:h}),e.end();return}}b(e,404,{error:"not found",path:r})}async function ud(t,e,a){if(!e.capabilities.listAll||!e.listAll){let c={};for(let m of t.columns)c[m.id]=[];return{columns:c,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(c=>c.kind!=="closed"),u=t.columns.some(c=>c.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],y=u?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let c of t.columns)w[c.id]=[];let T=t.columns.find(c=>c.kind==="closed");for(let c of y)T&&w[T.id].push({...c,stage:T.id});let g=t.columns.filter(c=>c.kind!=="closed");for(let c of f){let m=Jt(c,g);if(!m)continue;let h=w[m];h&&h.push({...c,stage:m})}if(i)for(let c of Object.keys(w))w[c]=w[c].filter(m=>m.assignee===i);for(let c of Object.keys(w))w[c].sort((m,h)=>{let x=(m.priority??99)-(h.priority??99);return x!==0?x:(h.updatedAt||"").localeCompare(m.updatedAt||"")});let S=Object.fromEntries(Object.entries(w).map(([c,m])=>[c,m.length]));return{columns:w,totals:S}}async function md(t,e,a,n){let r=Vt(a,n),o=t;r.closeIssue&&typeof o.setState=="function"?await o.setState(e,"close"):r.reopen&&typeof o.setState=="function"&&await o.setState(e,"reopen"),(r.addLabels?.length||r.removeLabels?.length)&&typeof o.transitionMany=="function"?await o.transitionMany(e,r.addLabels||[],r.removeLabels||[]):r.addLabels?.length&&t.transition&&await t.transition(e,r.addLabels[0],r.removeLabels?.[0])}function fd(t){return{id:t.id,workflowId:t.workflowId,workflowVersion:t.workflowVersion,homeNode:t.homeNode,status:t.status,pending:t.pending,entityRef:t.entityRef,history:(t.history||[]).slice(-5),parentRunId:t.parentRunId,parentNodeId:t.parentNodeId,rootRunId:t.rootRunId,depth:t.depth,createdAt:t.createdAt,updatedAt:t.updatedAt}}function hd(t,e){if(t.source.type==="gitlab"){let a=e.channels.gitlab;if(!a?.token)throw new Error("channels.gitlab.token is required for gitlab boards");let n={};for(let r of a.agentMappings)r.gitlabUsernames.length&&(n[r.agentId]=r.gitlabUsernames);return new ga(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ut(t){try{let e=Pe(process.cwd(),".agentx");Gr(e)||sd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
16412
+ `;od(Pe(e,"board-audit.jsonl"),a)}catch{}}function Ft(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function gd(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",[i,l,d,p,u,f,y,w]=await Promise.all([fetch(t+"/health",{headers:r,signal:a}).catch(()=>null),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),fetch(t+"/mesh",{headers:r,signal:a}).catch(()=>null),fetch(t+"/crons",{headers:r,signal:a}).catch(()=>null),fetch(t+"/crons/runs"+s,{headers:r,signal:a}).catch(()=>null),fetch(t+"/talk",{headers:r,signal:a}).catch(()=>null),fetch(t+"/routines",{headers:r,signal:a}).catch(()=>null),fetch(t+"/attach/sessions",{headers:r,signal:a}).catch(()=>null)]);if(!l||!l.ok)return o.error=l?`HTTP ${l.status}`:"unreachable",o;let T=await l.json();if(o.agents=T.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),i&&i.ok){let g=await i.json();o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(p&&p.ok){let g=await p.json();o.crons=g.map(S=>({id:S.id,enabled:S.enabled===!0,schedule:String(S.schedule||""),timezone:S.timezone,agent:String(S.agent||""),kind:typeof S.command=="string"&&S.command.trim()?"command":"agent",model:S.model,nextRun:S.nextRun,retryPending:S.retryPending===!0,consecutiveErrors:Number(S.consecutiveErrors)||0}))}if(u&&u.ok){let g=await u.json();o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(y&&y.ok){let g=await y.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,ia.routines))}if(f&&f.ok){let g=await f.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Ed(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await vd(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var st=null;function xd(t){if(st)return st;let e=Pe(process.cwd(),".agentx/wiki");return st=Da({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),st}var Wt=new WeakMap;async function vd(t){if(Wt.has(t))return Wt.get(t);try{let e=t.ok?await t.json():null;return Wt.set(t,e),e}catch{return null}}async function lt(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function bd(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||se(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function he(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=se(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:se(a,l)})}let s=await lt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:se(a,i.url)});return[...o.values()]}var yd=3e3,wd=6e3,kd=5*6e4,Gt=new Map,it=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=it.get(a);if(n)return n;let r=(async()=>{let o=await he(t,AbortSignal.timeout(yd)),s=await Promise.all(o.map(async i=>{let l=await gd(i.url,i.token,AbortSignal.timeout(wd),e);return e?l:_d(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>it.delete(a));return it.set(a,r),r}function _d(t,e,a=Date.now()){if(e.reachable&&!e.error)return Gt.set(t,{node:e,at:a}),e;let n=Gt.get(t);return!n||a-n.at>kd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function zm(){Gt.clear(),it.clear()}function Ed(t,e,a){let n=s=>s?s.replace(/\/+$/,"").split("/").pop()||s:"",r=e.map(s=>({session:String(s.sessionId).slice(0,8),project:n(s.cwd),agentIds:Array.isArray(s.agentIds)?s.agentIds:[],mode:String(s.mode||"notify"),lastSeenAt:Number(s.lastSeenAt)||0,pending:Number(s.pending)||0})),o=new Set(e.map(s=>s.sessionId));for(let[s,i]of Object.entries(a))o.has(s)||!Array.isArray(i.agentIds)||i.agentIds.length===0||r.push({session:s.slice(0,8),project:n(i.cwd),agentIds:i.agentIds,mode:String(i.mode||"notify"),lastSeenAt:Number(i.savedAt)||0,pending:0,waiting:!0});t.attachSessions=r;for(let s of t.agents){let i=r.find(l=>l.agentIds.includes(s.id)&&!l.waiting)??r.find(l=>l.agentIds.includes(s.id));i&&(s.attached={session:i.session,project:i.project,mode:i.mode,lastSeenAt:i.lastSeenAt,waiting:i.waiting})}}function Sd(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,d)=>{n||e.write(`event: ${l}
16413
+ data: ${JSON.stringify(d)}
15532
16414
 
15533
- `)},o=async()=>{try{let i=await Qe(a);r("snapshot",i)}catch(i){r("error",{message:i.message})}};o();let s=setInterval(o,2e3);t.on("close",()=>{n=!0,clearInterval(s),e.end()})}async function Tl(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let S of a.config.dashboard.daemons)i.add(S.url.replace(/\/+$/,""));try{let S=await Ze(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let w of S)i.add(w.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){v(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=ue(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,m;try{m=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(S){v(e,502,{error:S.message||"upstream connect failed"});return}if(!m.ok||!m.body){v(e,m.status||502,{error:`upstream HTTP ${m.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let h=m.body.getReader();(async()=>{try{for(;;){let{value:S,done:w}=await h.read();if(w)break;S&&e.write(S)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Cl(t,e,a){let n=st(t);if(!n)return v(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new V().verify(n);if(!r)return v(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!me(r,o))return v(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Al(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 le(t)}catch{v(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){v(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(d){v(e,502,{error:d.message||"upstream call failed"})}}async function Ml(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let m of e.config.dashboard.daemons)i.add(m.url.replace(/\/+$/,""));try{let m=await Ze(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let h of m)i.add(h.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){v(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=ue(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let m=await fetch(`${s}${p}`,{headers:d}),h=await m.text();t.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(h)}catch(m){v(t,502,{error:m.message||"upstream fetch failed"})}}async function Il(t,e,a,n,r,o){await Lt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Lt(t,e,a,n,r){let o={};try{o=await le(t)??{}}catch{}let s=await hr(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function hr(t,e,a,n){let r=(d,p)=>({status:d,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await Ze(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of d)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=ue(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function $l(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Qe(t,n),async nodePost(n,r,o){let s=await hr(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=je({root:process.cwd()}).items.map(pr)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=Ie(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let d=await l.json();s.items=(d.items??[]).map(pr)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let d=be(),p=await Le({root:process.cwd()},r,o,{laterHours:d.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=Ie(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let d=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:d.status,body:a(await d.text())}}catch(d){return{status:502,body:{error:d.message||"peer dashboard unreachable"}}}}}}function pr(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var jl=`
16415
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ne(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}finally{o=!1}}};s();let i=setInterval(s,2e3);t.on("close",()=>{n=!0,clearInterval(i),e.end()})}async function Td(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await lt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(w){b(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:T}=await f.read();if(T)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Cd(t,e,a){let n=gt(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Q().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ge(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Ad(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await pe(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(d){b(e,502,{error:d.message||"upstream call failed"})}}async function Md(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await lt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:d}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){b(t,502,{error:u.message||"upstream fetch failed"})}}async function Id(t,e,a,n,r,o){await Xt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Xt(t,e,a,n,r){let o={};try{o=await pe(t)??{}}catch{}let s=await Xr(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Xr(t,e,a,n){let r=(d,p)=>({status:d,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await lt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of d)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=se(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function $d(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=ca(e.keysFile);return{store:()=>{let r=ut();return r?new ka(r):null},publicKey:()=>pa(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Kr(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ne(t,n),async nodePost(n,r,o){let s=await Xr(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=He({root:process.cwd()}).items.map(Fr)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=Oe(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let d=await l.json();s.items=(d.items??[]).map(Fr)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let d=we(),p=await Be({root:process.cwd()},r,o,{laterHours:d.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=Oe(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let d=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:d.status,body:a(await d.text())}}catch(d){return{status:502,body:{error:d.message||"peer dashboard unreachable"}}}}}}function Ld(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=se(t.dashboard,e),n=Kr(t);return{store:()=>{let r=ut();return r?new ot(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ne(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s)}}function Fr(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var jd=`
15534
16416
  You are helping draft a new GitLab issue. Follow these conventions strictly.
15535
16417
 
15536
16418
  Title pattern:
@@ -15562,16 +16444,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
15562
16444
  Shape:
15563
16445
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
15564
16446
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
15565
- `;async function Ll(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):
16447
+ `;async function Rd(t,e){let a=(e?.rough||"").toString().trim();if(!a)throw new Error("rough description required");let n=e?.agent||t.dashboard.draftAgent;if(!n)throw new Error("no draft agent configured (set dashboard.draftAgent or pass agent in body)");let r=e?.context||{},o=["Rough description from the user:",'"""',a,'"""',"",`Board: ${r.boardName||"(unspecified)"}`,r.primaryLabel?`Primary board label (include in labels): ${r.primaryLabel}`:"",r.columnLabel?`Target column label (include in labels): ${r.columnLabel}`:"",r.project?`GitLab project: ${r.project}`:"",r.knownLabels?.length?`Known labels in this project (prefer picking from these when they fit):
15566
16448
  - ${r.knownLabels.slice(0,60).join(`
15567
16449
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
15568
- `),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",i={"Content-Type":"application/json"};t.dashboard.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);let l=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:jl}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let p=(d.content||"").toString(),m=Rl(p);if(!m||typeof m.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let h=Array.isArray(m.labels)?m.labels.filter(y=>typeof y=="string"):[];return r.primaryLabel&&!h.includes(r.primaryLabel)&&h.unshift(r.primaryLabel),r.columnLabel&&!h.includes(r.columnLabel)&&h.unshift(r.columnLabel),{title:m.title.trim(),description:(m.description||"").toString(),labels:h,assigneeUsername:typeof m.assigneeUsername=="string"?m.assigneeUsername:void 0,kind:typeof m.kind=="string"?m.kind:void 0,raw:p}}function Rl(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 Pl(t){let e=fl(hl(import.meta.url));return Me(e,t)}async function Ol(t){return ml(t)}function v(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function le(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 fr(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function O(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:fr(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 Dl(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;v(e,200,await Ke(await gr(r,a.config)))}async function gr(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=kt(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=Ie(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let m=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return m.ok?{nodeId:i.name||i.url,snap:await m.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return yn(n)}async function Nl(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||"",h=[m&&`${m}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),y=h.find(S=>mr(S));if(!y){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:h}));return}r="tail",o=["-F","-n","200",y]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
16450
+ `),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",i={"Content-Type":"application/json"};t.dashboard.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);let l=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:jd}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let p=(d.content||"").toString(),u=Pd(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.labels.filter(y=>typeof y=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function Pd(t){if(!t)return null;try{return JSON.parse(t)}catch{}let e=t.match(/```(?:json)?\s*([\s\S]*?)```/);if(e)try{return JSON.parse(e[1])}catch{}let a=t.indexOf("{");if(a===-1)return null;let n=0;for(let r=a;r<t.length;r++){let o=t[r];if(o==="{")n++;else if(o==="}"&&(n--,n===0))try{return JSON.parse(t.slice(a,r+1))}catch{return null}}return null}function Nd(t){let e=dd(ld(import.meta.url));return Pe(e,t)}async function Od(t){return id(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function pe(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function Jr(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function N(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:Jr(s),tokenScope:s.dashboardToken||s.token?"proxy-ready":void 0})),o=r.length>0?[{id:"fleet",name:"Fleet (all peers)",dashboardUrl:"",tokenScope:"merged across nodes"}]:[];return[n,...r,...o]}async function Dd(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await tt(await Vr(r,a.config)))}async function Vr(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Lt(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=Oe(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Hn(n)}async function Hd(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),y=f.find(w=>Gr(w));if(!y){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:f}));return}r="tail",o=["-F","-n","200",y]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
15569
16451
 
15570
- `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=m=>{i+=m.toString("utf8");let h;for(;(h=i.indexOf(`
15571
- `))>=0;){let y=i.slice(0,h).replace(/\r$/,"");i=i.slice(h+1);try{e.write(`event: line
16452
+ `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
16453
+ `))>=0;){let y=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
15572
16454
  data: ${y.replace(/\n/g," ")}
15573
16455
 
15574
16456
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
15575
16457
 
15576
- `)}catch{}},15e3),p=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function ur(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((m,h)=>{let y=[];t.on("data",S=>y.push(S)),t.on("end",()=>m(Buffer.concat(y))),t.on("error",h)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let m=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),h=Buffer.from(await m.arrayBuffer());e.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(h)}catch(m){v(e,502,{error:`proxy to peer failed: ${m?.message||m}`,target:r})}}function Ie(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:fr(n),token:n.dashboardToken||n.token}:null}export{pe as resolveNodeTargets,lu as startBoardDashboard};
15577
- //# sourceMappingURL=board-dashboard-E3MUVNVQ.js.map
16458
+ `)}catch{}},15e3),p=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function Wr(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let y=[];t.on("data",w=>y.push(w)),t.on("end",()=>u(Buffer.concat(y))),t.on("error",f)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Oe(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Jr(n),token:n.dashboardToken||n.token}:null}export{Ed as applyAttachSessions,pd as handleBoardRequest,zm as resetLiveCaches,he as resolveNodeTargets,Bm as startBoardDashboard,_d as withLastGood};
16459
+ //# sourceMappingURL=board-dashboard-NRRYCDZW.js.map