agentix-cli 0.80.1 → 0.81.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/dist/{App-KVH5POXZ.js → App-HF6W6CV2.js} +2 -2
  2. package/dist/{App-KVH5POXZ.js.map → App-HF6W6CV2.js.map} +1 -1
  3. package/dist/ChatApp-74VBWP7R.js +7 -0
  4. package/dist/{ChatApp-LD4TXJWP.js.map → ChatApp-74VBWP7R.js.map} +1 -1
  5. package/dist/{agent-FUMJM6OW.js → agent-BDEPUFBQ.js} +2 -2
  6. package/dist/{board-dashboard-OS5J3F73.js → board-dashboard-TWEF5XVE.js} +186 -169
  7. package/dist/board-dashboard-TWEF5XVE.js.map +1 -0
  8. package/dist/{chunk-R42S57G6.js → chunk-4KJ3PCAI.js} +2 -2
  9. package/dist/{chunk-PE55MMLK.js → chunk-5GXCOHDM.js} +2 -2
  10. package/dist/{chunk-PE55MMLK.js.map → chunk-5GXCOHDM.js.map} +1 -1
  11. package/dist/{chunk-BJPIRNP6.js → chunk-74FSHUB3.js} +2 -2
  12. package/dist/{chunk-H7253EHW.js → chunk-ATXE3EMV.js} +2 -2
  13. package/dist/{chunk-TEFMZY6B.js → chunk-BB3ESU74.js} +2 -2
  14. package/dist/{chunk-XESESMKN.js → chunk-BDM4VTBR.js} +39 -39
  15. package/dist/{chunk-XESESMKN.js.map → chunk-BDM4VTBR.js.map} +1 -1
  16. package/dist/chunk-BYD5B3P3.js +9 -0
  17. package/dist/{chunk-Z3IP66SL.js.map → chunk-BYD5B3P3.js.map} +1 -1
  18. package/dist/chunk-EFV7U5LD.js +152 -0
  19. package/dist/chunk-EFV7U5LD.js.map +1 -0
  20. package/dist/chunk-ES7Z64Z5.js +22 -0
  21. package/dist/chunk-ES7Z64Z5.js.map +1 -0
  22. package/dist/{chunk-WP6KLXTP.js → chunk-GLQLCBJS.js} +4 -4
  23. package/dist/chunk-GLQLCBJS.js.map +1 -0
  24. package/dist/{chunk-UB63NQQL.js → chunk-GUAJNZIX.js} +2 -2
  25. package/dist/{chunk-UXSYVMPK.js → chunk-HUQRPEDP.js} +2 -2
  26. package/dist/{chunk-BEHC3X42.js → chunk-HYE2UUQ4.js} +242 -211
  27. package/dist/chunk-HYE2UUQ4.js.map +1 -0
  28. package/dist/chunk-JG3O5GL6.js +5 -0
  29. package/dist/{chunk-MOQNLS5Z.js.map → chunk-JG3O5GL6.js.map} +1 -1
  30. package/dist/chunk-JXF54PT7.js +2 -0
  31. package/dist/chunk-JXF54PT7.js.map +1 -0
  32. package/dist/chunk-LTHQXWZN.js +51 -0
  33. package/dist/chunk-LTHQXWZN.js.map +1 -0
  34. package/dist/{chunk-ZR3NZLJL.js → chunk-LUL4ILAQ.js} +2 -2
  35. package/dist/{chunk-N6EWZGIX.js → chunk-PN6XHTG5.js} +6 -6
  36. package/dist/{chunk-N6EWZGIX.js.map → chunk-PN6XHTG5.js.map} +1 -1
  37. package/dist/{chunk-7IGSJGXI.js → chunk-TW4L6RP2.js} +2 -2
  38. package/dist/chunk-UCKKAWLZ.js +2 -0
  39. package/dist/chunk-UCKKAWLZ.js.map +1 -0
  40. package/dist/{chunk-3UN6CXRL.js → chunk-VVW4JYV6.js} +24 -24
  41. package/dist/chunk-VVW4JYV6.js.map +1 -0
  42. package/dist/{chunk-BVZFYBBP.js → chunk-WWU2D65N.js} +2 -2
  43. package/dist/chunk-XF65CDNS.js +5 -0
  44. package/dist/{chunk-UR3ZIDMA.js.map → chunk-XF65CDNS.js.map} +1 -1
  45. package/dist/{chunk-YCI3KUYF.js → chunk-XQ7MVPWP.js} +7 -7
  46. package/dist/chunk-XQ7MVPWP.js.map +1 -0
  47. package/dist/{chunk-MYRSNJJ4.js → chunk-ZDDJNKU5.js} +2 -2
  48. package/dist/{chunk-Z3XUGXPD.js → chunk-ZUAV3PTL.js} +2 -2
  49. package/dist/cli.js +1 -1
  50. package/dist/cli.js.map +1 -1
  51. package/dist/client-JDY2FZUF.js +2 -0
  52. package/dist/config-JCETBKWT.js +2 -0
  53. package/dist/config-mutator-YQWTY47O.js +2 -0
  54. package/dist/doctor-6EWW7NC2.js +2 -0
  55. package/dist/{facts-U7BUYRXN.js → facts-5T5GRUTG.js} +6 -6
  56. package/dist/{facts-U7BUYRXN.js.map → facts-5T5GRUTG.js.map} +1 -1
  57. package/dist/{failure-candidates-RIXA3Y6D.js → failure-candidates-PBPF45GN.js} +2 -2
  58. package/dist/index.d.ts +619 -499
  59. package/dist/index.js +1 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/{chunk-AF46YOLU.js → program-FUYHN2F7.js} +194 -184
  62. package/dist/program-FUYHN2F7.js.map +1 -0
  63. package/dist/promote-ZZWMGVO2.js +2 -0
  64. package/dist/query-OQBB7EFS.js +2 -0
  65. package/dist/registry-PLSOZ3CL.js +2 -0
  66. package/dist/request-planner-HX44G2SX.js +2 -0
  67. package/dist/{request-planner-H74KHFGJ.js.map → request-planner-HX44G2SX.js.map} +1 -1
  68. package/dist/review-candidates-FBDLPU6H.js +4 -0
  69. package/dist/{review-candidates-IPJWEXR2.js.map → review-candidates-FBDLPU6H.js.map} +1 -1
  70. package/dist/routing-3SZHWHUA.js +2 -0
  71. package/dist/schedule-tool-5FULSHWJ.js +2 -0
  72. package/dist/scheduler-ITOKSMYT.js +2 -0
  73. package/dist/seat-2HJG3UNW.js +2 -0
  74. package/dist/select-UKAOL7QB.js +2 -0
  75. package/dist/{select-BUWOD47K.js.map → select-UKAOL7QB.js.map} +1 -1
  76. package/dist/set-enabled-ADFSNG5A.js +2 -0
  77. package/dist/{set-enabled-XWSFTICB.js.map → set-enabled-ADFSNG5A.js.map} +1 -1
  78. package/dist/signal-exit-WL7G3EEZ.js +2 -0
  79. package/dist/signal-exit-WL7G3EEZ.js.map +1 -0
  80. package/dist/{surface-usage-HVVP22SA.js → surface-usage-O5L4KLGS.js} +2 -2
  81. package/dist/{tool-VOA4HSVP.js → tool-MSXWU44P.js} +2 -2
  82. package/dist/{tool-VOA4HSVP.js.map → tool-MSXWU44P.js.map} +1 -1
  83. package/dist/{tool-GUINJ2BQ.js → tool-X7YEIJVZ.js} +2 -2
  84. package/dist/{tool-GUINJ2BQ.js.map → tool-X7YEIJVZ.js.map} +1 -1
  85. package/dist/wiki-QUVWB4IN.js +2 -0
  86. package/package.json +1 -1
  87. package/dist/ChatApp-LD4TXJWP.js +0 -7
  88. package/dist/board-dashboard-OS5J3F73.js.map +0 -1
  89. package/dist/chunk-3UN6CXRL.js.map +0 -1
  90. package/dist/chunk-42Y3BXXS.js +0 -15
  91. package/dist/chunk-42Y3BXXS.js.map +0 -1
  92. package/dist/chunk-6JJ3GODZ.js +0 -57
  93. package/dist/chunk-6JJ3GODZ.js.map +0 -1
  94. package/dist/chunk-AF46YOLU.js.map +0 -1
  95. package/dist/chunk-API4IZZG.js +0 -2
  96. package/dist/chunk-API4IZZG.js.map +0 -1
  97. package/dist/chunk-BEHC3X42.js.map +0 -1
  98. package/dist/chunk-MOQNLS5Z.js +0 -5
  99. package/dist/chunk-NOAAK2XI.js +0 -152
  100. package/dist/chunk-NOAAK2XI.js.map +0 -1
  101. package/dist/chunk-UR3ZIDMA.js +0 -5
  102. package/dist/chunk-WP6KLXTP.js.map +0 -1
  103. package/dist/chunk-YCI3KUYF.js.map +0 -1
  104. package/dist/chunk-Z3IP66SL.js +0 -9
  105. package/dist/client-TJ5YZOEE.js +0 -2
  106. package/dist/config-4WZ7Y34V.js +0 -2
  107. package/dist/config-mutator-5Z7EEB5N.js +0 -2
  108. package/dist/doctor-7K3NRBNN.js +0 -2
  109. package/dist/program-KMQNX6YK.js +0 -2
  110. package/dist/promote-NDC3X54P.js +0 -2
  111. package/dist/query-F7BD3JPE.js +0 -2
  112. package/dist/registry-5NBHBVY3.js +0 -2
  113. package/dist/request-planner-H74KHFGJ.js +0 -2
  114. package/dist/review-candidates-IPJWEXR2.js +0 -4
  115. package/dist/routing-3RSG7SKW.js +0 -2
  116. package/dist/schedule-tool-7NYAK43U.js +0 -2
  117. package/dist/scheduler-24O7PADJ.js +0 -2
  118. package/dist/seat-TOM2WHQR.js +0 -2
  119. package/dist/select-BUWOD47K.js +0 -2
  120. package/dist/set-enabled-XWSFTICB.js +0 -2
  121. package/dist/wiki-VFME4T2H.js +0 -2
  122. package/dist/wiki-VFME4T2H.js.map +0 -1
  123. /package/dist/{agent-FUMJM6OW.js.map → agent-BDEPUFBQ.js.map} +0 -0
  124. /package/dist/{chunk-R42S57G6.js.map → chunk-4KJ3PCAI.js.map} +0 -0
  125. /package/dist/{chunk-BJPIRNP6.js.map → chunk-74FSHUB3.js.map} +0 -0
  126. /package/dist/{chunk-H7253EHW.js.map → chunk-ATXE3EMV.js.map} +0 -0
  127. /package/dist/{chunk-TEFMZY6B.js.map → chunk-BB3ESU74.js.map} +0 -0
  128. /package/dist/{chunk-UB63NQQL.js.map → chunk-GUAJNZIX.js.map} +0 -0
  129. /package/dist/{chunk-UXSYVMPK.js.map → chunk-HUQRPEDP.js.map} +0 -0
  130. /package/dist/{chunk-ZR3NZLJL.js.map → chunk-LUL4ILAQ.js.map} +0 -0
  131. /package/dist/{chunk-7IGSJGXI.js.map → chunk-TW4L6RP2.js.map} +0 -0
  132. /package/dist/{chunk-BVZFYBBP.js.map → chunk-WWU2D65N.js.map} +0 -0
  133. /package/dist/{chunk-MYRSNJJ4.js.map → chunk-ZDDJNKU5.js.map} +0 -0
  134. /package/dist/{chunk-Z3XUGXPD.js.map → chunk-ZUAV3PTL.js.map} +0 -0
  135. /package/dist/{client-TJ5YZOEE.js.map → client-JDY2FZUF.js.map} +0 -0
  136. /package/dist/{config-4WZ7Y34V.js.map → config-JCETBKWT.js.map} +0 -0
  137. /package/dist/{config-mutator-5Z7EEB5N.js.map → config-mutator-YQWTY47O.js.map} +0 -0
  138. /package/dist/{doctor-7K3NRBNN.js.map → doctor-6EWW7NC2.js.map} +0 -0
  139. /package/dist/{failure-candidates-RIXA3Y6D.js.map → failure-candidates-PBPF45GN.js.map} +0 -0
  140. /package/dist/{program-KMQNX6YK.js.map → promote-ZZWMGVO2.js.map} +0 -0
  141. /package/dist/{promote-NDC3X54P.js.map → query-OQBB7EFS.js.map} +0 -0
  142. /package/dist/{query-F7BD3JPE.js.map → registry-PLSOZ3CL.js.map} +0 -0
  143. /package/dist/{registry-5NBHBVY3.js.map → routing-3SZHWHUA.js.map} +0 -0
  144. /package/dist/{routing-3RSG7SKW.js.map → schedule-tool-5FULSHWJ.js.map} +0 -0
  145. /package/dist/{schedule-tool-7NYAK43U.js.map → scheduler-ITOKSMYT.js.map} +0 -0
  146. /package/dist/{scheduler-24O7PADJ.js.map → seat-2HJG3UNW.js.map} +0 -0
  147. /package/dist/{seat-TOM2WHQR.js.map → surface-usage-O5L4KLGS.js.map} +0 -0
  148. /package/dist/{surface-usage-HVVP22SA.js.map → wiki-QUVWB4IN.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as kn}from"./chunk-2NYP4OQU.js";import{a as ce,b as wn}from"./chunk-JWDJMFU6.js";import{a as Cn}from"./chunk-CPXZWVKN.js";import{a as A,b as In,c as Mn,d as Rn,e as Ln,h as $n,i as we,j as Pn,k as jn,l as Nn,m as Dn,n as Hn}from"./chunk-3UN6CXRL.js";import{a as On}from"./chunk-Z3IP66SL.js";import{a as _n,b as U,c as Sn,d as R,i as ct,j as dt,k as re,l as W,m as pt,n as En,o as Tn,p as An}from"./chunk-O5U5NVLR.js";import{$ as on,$a as Le,Ga as dn,Ia as pn,Ja as un,K as qt,Ka as mn,L as tn,M as Ft,N as at,O as nt,R as an,S as nn,Sa as fn,T as rn,Ua as Re,Za as hn,_ as z,a as Xa,aa as sn,ab as rt,bb as ot,c as et,cb as st,d as Bt,db as it,e as Ka,eb as gn,fb as xn,gb as vn,hb as lt,i as tt,jb as bn,l as He,mb as yn,n as Ja,p as ne,q as ye,r as Qa,s as zt}from"./chunk-XESESMKN.js";import"./chunk-GTJIKXDB.js";import{g as Wa,h as Ga}from"./chunk-Z3XUGXPD.js";import{p as Va,t as Ya}from"./chunk-S2GAEH2F.js";import{a as O,b as ln,c as cn}from"./chunk-CL53UVOF.js";import"./chunk-BVZFYBBP.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as Za,c as en}from"./chunk-2D3RYIDU.js";import{A as Ua,a as Da,f as Ha,g as Dt,h as Ht,l as Ba,m as za,n as qa,x as Qe,y as Ze,z as le}from"./chunk-6JJ3GODZ.js";import{b as Fa}from"./chunk-API4IZZG.js";import"./chunk-WP6KLXTP.js";import{a as Me}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-TEFMZY6B.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-R42S57G6.js";import"./chunk-UR3ZIDMA.js";import"./chunk-H7253EHW.js";import"./chunk-ZR3NZLJL.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as Na}from"./chunk-UB63NQQL.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-PE55MMLK.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{F as ae,I as Nt,a as ja,b as Oa,c as li,v as Ye,w as ci}from"./chunk-42Y3BXXS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ut(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 Bn(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ut(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={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"/>'},ke=(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>",ut=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ke(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function zn(t={}){return R({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as A,b as Rn,c as Ln,d as $n,e as Pn,h as jn,i as we,j as On,k as Nn,n as Dn,o as Hn,p as zn,q as qn,r as Fn}from"./chunk-VVW4JYV6.js";import{a as Bn}from"./chunk-BYD5B3P3.js";import{a as Sn}from"./chunk-2NYP4OQU.js";import{a as ce,b as _n}from"./chunk-JWDJMFU6.js";import{a as Mn}from"./chunk-CPXZWVKN.js";import{a as En,b as U,c as Tn,d as R,i as ct,j as dt,k as re,l as W,m as pt,n as An,o as Cn,p as In}from"./chunk-O5U5NVLR.js";import{$ as ln,$a as Le,Ga as un,Ia as mn,Ja as fn,K as qt,Ka as hn,L as nn,M as Ft,N as at,O as nt,R as rn,S as on,Sa as gn,T as sn,Ua as Re,Za as xn,_ as z,a as Ja,aa as cn,ab as rt,bb as ot,c as et,cb as st,d as Bt,db as it,e as Va,eb as vn,fb as bn,gb as yn,hb as lt,i as tt,jb as wn,l as He,mb as kn,n as Ya,p as ne,q as ye,r as en,s as zt}from"./chunk-BDM4VTBR.js";import"./chunk-GTJIKXDB.js";import{g as Xa,h as Ka}from"./chunk-ZUAV3PTL.js";import{p as Qa,t as Za}from"./chunk-S2GAEH2F.js";import{a as O,b as dn,c as pn}from"./chunk-CL53UVOF.js";import"./chunk-WWU2D65N.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as tn,c as an}from"./chunk-2D3RYIDU.js";import{a as za,f as qa,g as Dt,h as Ht,l as Fa,m as Ua,n as Wa,u as Qe,v as Ze,w as le,x as Ga}from"./chunk-ES7Z64Z5.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-BB3ESU74.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-4KJ3PCAI.js";import"./chunk-XF65CDNS.js";import"./chunk-ATXE3EMV.js";import"./chunk-LUL4ILAQ.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as Ba}from"./chunk-GUAJNZIX.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-5GXCOHDM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{K as Ha,M as hi,a as ja,aa as ae,b as Oa,c as ui,da as Nt,v as Ye,w as mi}from"./chunk-LTHQXWZN.js";import{b as Na,h as fi}from"./chunk-UCKKAWLZ.js";import{a as Me,i as Da}from"./chunk-PN6XHTG5.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ut(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 Un(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ut(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={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"/>'},ke=(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>",ut=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ke(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Wn(t={}){return R({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
2
2
 
3
3
  <div class="bf-head">
4
4
  <div>
@@ -85,7 +85,7 @@ ${ut(oe.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:di,scripts:`<script>${U({decayOf:Ut,rankByDecay:Bn})}const ICON = ${JSON.stringify(oe)};${pi}</script>`})}var di=`
88
+ </div>`,css:gi,scripts:`<script>${U({decayOf:Ut,rankByDecay:Un})}const ICON = ${JSON.stringify(oe)};${xi}</script>`})}var gi=`
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
- }`,pi=String.raw`
364
+ }`,xi=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,13 +776,13 @@ 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 Wt(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=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,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=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,c)=>l+c.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,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function Gt(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 qn(t,e=[],a){let{bands:n,gaps:r}=Wt(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,m=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:c,track:0,left:m,width:h,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((c,p)=>Gt(l.runs.filter(u=>u.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as ui}from"crypto";import{readFileSync as mi,statSync as fi}from"fs";import{resolve as hi,dirname as gi}from"path";import{fileURLToPath as xi}from"url";var Fn=new Map;function mt(t){let e=Fn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=gi(xi(import.meta.url)),r=hi(n,"web",t),o=fi(r),s=o.size<8e6?ui("sha1").update(mi(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Fn.set(t,a),a}var de={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"/>'},ft=(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>",vi=[["agent","Agent",de.bot],["client","Client",de.user],["project","Project",de.folder],["channel","Channel",de.route],["node","Node",de.mesh]],Un={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 Wn(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return R({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function Wt(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=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,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=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,c)=>l+c.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,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function Gt(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 Gn(t,e=[],a){let{bands:n,gaps:r}=Wt(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,m=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:c,track:0,left:m,width:h,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((c,p)=>Gt(l.runs.filter(u=>u.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as vi}from"crypto";import{readFileSync as bi,statSync as yi}from"fs";import{resolve as wi,dirname as ki}from"path";import{fileURLToPath as _i}from"url";var Xn=new Map;function mt(t){let e=Xn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=ki(_i(import.meta.url)),r=wi(n,"web",t),o=yi(r),s=o.size<8e6?vi("sha1").update(bi(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Xn.set(t,a),a}var de={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"/>'},ft=(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>",Si=[["agent","Agent",de.bot],["client","Client",de.user],["project","Project",de.folder],["channel","Channel",de.route],["node","Node",de.mesh]],Kn={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 Jn(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return R({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">${Un[e]}</p>
785
+ <p class="ac-sub" id="sub">${Kn[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
@@ -799,7 +799,7 @@ 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
- ${vi.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${ft(o,13)}${r}</button>`).join("")}
802
+ ${Si.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${ft(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>
@@ -819,7 +819,7 @@ refresh();
819
819
  <div id="ax-fleet-root" data-hours="24" data-src="${mt("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:bi,scripts:`<script>${U({computeBands:Wt,packTracks:Gt,buildTimeline:qn})}const ICON = ${JSON.stringify(de)};const SUB = ${JSON.stringify(Un)};${yi}</script>`})}var bi=`
822
+ </div>`,css:Ei,scripts:`<script>${U({computeBands:Wt,packTracks:Gt,buildTimeline:Gn})}const ICON = ${JSON.stringify(de)};const SUB = ${JSON.stringify(Kn)};${Ti}</script>`})}var Ei=`
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
- `,yi=String.raw`
908
+ `,Ti=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 Gn(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return R({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:wi,scripts:`<script src="${mt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var wi=`
1025
+ `;function Vn(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return R({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ai,scripts:`<script src="${mt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Ai=`
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 Up}from"http";import{appendFileSync as Wp,existsSync as Zs,mkdirSync as Gp}from"fs";import{readFile as Xp}from"fs/promises";import{fileURLToPath as Kp}from"url";import{dirname as Jp,resolve as Je}from"path";li();var Xn='/*! 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 gt,readFileSync as tr,writeFileSync as ar,rmSync as tm,mkdirSync as Ai,copyFileSync as Ci,readdirSync as Ii}from"fs";import{resolve as $e}from"path";ci();function Jn(t){let e=Ye.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:Ye.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function ht(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=Ye.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var Kn=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Vn(t){return ht(e=>(typeof t?.enabled=="boolean"&&(e.enabled=t.enabled),typeof t?.allowAutoAck=="boolean"&&(e.allowAutoAck=t.allowAutoAck),t?.batchSeconds!==void 0&&(e.batchSeconds=Number(t.batchSeconds)),`WhatsApp triage ${e.enabled?"on":"off"}`))}function Yn(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return ht((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:Kn(t?.chats),senders:Kn(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function Qn(t){let e=String(t?.id??"");return ht(a=>{let n=a.rules.find(r=>r.id===e);if(!n)throw new Error(`Watch rule "${e}" not found.`);return typeof t?.patch?.enabled=="boolean"&&(n.enabled=t.patch.enabled),typeof t?.patch?.autoAck=="boolean"&&(n.autoAck=t.patch.autoAck),`updated watch rule "${e}"`})}function Zn(t){let e=String(t?.id??"");return ht(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}Nt();var pe={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 er(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ct({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.`})+dt([{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">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return R({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+_i()+En,css:Ei,scripts:`${e}<script>${Tn}
1047
- ${An}
1048
- ${ki}
1049
- ${Ti}</script>`})}var ki=`
1046
+ `;import{createServer as Vp}from"http";import{appendFileSync as Yp,existsSync as ni,mkdirSync as Qp}from"fs";import{readFile as Zp}from"fs/promises";import{fileURLToPath as eu}from"url";import{dirname as tu,resolve as Je}from"path";hi();ui();var Yn='/*! 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 gt,readFileSync as or,writeFileSync as sr,rmSync as im,mkdirSync as $i,copyFileSync as Pi,readdirSync as ji}from"fs";import{resolve as $e}from"path";mi();function Zn(t){let e=Ye.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:Ye.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function ht(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=Ye.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var Qn=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function er(t){return ht(e=>(typeof t?.enabled=="boolean"&&(e.enabled=t.enabled),typeof t?.allowAutoAck=="boolean"&&(e.allowAutoAck=t.allowAutoAck),t?.batchSeconds!==void 0&&(e.batchSeconds=Number(t.batchSeconds)),`WhatsApp triage ${e.enabled?"on":"off"}`))}function tr(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return ht((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:Qn(t?.chats),senders:Qn(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function ar(t){let e=String(t?.id??"");return ht(a=>{let n=a.rules.find(r=>r.id===e);if(!n)throw new Error(`Watch rule "${e}" not found.`);return typeof t?.patch?.enabled=="boolean"&&(n.enabled=t.patch.enabled),typeof t?.patch?.autoAck=="boolean"&&(n.autoAck=t.patch.autoAck),`updated watch rule "${e}"`})}function nr(t){let e=String(t?.id??"");return ht(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}Nt();var pe={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 rr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ct({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.`})+dt([{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">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return R({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ii()+An,css:Ri,scripts:`${e}<script>${Cn}
1047
+ ${In}
1048
+ ${Ci}
1049
+ ${Li}</script>`})}var Ci=`
1050
1050
  (function(){
1051
1051
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1052
1052
  async function voiceMissing() {
@@ -1140,8 +1140,8 @@ ${Ti}</script>`})}var ki=`
1140
1140
  refresh();
1141
1141
  // Refresh again after the main admin script has had a chance to mutate config.
1142
1142
  document.addEventListener('ax-config-saved', refresh);
1143
- })();`;function _i(){let t=cn().business?`<button data-tab="business">Business</button>
1144
- `:"";return Si.replace("__BUSINESS_TABS__",t)}var Si=`
1143
+ })();`;function Ii(){let t=pn().business?`<button data-tab="business">Business</button>
1144
+ `:"";return Mi.replace("__BUSINESS_TABS__",t)}var Mi=`
1145
1145
  <div id="peer-banner" class="peer-banner">
1146
1146
  <span class="label">Managing</span>
1147
1147
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -1800,7 +1800,7 @@ ${Ti}</script>`})}var ki=`
1800
1800
  <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>
1801
1801
  </section>
1802
1802
  </main>
1803
- `,Ei=`
1803
+ `,Ri=`
1804
1804
 
1805
1805
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
1806
1806
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -2008,7 +2008,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
2008
2008
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
2009
2009
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
2010
2010
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
2011
- `,Ti=`
2011
+ `,Li=`
2012
2012
  const $ = (id) => document.getElementById(id);
2013
2013
  let state = null;
2014
2014
 
@@ -3603,7 +3603,8 @@ function renderGitLabPane() {
3603
3603
  '<input id="gl-port" type="number" min="1" max="65535" value="' + (g.webhookPort || 18810) + '" />' +
3604
3604
  '<div class="actions"><button class="primary" onclick="configureGitLab()">' + (configured ? 'Save' : 'Connect') + '</button><div id="gl-msg" class="msg"></div></div>' +
3605
3605
  '<div class="hint-block">Per-project routes and per-agent tokens stay in the <b>Advanced</b> tab (raw JSON). Webhooks from GitLab are also registered in the <b>Webhooks</b> tab with source=<code>gitlab</code>.</div>' +
3606
- '</div>';
3606
+ '</div>' + requestStatusCard('gitlab', 'GitLab');
3607
+ wireRequestStatus('gitlab');
3607
3608
  const t = $('gl-toggle');
3608
3609
  if (t) t.addEventListener('change', async (e) => {
3609
3610
  try { await req('POST', '/api/admin/channels/gitlab/toggle', { enabled: e.target.checked }); refresh(); }
@@ -3638,7 +3639,23 @@ function renderGitHubPane() {
3638
3639
  $('ch-github').innerHTML =
3639
3640
  '<div class="hint-block" style="margin-bottom:14px">GitHub doesn&rsquo;t need a bot adapter \u2014 it speaks webhooks. Register one in the <b>Webhooks</b> tab with <code>source=github</code>, bind it to an agent, then paste the generated URL into the repo&rsquo;s <i>Settings \u2192 Webhooks</i>.</div>' +
3640
3641
  '<div class="list">' + hookList + '</div>' +
3641
- '<div class="actions"><button class="primary" onclick="jumpToWebhooks()">Add a GitHub webhook \u2192</button></div>';
3642
+ '<div class="actions"><button class="primary" onclick="jumpToWebhooks()">Add a GitHub webhook \u2192</button></div>' +
3643
+ requestStatusCard('github', 'GitHub');
3644
+ wireRequestStatus('github');
3645
+ }
3646
+ // Request status (#383): one comment per request, kept up to date by AgentX.
3647
+ function requestStatusCard(channel, label) {
3648
+ const on = (state.requestStatus || []).includes(channel);
3649
+ return '<div class="row-card" style="margin-top:12px"><div class="info"><h3>Request status</h3>' +
3650
+ '<div class="meta">When someone asks an agent for work on ' + label + ', AgentX posts one comment with the state of that request (queued, working, waiting, done, failed, timed out, cut off by a restart) and edits it as the work moves.</div></div>' +
3651
+ '<label class="toggle-switch" style="margin:0"><input type="checkbox" id="rs-' + channel + '"' + (on ? ' checked' : '') + ' /> <span>On</span></label></div>';
3652
+ }
3653
+ function wireRequestStatus(channel) {
3654
+ const t = $('rs-' + channel);
3655
+ if (t) t.addEventListener('change', async (e) => {
3656
+ try { await req('POST', '/api/admin/channels/request-status', { channel: channel, enabled: e.target.checked }); refresh(); }
3657
+ catch (err) { showMsg($('global-msg'), 'err', err.message); e.target.checked = !e.target.checked; }
3658
+ });
3642
3659
  }
3643
3660
  function jumpToWebhooks() {
3644
3661
  for (const btn of document.querySelectorAll('nav.tabs button')) {
@@ -4875,11 +4892,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
4875
4892
  })();
4876
4893
 
4877
4894
  refresh();
4878
- `;function nr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(er({peers:a,localToken:n}))}async function rr(t,e){let a=Jt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function or(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Fi(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Mi(t),r={"GET /api/admin/state":()=>Li(),"POST /api/admin/agents":()=>Di(n),"PATCH /api/admin/agents":()=>Hi(n),"DELETE /api/admin/agents":()=>Bi(n),"POST /api/admin/agents/access":()=>$i(n),"POST /api/admin/channels/telegram":()=>zi(n),"DELETE /api/admin/channels/telegram":()=>pl(n),"POST /api/admin/channels/telegram/toggle":()=>ul(n),"POST /api/admin/crons":()=>ml(n),"DELETE /api/admin/crons":()=>fl(n),"POST /api/admin/config/raw":()=>hl(n),"GET /api/admin/tokens":()=>Pi(),"POST /api/admin/tokens":()=>ji(n),"DELETE /api/admin/tokens":()=>Oi(n),"POST /api/admin/agents/test":()=>Ni(n),"POST /api/admin/agents/integrations":()=>Ji(n),"DELETE /api/admin/agents/integrations":()=>Vi(n),"PATCH /api/admin/agents/integrations":()=>Yi(n),"PATCH /api/admin/channels/telegram":()=>qi(n),"POST /api/admin/channels/slack":()=>rl(n),"POST /api/admin/channels/slack/toggle":()=>ol(n),"POST /api/admin/channels/discord":()=>sl(n),"POST /api/admin/channels/discord/toggle":()=>il(n),"POST /api/admin/channels/gitlab":()=>ll(n),"POST /api/admin/channels/gitlab/toggle":()=>cl(n),"GET /api/admin/channels/whatsapp/state":()=>Be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Be("/webrtc/history"),"POST /api/admin/actions":()=>Cl(n),"DELETE /api/admin/actions":()=>Il(n),"POST /api/admin/actions/run":()=>Ml(n),"GET /api/admin/channels/whatsapp/chats":()=>Be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>dl(n),"POST /api/admin/webhooks":()=>Qi(n),"PATCH /api/admin/webhooks":()=>Zi(n),"DELETE /api/admin/webhooks":()=>nl(n),"POST /api/admin/whatsapp-triage":()=>Vn(n),"POST /api/admin/whatsapp-triage/rules":()=>Yn(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Qn(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Zn(n),"POST /api/admin/mesh/peers":()=>el(n),"DELETE /api/admin/mesh/peers":()=>tl(n),"POST /api/admin/mesh/toggle":()=>al(n),"GET /api/admin/files":()=>Ui(t),"GET /api/admin/files/read":()=>Wi(t),"PUT /api/admin/files":()=>Gi(n),"POST /api/admin/files/skill":()=>Xi(n),"DELETE /api/admin/files/skill":()=>Ki(n),"POST /api/admin/business/orgchart":()=>gl(n),"DELETE /api/admin/business/orgchart":()=>xl(n),"POST /api/admin/business/project":()=>vl(n),"DELETE /api/admin/business/project":()=>wl(n),"POST /api/admin/business/client":()=>bl(n),"DELETE /api/admin/business/client":()=>yl(n),"POST /api/admin/business/contact":()=>kl(n),"DELETE /api/admin/business/contact":()=>_l(n),"POST /api/admin/boards":()=>Sl(n),"DELETE /api/admin/boards":()=>El(n),"POST /api/admin/boards/columns":()=>Tl(n),"DELETE /api/admin/boards/columns":()=>Al(n),"POST /api/admin/notifications":()=>Ll(n),"POST /api/admin/screen":()=>$l(n),"POST /api/admin/webhooks/triggers":()=>Pl(n),"POST /api/admin/mesh/health":()=>Rl(n),"GET /api/admin/projects":()=>Be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Xt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Xt(e,200,i)}catch(n){Xt(e,400,{error:n.message||"admin op failed"})}}function Xt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Mi(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 Ri(t){let e=$e(process.cwd(),t);if(!gt(e))return[];let a=[];for(let n of Ii(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(tr($e(e,n.name),"utf-8")))}catch{}return a}function Jt(){let t=$e(process.cwd(),"agentx.json");return gt(t)?JSON.parse(tr(t,"utf-8")):null}function Li(){let t=Jt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,f])=>({id:d,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let v=x.credentials||{},k={};for(let[b,S]of Object.entries(v))typeof S=="string"&&/^[A-Z][A-Z0-9_]*$/.test(S)?k[b]=process.env[S]?"set":"unset":typeof S=="string"&&(k[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:k,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,f])=>({id:d,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.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(([d,f])=>({id:d,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},w=t.notifications||{},_={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:Va(w.local),ntfy:Nn(t.channels?.ntfy)},E=[];try{E=Ri(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,whatsappTriage:Jn(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:bn(t.screen),actions:E}}function $i(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}=A(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 Pi(){return new ne().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 ji(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 ne().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Oi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ne().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ni(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=ae();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(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Di(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=ir(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=$e(process.cwd(),"agents",e),{summary:l}=A(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}"`}),c=$e(i,"CLAUDE.md");if(!gt(c))try{Ai(i,{recursive:!0}),ar(c,`# ${a}
4895
+ `;function ir(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rr({peers:a,localToken:n}))}async function lr(t,e){let a=Jt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function cr(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ji(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Oi(t),r={"GET /api/admin/state":()=>Di(),"POST /api/admin/agents":()=>Ui(n),"PATCH /api/admin/agents":()=>Wi(n),"DELETE /api/admin/agents":()=>Gi(n),"POST /api/admin/agents/access":()=>Hi(n),"POST /api/admin/channels/telegram":()=>Xi(n),"DELETE /api/admin/channels/telegram":()=>xl(n),"POST /api/admin/channels/telegram/toggle":()=>vl(n),"POST /api/admin/crons":()=>bl(n),"DELETE /api/admin/crons":()=>yl(n),"POST /api/admin/config/raw":()=>wl(n),"GET /api/admin/tokens":()=>Bi(),"POST /api/admin/tokens":()=>zi(n),"DELETE /api/admin/tokens":()=>qi(n),"POST /api/admin/agents/test":()=>Fi(n),"POST /api/admin/agents/integrations":()=>tl(n),"DELETE /api/admin/agents/integrations":()=>al(n),"PATCH /api/admin/agents/integrations":()=>nl(n),"PATCH /api/admin/channels/telegram":()=>Ki(n),"POST /api/admin/channels/slack":()=>dl(n),"POST /api/admin/channels/slack/toggle":()=>pl(n),"POST /api/admin/channels/discord":()=>ul(n),"POST /api/admin/channels/discord/toggle":()=>ml(n),"POST /api/admin/channels/gitlab":()=>fl(n),"POST /api/admin/channels/gitlab/toggle":()=>hl(n),"POST /api/admin/channels/request-status":()=>Hn(n),"GET /api/admin/channels/whatsapp/state":()=>Be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Be("/webrtc/history"),"POST /api/admin/actions":()=>Pl(n),"DELETE /api/admin/actions":()=>jl(n),"POST /api/admin/actions/run":()=>Ol(n),"GET /api/admin/channels/whatsapp/chats":()=>Be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>gl(n),"POST /api/admin/webhooks":()=>rl(n),"PATCH /api/admin/webhooks":()=>ol(n),"DELETE /api/admin/webhooks":()=>cl(n),"POST /api/admin/whatsapp-triage":()=>er(n),"POST /api/admin/whatsapp-triage/rules":()=>tr(n),"PATCH /api/admin/whatsapp-triage/rules":()=>ar(n),"DELETE /api/admin/whatsapp-triage/rules":()=>nr(n),"POST /api/admin/mesh/peers":()=>sl(n),"DELETE /api/admin/mesh/peers":()=>il(n),"POST /api/admin/mesh/toggle":()=>ll(n),"GET /api/admin/files":()=>Vi(t),"GET /api/admin/files/read":()=>Yi(t),"PUT /api/admin/files":()=>Qi(n),"POST /api/admin/files/skill":()=>Zi(n),"DELETE /api/admin/files/skill":()=>el(n),"POST /api/admin/business/orgchart":()=>kl(n),"DELETE /api/admin/business/orgchart":()=>_l(n),"POST /api/admin/business/project":()=>Sl(n),"DELETE /api/admin/business/project":()=>Al(n),"POST /api/admin/business/client":()=>El(n),"DELETE /api/admin/business/client":()=>Tl(n),"POST /api/admin/business/contact":()=>Cl(n),"DELETE /api/admin/business/contact":()=>Il(n),"POST /api/admin/boards":()=>Ml(n),"DELETE /api/admin/boards":()=>Rl(n),"POST /api/admin/boards/columns":()=>Ll(n),"DELETE /api/admin/boards/columns":()=>$l(n),"POST /api/admin/notifications":()=>Dl(n),"POST /api/admin/screen":()=>Hl(n),"POST /api/admin/webhooks/triggers":()=>Bl(n),"POST /api/admin/mesh/health":()=>Nl(n),"GET /api/admin/projects":()=>Be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Xt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Xt(e,200,i)}catch(n){Xt(e,400,{error:n.message||"admin op failed"})}}function Xt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Oi(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 Ni(t){let e=$e(process.cwd(),t);if(!gt(e))return[];let a=[];for(let n of ji(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(or($e(e,n.name),"utf-8")))}catch{}return a}function Jt(){let t=$e(process.cwd(),"agentx.json");return gt(t)?JSON.parse(or(t,"utf-8")):null}function Di(){let t=Jt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,f])=>({id:d,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let v=x.credentials||{},k={};for(let[b,S]of Object.entries(v))typeof S=="string"&&/^[A-Z][A-Z0-9_]*$/.test(S)?k[b]=process.env[S]?"set":"unset":typeof S=="string"&&(k[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:k,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,f])=>({id:d,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.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(([d,f])=>({id:d,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},w=t.notifications||{},_={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:Qa(w.local),ntfy:zn(t.channels?.ntfy)},E=[];try{E=Ni(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Dn(t),whatsappTriage:Zn(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:wn(t.screen),actions:E}}function Hi(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}=A(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 Bi(){return new ne().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 zi(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 ne().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function qi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ne().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Fi(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=ae();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(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Ui(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=pr(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=$e(process.cwd(),"agents",e),{summary:l}=A(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}"`}),c=$e(i,"CLAUDE.md");if(!gt(c))try{$i(i,{recursive:!0}),sr(c,`# ${a}
4879
4896
 
4880
4897
  ${s||"You are "+a+"."}
4881
- `)}catch{}return{summary:l}}function Hi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(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=ir(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 Bi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(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 zi(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}=A(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 qi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Be(t){let{url:e,headers:a}=Vt(),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 me(t,e){let{url:a,headers:n}=Vt(),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 Fi(t,e){try{let{url:a,headers:n}=Vt(),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 Vt(){let t="http://127.0.0.1:18800",e={};try{let a=ae();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ze(t){let a=Jt()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function Kt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Ui(t){let e=Kt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Le(ze(e));return{agentId:e,...a}}function Wi(t){let e=Kt(t,"agent").trim(),a=Kt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return rt(ze(e),a)}function Gi(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=ot(ze(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Xi(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=st(ze(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Ki(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=it(ze(e),a);return{summary:`removed skill "${a}"`,...n}}function Ji(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 c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(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(c=>c.kind===a&&c.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 Vi(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}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.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 Yi(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}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var sr=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Qi(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(!sr.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(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 c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Zi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&sr.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 el(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}=A(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 tl(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(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 al(t){let e=!!t?.enabled,{summary:a}=A(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 nl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(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 rl(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}=A(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 ol(t){let e=!!t?.enabled,{summary:a}=A(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 sl(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}=A(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 il(t){let e=!!t?.enabled,{summary:a}=A(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 ll(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}=A(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 cl(t){let e=!!t?.enabled,{summary:a}=A(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 dl(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-24O7PADJ.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 pl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(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 ul(t){let e=!!t?.enabled,{summary:a}=A(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 ml(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}=A(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 fl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function hl(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=$e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(gt(n))try{Ci(n,r)}catch{}ar(n,JSON.stringify(a,null,2)+`
4882
- `,"utf-8");try{let s=ae().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 ir(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function gl(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}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function xl(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(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 vl(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}=A(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 bl(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}=A(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 yl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(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 wl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(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 kl(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}=A(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 _l(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}=A(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 Sl(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}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=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),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function El(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(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 Tl(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}=A(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 c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Al(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}=A(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 Cl(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 Il(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 Ml(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 Rl(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}=A(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 Ll(t){let{summary:e}=A(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=Ya(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=Dn(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 $l(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=yn(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Pl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(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}}Nt();import{resolve as Nl}from"path";function lr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4898
+ `)}catch{}return{summary:l}}function Wi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(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=pr(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 Gi(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(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 Xi(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}=A(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 Ki(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Be(t){let{url:e,headers:a}=Vt(),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 me(t,e){let{url:a,headers:n}=Vt(),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 Ji(t,e){try{let{url:a,headers:n}=Vt(),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 Vt(){let t="http://127.0.0.1:18800",e={};try{let a=ae();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ze(t){let a=Jt()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function Kt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Vi(t){let e=Kt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Le(ze(e));return{agentId:e,...a}}function Yi(t){let e=Kt(t,"agent").trim(),a=Kt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return rt(ze(e),a)}function Qi(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=ot(ze(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Zi(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=st(ze(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function el(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=it(ze(e),a);return{summary:`removed skill "${a}"`,...n}}function tl(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 c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(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(c=>c.kind===a&&c.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 al(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}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.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 nl(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}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var dr=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function rl(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(!dr.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(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 c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function ol(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&dr.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 sl(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}=A(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 il(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(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 ll(t){let e=!!t?.enabled,{summary:a}=A(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 cl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(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 dl(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}=A(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 pl(t){let e=!!t?.enabled,{summary:a}=A(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 ul(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}=A(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 ml(t){let e=!!t?.enabled,{summary:a}=A(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 fl(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}=A(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 hl(t){let e=!!t?.enabled,{summary:a}=A(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 gl(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-ITOKSMYT.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 xl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(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 vl(t){let e=!!t?.enabled,{summary:a}=A(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 bl(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}=A(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 yl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function wl(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=$e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(gt(n))try{Pi(n,r)}catch{}sr(n,JSON.stringify(a,null,2)+`
4899
+ `,"utf-8");try{let s=ae().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 pr(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function kl(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}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function _l(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(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 Sl(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}=A(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 El(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}=A(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 Tl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(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 Al(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(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 Cl(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}=A(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 Il(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}=A(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 Ml(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}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=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),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Rl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(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 Ll(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}=A(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 c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function $l(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}=A(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 Pl(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 jl(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 Ol(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 Nl(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}=A(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 Dl(t){let{summary:e}=A(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=Za(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=qn(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 Hl(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=kn(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Bl(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(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}}Nt();import{resolve as Fl}from"path";function ur(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4883
4900
 
4884
4901
  <div id="disabled-banner" class="banner warn" style="display:none">
4885
4902
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -4934,7 +4951,7 @@ ${s||"You are "+a+"."}
4934
4951
  <h2>Recent classifications</h2>
4935
4952
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
4936
4953
  <div id="recent"></div>
4937
- </section>`;return R({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:jl,scripts:`${e}<script>${Ol}</script>`})}var jl=`
4954
+ </section>`;return R({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:zl,scripts:`${e}<script>${ql}</script>`})}var zl=`
4938
4955
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
4939
4956
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
4940
4957
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -5038,7 +5055,7 @@ details {
5038
5055
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
5039
5056
  }
5040
5057
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
5041
- details[open] summary { margin-bottom: 8px; }`,Ol=`
5058
+ details[open] summary { margin-bottom: 8px; }`,ql=`
5042
5059
  const $ = (id) => document.getElementById(id);
5043
5060
  const state = { schema: null, nodes: [], pending: [], recent: [] };
5044
5061
 
@@ -5258,7 +5275,7 @@ $('btn-save-schema').addEventListener('click', async () => {
5258
5275
  $('btn-reload-schema').addEventListener('click', refresh);
5259
5276
 
5260
5277
  refresh();
5261
- `;function dr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lr({peers:a,localToken:n}))}async function pr(t,e,a){try{let n=t.method==="GET"?void 0:await Gl(t),r=Dl(),o={"GET /api/admin/graph/state":()=>Hl(r),"POST /api/admin/graph/classifications/approve":()=>Bl(r,n),"POST /api/admin/graph/classifications/reject":()=>zl(r,n),"POST /api/admin/graph/nodes":()=>ql(r,n),"PATCH /api/admin/graph/nodes":()=>Fl(r,n),"DELETE /api/admin/graph/nodes":()=>Ul(r,n),"PUT /api/admin/graph/schema":()=>Wl(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Yt(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Yt(e,200,l)}catch(n){Yt(e,400,{error:n?.message||"graph op failed"})}}function Dl(){let t=ae(),e=Nl(process.cwd(),t.graph.baseDir);return new Na({baseDir:e})}function Hl(t){let e=ae(),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 Bl(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=ur(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=Qt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function zl(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=ur(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function ur(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 ql(t,e){let a=cr(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?cr(String(e.parentId)):null,o=Qt({[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 Fl(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Qt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ul(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Wl(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 Qt(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 cr(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Yt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Gl(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 mr=`
5278
+ `;function fr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({peers:a,localToken:n}))}async function hr(t,e,a){try{let n=t.method==="GET"?void 0:await Ql(t),r=Ul(),o={"GET /api/admin/graph/state":()=>Wl(r),"POST /api/admin/graph/classifications/approve":()=>Gl(r,n),"POST /api/admin/graph/classifications/reject":()=>Xl(r,n),"POST /api/admin/graph/nodes":()=>Kl(r,n),"PATCH /api/admin/graph/nodes":()=>Jl(r,n),"DELETE /api/admin/graph/nodes":()=>Vl(r,n),"PUT /api/admin/graph/schema":()=>Yl(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Yt(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Yt(e,200,l)}catch(n){Yt(e,400,{error:n?.message||"graph op failed"})}}function Ul(){let t=ae(),e=Fl(process.cwd(),t.graph.baseDir);return new Ba({baseDir:e})}function Wl(t){let e=ae(),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 Gl(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=gr(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=Qt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Xl(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=gr(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function gr(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 Kl(t,e){let a=mr(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?mr(String(e.parentId)):null,o=Qt({[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 Jl(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Qt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Vl(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Yl(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 Qt(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 mr(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Yt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ql(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 xr=`
5262
5279
  <section class="apv__req" id="req-section" aria-labelledby="req-h">
5263
5280
  <h2 id="req-h">Open requests <span id="req-n"></span></h2>
5264
5281
  <p class="apv__lead">What you asked agents for that is not finished, oldest first. Nothing leaves this list by getting old: close it as done, or drop it.</p>
@@ -5275,7 +5292,7 @@ refresh();
5275
5292
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5276
5293
  </form>
5277
5294
  </details>
5278
- </section>`,fr=`
5295
+ </section>`,vr=`
5279
5296
  .apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
5280
5297
  .apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
5281
5298
  .apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
@@ -5284,7 +5301,7 @@ refresh();
5284
5301
  .apv__state.is-needs_attention { color: var(--ax-err); }
5285
5302
  .apv__state.is-waiting_owner { color: var(--ax-amber-ink); }
5286
5303
  .apv__req input[type=text].apv__evidence { flex: 1 1 220px; min-width: 0; font: inherit; font-size: 13px; padding: 8px 10px; border-radius: var(--ax-radius-sm); border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-text); }
5287
- `,hr=`
5304
+ `,br=`
5288
5305
  (function(){
5289
5306
  var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
5290
5307
  function $(id){ return document.getElementById(id); }
@@ -5379,7 +5396,7 @@ load();
5379
5396
  document.addEventListener('apv:decided', load);
5380
5397
  setInterval(function(){ if (document.visibilityState === 'visible' && !$('req-section').contains(document.activeElement)) load(); }, 60000);
5381
5398
  })();
5382
- `;function gr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5399
+ `;function yr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5383
5400
  <header class="apv__head">
5384
5401
  <div>
5385
5402
  <h1>Approvals</h1>
@@ -5401,7 +5418,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !$('req-se
5401
5418
  <ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
5402
5419
  <p id="apv-snoozed" class="apv__foot"></p>
5403
5420
 
5404
- ${mr}
5421
+ ${xr}
5405
5422
 
5406
5423
  <details class="apv__settings" id="apv-settings">
5407
5424
  <summary>Settings: expiry, later, daily digest</summary>
@@ -5416,7 +5433,7 @@ ${mr}
5416
5433
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5417
5434
  </form>
5418
5435
  </details>
5419
- </div>`;return R({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Xl+fr,scripts:`${e}<script>${Kl}</script><script>${hr}</script>`})}var Xl=`
5436
+ </div>`;return R({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Zl+vr,scripts:`${e}<script>${ec}</script><script>${br}</script>`})}var Zl=`
5420
5437
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
5421
5438
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
5422
5439
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -5465,7 +5482,7 @@ ${mr}
5465
5482
  @media (max-width: 560px) {
5466
5483
  .apv__acts .ax-btn { flex: 1 1 0; }
5467
5484
  }
5468
- `,Kl=`
5485
+ `,ec=`
5469
5486
  (function(){
5470
5487
  var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
5471
5488
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
@@ -5633,7 +5650,7 @@ $('apv-form').addEventListener('submit', async function(ev){
5633
5650
  load();
5634
5651
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
5635
5652
  })();
5636
- `;var qe="/api/admin/approvals/requests",xr=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function vr(t,e,a,n){try{return await Jl(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Jl(t,e,a,n){if(t==="GET"&&e===qe){let r=Ft(n);return{status:200,body:{items:r?r.listOpen():[],settings:qt(n.configPath)}}}if(t==="POST"&&e===`${qe}/close`){let r=typeof a.id=="string"?a.id:"",o=a.action;if(!r||o!=="done"&&o!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let s=Ft(n),i=s?.get(r);if(!s||!i||i.state==="candidate")return{status:404,body:{error:`no request "${r}"`}};let l=o==="done"?typeof a.evidence=="string"?a.evidence:"":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return s.close(r,o==="done"?"done":"dropped",l,n.now??Date.now())?{status:200,body:{ok:!0,message:o==="done"?`${r} closed as done`:`${r} dropped`}}:{status:409,body:{error:`${r} is already closed`}}}if(t==="POST"&&e===`${qe}/settings`){let r={},o=i=>{let l=a[i];if(l!==void 0){if(typeof l!="number"||!(l>0))throw new Error(`${i} must be a positive number`);return l}};typeof a.enabled=="boolean"&&(r.enabled=a.enabled),r.from=xr(a.from),r.channels=xr(a.channels),r.staleAfterHours=o("staleAfterHours"),r.retentionDays=o("retentionDays");let s=await tn(r,{configPath:n.configPath,reload:n.reload});return s.success?{status:200,body:{ok:!0,settings:qt(n.configPath)}}:{status:400,body:{error:s.error}}}return{status:404,body:{error:"Not found"}}}var Vl=["yes","no","later"];function Q(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function xt(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 br(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(gr({peers:e,localToken:a}))}async function yr(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 Q(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(qe)){let i=await vr(o,a,o==="POST"?await xt(t):{},s);return Q(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=at(s,{includeSnoozed:n.searchParams.get("all")==="1"});return Q(e,200,{...i,settings:we(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await xt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Vl.includes(c))return Q(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=we(s.configPath),u=await nt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(Q(e,200,{ok:!0,message:u.message}),!0):(Q(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await xt(t),l=an(s,typeof i.key=="string"?i.key:"",!!we(s.configPath).popup?.enabled);return l.ok?(Q(e,200,{ok:!0,message:l.message}),!0):(Q(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await xt(t),l={},c=u=>{let m=i[u];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${u} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("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 m=Pn(u);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await jn(l,{configPath:s.configPath,reload:s.reload});return p.success?(Q(e,200,{ok:!0,settings:we(s.configPath)}),!0):(Q(e,400,{error:p.error}),!0)}}catch(i){return Q(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return Q(e,404,{error:"Not found"}),!0}import{resolve as Zl}from"path";import{existsSync as ec}from"fs";import tc from"better-sqlite3";function wr(t={}){let e=`<div class="ax-obs">
5653
+ `;var qe="/api/admin/approvals/requests",wr=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function kr(t,e,a,n){try{return await tc(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function tc(t,e,a,n){if(t==="GET"&&e===qe){let r=Ft(n);return{status:200,body:{items:r?r.listOpen():[],settings:qt(n.configPath)}}}if(t==="POST"&&e===`${qe}/close`){let r=typeof a.id=="string"?a.id:"",o=a.action;if(!r||o!=="done"&&o!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let s=Ft(n),i=s?.get(r);if(!s||!i||i.state==="candidate")return{status:404,body:{error:`no request "${r}"`}};let l=o==="done"?typeof a.evidence=="string"?a.evidence:"":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return s.close(r,o==="done"?"done":"dropped",l,n.now??Date.now())?{status:200,body:{ok:!0,message:o==="done"?`${r} closed as done`:`${r} dropped`}}:{status:409,body:{error:`${r} is already closed`}}}if(t==="POST"&&e===`${qe}/settings`){let r={},o=i=>{let l=a[i];if(l!==void 0){if(typeof l!="number"||!(l>0))throw new Error(`${i} must be a positive number`);return l}};typeof a.enabled=="boolean"&&(r.enabled=a.enabled),r.from=wr(a.from),r.channels=wr(a.channels),r.staleAfterHours=o("staleAfterHours"),r.retentionDays=o("retentionDays");let s=await nn(r,{configPath:n.configPath,reload:n.reload});return s.success?{status:200,body:{ok:!0,settings:qt(n.configPath)}}:{status:400,body:{error:s.error}}}return{status:404,body:{error:"Not found"}}}var ac=["yes","no","later"];function Q(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function xt(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 _r(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(yr({peers:e,localToken:a}))}async function Sr(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 Q(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(qe)){let i=await kr(o,a,o==="POST"?await xt(t):{},s);return Q(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=at(s,{includeSnoozed:n.searchParams.get("all")==="1"});return Q(e,200,{...i,settings:we(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await xt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!ac.includes(c))return Q(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=we(s.configPath),u=await nt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(Q(e,200,{ok:!0,message:u.message}),!0):(Q(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await xt(t),l=rn(s,typeof i.key=="string"?i.key:"",!!we(s.configPath).popup?.enabled);return l.ok?(Q(e,200,{ok:!0,message:l.message}),!0):(Q(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await xt(t),l={},c=u=>{let m=i[u];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${u} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("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 m=On(u);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await Nn(l,{configPath:s.configPath,reload:s.reload});return p.success?(Q(e,200,{ok:!0,settings:we(s.configPath)}),!0):(Q(e,400,{error:p.error}),!0)}}catch(i){return Q(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return Q(e,404,{error:"Not found"}),!0}import{resolve as oc}from"path";import{existsSync as sc}from"fs";import ic from"better-sqlite3";function Er(t={}){let e=`<div class="ax-obs">
5637
5654
  <header class="ax-obs__head">
5638
5655
  <h1>Health</h1>
5639
5656
  <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>
@@ -5755,7 +5772,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5755
5772
  </div>
5756
5773
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
5757
5774
  </section>
5758
- </div>`;return R({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Yl,scripts:`<script>${Ql}</script>`})}var Yl=`
5775
+ </div>`;return R({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:nc,scripts:`<script>${rc}</script>`})}var nc=`
5759
5776
  .ax-obs { padding: 16px 24px; }
5760
5777
  .ax-obs__head { margin-bottom: 16px; }
5761
5778
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -5872,7 +5889,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5872
5889
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
5873
5890
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
5874
5891
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
5875
- `,Ql=`
5892
+ `,rc=`
5876
5893
  (function(){
5877
5894
  var panes = document.querySelectorAll('.ax-obs__pane');
5878
5895
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -6256,7 +6273,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6256
6273
 
6257
6274
  load(current);
6258
6275
  })();
6259
- `;var Sr={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 Er(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Zt(t){let e=Sr[Er(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 ac(){let t=Zl(process.cwd(),".agentx/db.sqlite");if(!ec(t))return null;try{let e=new tc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Tr(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wr({peers:a}))}function nc(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 fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Ar(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=ac();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=nc(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6276
+ `;var Cr={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 Ir(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Zt(t){let e=Cr[Ir(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 lc(){let t=oc(process.cwd(),".agentx/db.sqlite");if(!sc(t))return null;try{let e=new ic(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Mr(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Er({peers:a}))}function cc(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 fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Rr(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=lc();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=cc(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6260
6277
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
6261
6278
  FROM route_traces
6262
6279
  ${i.length?"WHERE "+i.join(" AND "):""}
@@ -6271,8 +6288,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6271
6288
  FROM task_history
6272
6289
  WHERE ${i.join(" AND ")}
6273
6290
  ORDER BY started_at DESC LIMIT @limit
6274
- `,u=r.db.prepare(c).all(l).map(m=>({...m,plain:Cr(m.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,rc(r.db)),!0;if(n==="activity")return fe(e,200,oc(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=kr(i.searchParams.get("range"));return fe(e,200,_r(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=kr(i.searchParams.get("range")),c=_r(r.db,l),p=sc(c.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 fe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return fe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Cr(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(`
6275
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function rc(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,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=S=>p.length?p[Math.min(p.length-1,Math.floor(p.length*S))].duration_ms:0,m=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((S,I)=>S+Zt(I),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((S,I)=>S+Zt(I),0),g=t.prepare(`
6291
+ `,u=r.db.prepare(c).all(l).map(m=>({...m,plain:Lr(m.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,dc(r.db)),!0;if(n==="activity")return fe(e,200,pc(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Tr(i.searchParams.get("range"));return fe(e,200,Ar(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Tr(i.searchParams.get("range")),c=Ar(r.db,l),p=uc(c.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 fe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return fe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Lr(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(`
6292
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function dc(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,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=S=>p.length?p[Math.min(p.length-1,Math.floor(p.length*S))].duration_ms:0,m=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((S,I)=>S+Zt(I),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((S,I)=>S+Zt(I),0),g=t.prepare(`
6276
6293
  SELECT agent_id,
6277
6294
  COUNT(*) AS tasks,
6278
6295
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -6295,7 +6312,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6295
6312
  FROM task_history
6296
6313
  WHERE status='error' AND started_at >= ?
6297
6314
  ORDER BY started_at DESC LIMIT 5
6298
- `).all(o).map(S=>({...S,plain:Cr(S.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:_,spendDelta:_-E,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:b}}function oc(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(`
6315
+ `).all(o).map(S=>({...S,plain:Lr(S.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:_,spendDelta:_-E,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:b}}function pc(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(`
6299
6316
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
6300
6317
  COUNT(*) AS tasks,
6301
6318
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6322,7 +6339,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6322
6339
  WHERE started_at >= @since
6323
6340
  GROUP BY agent_id
6324
6341
  ORDER BY tasks_24h DESC, tasks_7d DESC
6325
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function kr(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 _r(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6342
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Tr(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 Ar(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6326
6343
  SELECT day, agent_id, model,
6327
6344
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
6328
6345
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -6330,10 +6347,10 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6330
6347
  FROM usage_daily
6331
6348
  ${a}
6332
6349
  ORDER BY day
6333
- `).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,c=0,p=0,u=0,m=0,h=0,w=0,_=0,E=0,g={},d={};for(let T of n){let M=Zt(T),P=Er(T.model),j=Sr[P],B=(T.tier2_input_tokens||0)/1e6*j.input*.5+(T.tier2_output_tokens||0)/1e6*j.output*.5+(T.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(T.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,se=(T.input_tokens||0)+(T.tier2_input_tokens||0),q=(T.output_tokens||0)+(T.tier2_output_tokens||0),te=(T.cache_read_tokens||0)+(T.tier2_cache_read_tokens||0),V=(T.cache_create_tokens||0)+(T.tier2_cache_create_tokens||0);u+=M,T.day>=s&&(p+=M,w+=T.tasks||0),T.day>=i&&T.day<s&&(E+=M,_+=T.tasks||0),T.day===r&&(l+=M),T.day===o&&(c+=M),T.day===r&&(m+=B),T.day>=s&&(h+=B);let N=g[T.day]||(g[T.day]={date:T.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});N.tasks+=T.tasks||0,N.input+=se,N.output+=q,N.cacheRead+=te,N.cacheCreate+=V,N.cost+=M,N.tier2+=B;let ie=N.agents[T.agent_id]||(N.agents[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});ie.tasks+=T.tasks||0,ie.cost+=M,ie.tier2+=B,ie.input+=se,ie.output+=q,ie.cacheRead+=te,ie.cacheCreate+=V,T.model&&(ie.model=T.model);let F=d[T.agent_id]||(d[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});F.tasks+=T.tasks||0,F.cost+=M,F.tier2+=B,F.input+=se,F.output+=q,F.cacheRead+=te,F.cacheCreate+=V,T.model&&(F.model=T.model)}let f=Object.values(g).sort((T,M)=>T.date<M.date?-1:1),x=0,v=0,k=0,b=0,S=0,I=0;for(let T of f)x+=T.tasks,v+=T.input,k+=T.output,b+=T.cacheRead,S+=T.cacheCreate,I+=T.cost;let C=Object.entries(d).map(([T,M])=>({agent_id:T,...M,tokens:M.input+M.output+M.cacheRead+M.cacheCreate})).sort((T,M)=>M.cost-T.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:v+k+b+S,cacheHitRange:b+v>0?b/(b+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:_>0?(w-_)/_:0},days:f,perAgent:C}}function sc(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+`
6350
+ `).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,c=0,p=0,u=0,m=0,h=0,w=0,_=0,E=0,g={},d={};for(let T of n){let M=Zt(T),P=Ir(T.model),j=Cr[P],B=(T.tier2_input_tokens||0)/1e6*j.input*.5+(T.tier2_output_tokens||0)/1e6*j.output*.5+(T.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(T.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,se=(T.input_tokens||0)+(T.tier2_input_tokens||0),q=(T.output_tokens||0)+(T.tier2_output_tokens||0),te=(T.cache_read_tokens||0)+(T.tier2_cache_read_tokens||0),V=(T.cache_create_tokens||0)+(T.tier2_cache_create_tokens||0);u+=M,T.day>=s&&(p+=M,w+=T.tasks||0),T.day>=i&&T.day<s&&(E+=M,_+=T.tasks||0),T.day===r&&(l+=M),T.day===o&&(c+=M),T.day===r&&(m+=B),T.day>=s&&(h+=B);let N=g[T.day]||(g[T.day]={date:T.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});N.tasks+=T.tasks||0,N.input+=se,N.output+=q,N.cacheRead+=te,N.cacheCreate+=V,N.cost+=M,N.tier2+=B;let ie=N.agents[T.agent_id]||(N.agents[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});ie.tasks+=T.tasks||0,ie.cost+=M,ie.tier2+=B,ie.input+=se,ie.output+=q,ie.cacheRead+=te,ie.cacheCreate+=V,T.model&&(ie.model=T.model);let F=d[T.agent_id]||(d[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});F.tasks+=T.tasks||0,F.cost+=M,F.tier2+=B,F.input+=se,F.output+=q,F.cacheRead+=te,F.cacheCreate+=V,T.model&&(F.model=T.model)}let f=Object.values(g).sort((T,M)=>T.date<M.date?-1:1),x=0,v=0,k=0,b=0,S=0,I=0;for(let T of f)x+=T.tasks,v+=T.input,k+=T.output,b+=T.cacheRead,S+=T.cacheCreate,I+=T.cost;let C=Object.entries(d).map(([T,M])=>({agent_id:T,...M,tokens:M.input+M.output+M.cacheRead+M.cacheCreate})).sort((T,M)=>M.cost-T.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:v+k+b+S,cacheHitRange:b+v>0?b/(b+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:_>0?(w-_)/_:0},days:f,perAgent:C}}function uc(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+`
6334
6351
  `+a.join(`
6335
6352
  `)+`
6336
- `}import{resolve as ic}from"path";import{existsSync as lc}from"fs";import cc from"better-sqlite3";function dc(){let t=ic(process.cwd(),".agentx/intent/ledger.sqlite");if(!lc(t))return null;try{let e=new cc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ir>6e4&&(Ir=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Ir=0;function _e(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function pc(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 Mr(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=dc();if(!r)return _e(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=pc(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=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 ${m}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6353
+ `}import{resolve as mc}from"path";import{existsSync as fc}from"fs";import hc from"better-sqlite3";function gc(){let t=mc(process.cwd(),".agentx/intent/ledger.sqlite");if(!fc(t))return null;try{let e=new hc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-$r>6e4&&($r=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var $r=0;function _e(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function xc(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 Pr(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=gc();if(!r)return _e(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=xc(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=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 ${m}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6337
6354
  SELECT COUNT(*) AS n FROM intent_decisions d
6338
6355
  LEFT JOIN intent_resolutions r
6339
6356
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
@@ -6360,7 +6377,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6360
6377
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6361
6378
  WHERE ${u.join(" AND ")}
6362
6379
  ORDER BY d.decided_at DESC LIMIT @limit
6363
- `;return _e(e,200,{rows:r.db.prepare(h).all(m)}),!0}return _e(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return _e(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Rr(t={}){return R({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6380
+ `;return _e(e,200,{rows:r.db.prepare(h).all(m)}),!0}return _e(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return _e(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function jr(t={}){return R({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6364
6381
  <header class="ax-led__head">
6365
6382
  <h1>Intent ledger</h1>
6366
6383
  <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>
@@ -6565,7 +6582,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6565
6582
  }
6566
6583
  load();
6567
6584
  })();
6568
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Lr(t={}){return R({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6585
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Or(t={}){return R({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6569
6586
  <header class="ax-cost__head">
6570
6587
  <div>
6571
6588
  <h1>Cost</h1>
@@ -7138,7 +7155,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7138
7155
  load();
7139
7156
  setInterval(load, 30000);
7140
7157
  })();
7141
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function $r(t={}){let e=`<div class="ax-pj__root">
7158
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Nr(t={}){let e=`<div class="ax-pj__root">
7142
7159
  <aside class="ax-pj__list">
7143
7160
  <header>
7144
7161
  <h2>Projects</h2>
@@ -7165,7 +7182,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7165
7182
  </header>
7166
7183
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
7167
7184
  </section>
7168
- </div>`;return R({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:uc,scripts:`<script>${mc}</script>`})}var uc=`
7185
+ </div>`;return R({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:vc,scripts:`<script>${bc}</script>`})}var vc=`
7169
7186
  .ax-pj__root {
7170
7187
  display: grid;
7171
7188
  grid-template-columns: 360px 1fr;
@@ -7352,7 +7369,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7352
7369
  }
7353
7370
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
7354
7371
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
7355
- `,mc=`
7372
+ `,bc=`
7356
7373
  (function(){
7357
7374
  const $ = (sel) => document.querySelector(sel);
7358
7375
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -8002,9 +8019,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8002
8019
  load();
8003
8020
  });
8004
8021
  })();
8005
- `;import{resolve as na,join as Ac}from"path";import{existsSync as ra,readdirSync as Cc,readFileSync as Ic}from"fs";import Mc from"better-sqlite3";var jr=String.raw`[\w.-]+(?:/[\w.-]+)+`,fc=new RegExp(`^(?:chat:)?(${jr}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),hc=new RegExp(`^\\[(?:GitLab|GitHub) (${jr}) `);function Pr(t){if(!t)return null;let e=t.match(fc);return e?e[1]:null}function ea(t){if(!t)return null;let e=t.trimStart().match(hc);return e?e[1]:null}function vt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Pr(typeof n?.chatId=="string"?n.chatId:null)??Pr(e)??ea(a)}function gc(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var xc=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,vc=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,bc=t=>/^issue/i.test(t)?"issue":"mr";function yc(t){let e=t.subject.match(xc)??t.inputPreview.trimStart().match(vc);return e?{kind:bc(e[1]),n:Number(e[2])}:null}function wc(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 Or(t){if(!gc(t.projectId))return[];let e=yc(t);return e?[e]:wc(t.inputPreview)}var kc=6e4,_c=5*6e4,Sc=40,Nr=6,Dr=new Map;function Hr(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 Or(n)){let s=bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Sc)return[...e.values()]}}return[...e.values()]}async function Br(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=bt(s.project,s.ref),l=Dr.get(i);l&&n-l.at<(s.github?_c:kc)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Nr)await Promise.all(o.slice(s,s+Nr).map(async i=>{let l=bt(i.project,i.ref),c=null;try{c=i.github?await Tc(i,e,a):await Ec(i,e,a)}catch{}Dr.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function zr(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 Ec(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 zr(`${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 Tc(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 zr(`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}var ta=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function qr(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=Fa(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=ta(o.from,80);if(s){a.callback={from:s,status:ta(o.status,20)??"done"};let i=ta(o.peer,80);i&&(a.callback.peer=i)}}return a}function oa(){let t=na(process.cwd(),".agentx/intent/ledger.sqlite");if(!ra(t))return null;try{let e=new Mc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Fr>6e4&&(Fr=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Fr=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={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"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Rc(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)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 Pe)return s}return"workflow"}return t}function Gr(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 Lc(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 Xr(t,e,a){return Ka(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 $c(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:G(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&&!aa(l))return{id:l,name:l,avatar:G(l),kind:"a2a"}}let i=o||r||s;if(i&&!aa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:G(i),kind:jc(e,n)}}}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,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!aa(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Ur(p);return{id:c,name:l||i||c,avatar:G(l||i||c),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,c=s.name||s.username;return{id:l,name:c,avatar:G(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:G(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:G(i),kind:Ur(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:G(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:G(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:G(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:G(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:G(o),kind:"whatsapp"}}}return null}var Pc={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function jc(t,e){let a=Pc[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Ur(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function aa(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 G(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 Kr(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}
8022
+ `;import{resolve as na,join as $c}from"path";import{existsSync as ra,readdirSync as Pc,readFileSync as jc}from"fs";import Oc from"better-sqlite3";var Hr=String.raw`[\w.-]+(?:/[\w.-]+)+`,yc=new RegExp(`^(?:chat:)?(${Hr}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),wc=new RegExp(`^\\[(?:GitLab|GitHub) (${Hr}) `);function Dr(t){if(!t)return null;let e=t.match(yc);return e?e[1]:null}function ea(t){if(!t)return null;let e=t.trimStart().match(wc);return e?e[1]:null}function vt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Dr(typeof n?.chatId=="string"?n.chatId:null)??Dr(e)??ea(a)}function kc(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var _c=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Sc=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ec=t=>/^issue/i.test(t)?"issue":"mr";function Tc(t){let e=t.subject.match(_c)??t.inputPreview.trimStart().match(Sc);return e?{kind:Ec(e[1]),n:Number(e[2])}:null}function Ac(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 Br(t){if(!kc(t.projectId))return[];let e=Tc(t);return e?[e]:Ac(t.inputPreview)}var Cc=6e4,Ic=5*6e4,Mc=40,zr=6,qr=new Map;function Fr(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 Br(n)){let s=bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Mc)return[...e.values()]}}return[...e.values()]}async function Ur(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=bt(s.project,s.ref),l=qr.get(i);l&&n-l.at<(s.github?Ic:Cc)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=zr)await Promise.all(o.slice(s,s+zr).map(async i=>{let l=bt(i.project,i.ref),c=null;try{c=i.github?await Lc(i,e,a):await Rc(i,e,a)}catch{}qr.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Wr(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 Rc(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 Wr(`${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 Lc(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 Wr(`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}fi();var ta=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Gr(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=Na(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=ta(o.from,80);if(s){a.callback={from:s,status:ta(o.status,20)??"done"};let i=ta(o.peer,80);i&&(a.callback.peer=i)}}return a}function oa(){let t=na(process.cwd(),".agentx/intent/ledger.sqlite");if(!ra(t))return null;try{let e=new Oc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Xr>6e4&&(Xr=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Xr=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={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"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Nc(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)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 Pe)return s}return"workflow"}return t}function Vr(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 Dc(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 Yr(t,e,a){return Va(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 Hc(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:G(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&&!aa(l))return{id:l,name:l,avatar:G(l),kind:"a2a"}}let i=o||r||s;if(i&&!aa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:G(i),kind:zc(e,n)}}}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,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!aa(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Kr(p);return{id:c,name:l||i||c,avatar:G(l||i||c),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,c=s.name||s.username;return{id:l,name:c,avatar:G(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:G(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:G(i),kind:Kr(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:G(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:G(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:G(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:G(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:G(o),kind:"whatsapp"}}}return null}var Bc={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function zc(t,e){let a=Bc[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Kr(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function aa(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 G(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 Qr(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}
8006
8023
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
8007
- ${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 Oc(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 Jr(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
8024
+ ${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 qc(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 Zr(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
8008
8025
  SELECT id, ts, source, project, subject, intent, raw_json
8009
8026
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
8010
8027
  `).all(r),s=new Map,i=new Map;if(o.length>0){let b=o.map(M=>M.id),S=b.map((M,P)=>`@id${P}`).join(","),I=Object.fromEntries(b.map((M,P)=>[`id${P}`,M])),C=t.prepare(`
@@ -8013,9 +8030,9 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
8013
8030
  `).all(I);for(let M of C)s.has(M.event_id)||s.set(M.event_id,[]),s.get(M.event_id).push(M);let T=t.prepare(`
8014
8031
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
8015
8032
  FROM intent_resolutions WHERE decision_event_id IN (${S})
8016
- `).all(I);for(let M of T)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,c=new Map,p=new Map,u=new Map,m=[],h=e?.business?.projects??[],w=e?.business?.contactMap??[],_=Bt(e?.business??{});for(let b of o){let S=null;try{S=JSON.parse(b.raw_json)}catch{}let I=Xr(b.source,S,w),C=Kr(b.source,S),T=qr(S),M=b.project??vt(S,b.subject,C),P=null,j=null;I?(P=I.client,j=I.project||`${I.client}/_chat`):M&&(P=et(M,h),j=M);let B=Rc(b.source,b.intent||"",S),se=Pe[B]||{label:B,color:"#6b7280"};p.has(B)||p.set(B,{id:B,label:se.label,color:se.color});let q="__system",te,V=$c(b.source,b.intent||"",S);if(V){q=V.id,te=V.kind;let N=I?.displayName||V.name;(!u.has(V.id)||I?.displayName)&&u.set(V.id,{id:V.id,name:N,avatar:G(N),kind:V.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(b.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let ie=`${b.id}|${N.decided_by}`,F=i.get(ie),$a=N.decided_at,Pa=F?.resolved_at??null,jt=Pa===null,si=F?.duration_ms??(jt?n-$a:0),ii=jt?"active":F?.status==="error"||F?.status==="fail"?"error":"completed",Y,De;if(P)Y=P,De=j;else{let Ot=_.get(N.agent_id);Ot?(Y=Ot,De=`${Ot}/_${b.source}`):(Y="unmapped",De=`unmapped/_${b.source}`)}l.has(Y)||l.set(Y,{id:Y,name:Y,color:Gr(Y),projects:[]}),c.has(Y)||c.set(Y,new Set),c.get(Y).add(De),m.push({id:`${b.id}|${N.decided_by}`,agentId:N.agent_id,clientId:Y,projectId:De,channelId:B,initiatorId:q,initiatorKind:te,subject:Oc(b.subject),intent:b.intent||"",startedAt:$a,resolvedAt:Pa,duration:si,active:jt,outcome:ii,tokens:0,inputPreview:C,system:Lc(N.agent_id,e),...T})}}let E=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,S)=>b.id.localeCompare(S.id)),g=[],d=new Set;if(e){let b=e.business??{},S=I=>{let C=b.orgChart?.[I]?.role,T=C?b.roles?.[C]?.title:void 0;return typeof T=="string"&&T.trim()?T.trim():void 0};for(let[I,C]of Object.entries(e.agents||{})){let T={id:I,name:C.name||I,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:S(I)};g.push(T),d.add(I)}}for(let b of m)d.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),d.add(b.agentId));g.sort((b,S)=>b.id.localeCompare(S.id));let f=[],x=new Set;for(let[b,S]of Object.entries(Pe))f.push({id:b,label:S.label,color:S.color}),x.add(b);for(let b of p.values())x.has(b.id)||f.push(b);let v=[...u.values()];v.find(b=>b.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:g,channels:f,initiators:v,dispatches:m,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function sa(t){let e=oa();if(!e)return null;try{return Jr(e.db,ve,t)}finally{e.close()}}function Vr(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,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 m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:h})}}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 m=Nc(u);if(m.clientId!==u.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Gr(m.clientId),projects:[]}),m.projectId!==u.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function Nc(t){if(t.clientId!=="unmapped")return t;let e=ea(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:et(e,a)}}async function yt(t){let e=ve?.channels?.gitlab,a=await Br(Hr(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 ve=null;function Yr(t){ve=t}async function Qr(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=oa();if(!n)return he(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Zr(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await yt(Jr(n.db,ve,o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Dc=5e3;async function ia(t,e,a,n=sa){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
8033
+ `).all(I);for(let M of T)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,c=new Map,p=new Map,u=new Map,m=[],h=e?.business?.projects??[],w=e?.business?.contactMap??[],_=Bt(e?.business??{});for(let b of o){let S=null;try{S=JSON.parse(b.raw_json)}catch{}let I=Yr(b.source,S,w),C=Qr(b.source,S),T=Gr(S),M=b.project??vt(S,b.subject,C),P=null,j=null;I?(P=I.client,j=I.project||`${I.client}/_chat`):M&&(P=et(M,h),j=M);let B=Nc(b.source,b.intent||"",S),se=Pe[B]||{label:B,color:"#6b7280"};p.has(B)||p.set(B,{id:B,label:se.label,color:se.color});let q="__system",te,V=Hc(b.source,b.intent||"",S);if(V){q=V.id,te=V.kind;let N=I?.displayName||V.name;(!u.has(V.id)||I?.displayName)&&u.set(V.id,{id:V.id,name:N,avatar:G(N),kind:V.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(b.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let ie=`${b.id}|${N.decided_by}`,F=i.get(ie),$a=N.decided_at,Pa=F?.resolved_at??null,jt=Pa===null,di=F?.duration_ms??(jt?n-$a:0),pi=jt?"active":F?.status==="error"||F?.status==="fail"?"error":"completed",Y,De;if(P)Y=P,De=j;else{let Ot=_.get(N.agent_id);Ot?(Y=Ot,De=`${Ot}/_${b.source}`):(Y="unmapped",De=`unmapped/_${b.source}`)}l.has(Y)||l.set(Y,{id:Y,name:Y,color:Vr(Y),projects:[]}),c.has(Y)||c.set(Y,new Set),c.get(Y).add(De),m.push({id:`${b.id}|${N.decided_by}`,agentId:N.agent_id,clientId:Y,projectId:De,channelId:B,initiatorId:q,initiatorKind:te,subject:qc(b.subject),intent:b.intent||"",startedAt:$a,resolvedAt:Pa,duration:di,active:jt,outcome:pi,tokens:0,inputPreview:C,system:Dc(N.agent_id,e),...T})}}let E=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,S)=>b.id.localeCompare(S.id)),g=[],d=new Set;if(e){let b=e.business??{},S=I=>{let C=b.orgChart?.[I]?.role,T=C?b.roles?.[C]?.title:void 0;return typeof T=="string"&&T.trim()?T.trim():void 0};for(let[I,C]of Object.entries(e.agents||{})){let T={id:I,name:C.name||I,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:S(I)};g.push(T),d.add(I)}}for(let b of m)d.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),d.add(b.agentId));g.sort((b,S)=>b.id.localeCompare(S.id));let f=[],x=new Set;for(let[b,S]of Object.entries(Pe))f.push({id:b,label:S.label,color:S.color}),x.add(b);for(let b of p.values())x.has(b.id)||f.push(b);let v=[...u.values()];v.find(b=>b.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:g,channels:f,initiators:v,dispatches:m,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function sa(t){let e=oa();if(!e)return null;try{return Zr(e.db,ve,t)}finally{e.close()}}function eo(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,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 m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:h})}}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 m=Fc(u);if(m.clientId!==u.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Vr(m.clientId),projects:[]}),m.projectId!==u.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function Fc(t){if(t.clientId!=="unmapped")return t;let e=ea(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:et(e,a)}}async function yt(t){let e=ve?.channels?.gitlab,a=await Ur(Fr(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 ve=null;function to(t){ve=t}async function ao(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=oa();if(!n)return he(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=no(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await yt(Zr(n.db,ve,o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Uc=5e3;async function ia(t,e,a,n=sa){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
8017
8034
 
8018
- `);let r=new URL(t.url||"/","http://_"),o=Zr(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
8035
+ `);let r=new URL(t.url||"/","http://_"),o=no(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
8019
8036
 
8020
8037
  `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await yt(p);if(s)break;u?(e.write(`event: snapshot
8021
8038
  `),e.write(`data: ${JSON.stringify(u)}
@@ -8026,7 +8043,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
8026
8043
  `)}catch(p){e.write(`event: error
8027
8044
  data: ${JSON.stringify({error:p?.message??String(p)})}
8028
8045
 
8029
- `)}let c=Date.now();for(;!s&&Date.now()-c<Dc;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Zr(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Hc(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=na(process.cwd(),".agentx/task-history",t,n);if(!ra(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=na(process.cwd(),".agentx/task-history",t,o);return ra(s)?Wr(s,e,a):null}return Wr(r,e,a)}function Wr(t,e,a){let n=null,r=1/0;for(let o of Cc(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Ic(Ac(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 c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function eo(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 he(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=oa();if(!l)return he(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return he(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 he(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),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=Kr(c.source,m),w=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,_=null,E=null;if(p.agent_id){let k=Hc(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(_=k.responseText);let b=k.transcript;Array.isArray(b)&&(E=b.length)}}let g=ve?.business?.projects??[],d=ve?.business?.contactMap??[],f=Bt(ve?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Xr(c.source,m,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||vt(m,c.subject,h)){let k=c.project||vt(m,c.subject,h);x={client:et(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=f.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:w,response:_,transcriptLen:E,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){he(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Fc,readFileSync as Uc}from"fs";import{resolve as ao}from"path";Nt();function to(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=Bc.replace(/__AGENT_ID__/g,O(e));return R({title:`AgentX \xB7 ${O(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${O(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:zc,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>${qc}</script>`})}var Bc=`
8046
+ `)}let c=Date.now();for(;!s&&Date.now()-c<Uc;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function no(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Wc(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=na(process.cwd(),".agentx/task-history",t,n);if(!ra(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=na(process.cwd(),".agentx/task-history",t,o);return ra(s)?Jr(s,e,a):null}return Jr(r,e,a)}function Jr(t,e,a){let n=null,r=1/0;for(let o of Pc(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(jc($c(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 c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function ro(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 he(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=oa();if(!l)return he(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return he(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 he(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),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=Qr(c.source,m),w=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,_=null,E=null;if(p.agent_id){let k=Wc(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(_=k.responseText);let b=k.transcript;Array.isArray(b)&&(E=b.length)}}let g=ve?.business?.projects??[],d=ve?.business?.contactMap??[],f=Bt(ve?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Yr(c.source,m,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||vt(m,c.subject,h)){let k=c.project||vt(m,c.subject,h);x={client:et(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=f.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:w,response:_,transcriptLen:E,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){he(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Jc,readFileSync as Vc}from"fs";import{resolve as so}from"path";Nt();function oo(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=Gc.replace(/__AGENT_ID__/g,O(e));return R({title:`AgentX \xB7 ${O(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${O(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Xc,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>${Kc}</script>`})}var Gc=`
8030
8047
  <!-- Breadcrumb -->
8031
8048
  <div class="ax-crumb">
8032
8049
  <a href="/admin">Settings</a>
@@ -8615,7 +8632,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
8615
8632
  </div>
8616
8633
  </div>
8617
8634
  </div>
8618
- `,zc=`
8635
+ `,Xc=`
8619
8636
  /* Agent-specific layout + legacy styles for bits the migration left in
8620
8637
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
8621
8638
  * primitives live in components.css.ts. */
@@ -8734,7 +8751,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
8734
8751
 
8735
8752
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
8736
8753
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
8737
- `,qc=`
8754
+ `,Kc=`
8738
8755
  const $ = (id) => document.getElementById(id);
8739
8756
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
8740
8757
 
@@ -9590,15 +9607,15 @@ document.addEventListener('keydown', (e) => {
9590
9607
  /* ===== Boot ===== */
9591
9608
  initOptsToggles();
9592
9609
  loadAgent();
9593
- `;function no(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(to({agentId:a,peers:n,localToken:r}))}async function ro(t,e,a){try{let n=t.method==="GET"?void 0:await ud(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){wt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Fe(i),"PATCH ":()=>Wc(i,n),"PATCH capability":()=>Kc(i,n),"POST mcp":()=>Gc(i,n),"DELETE mcp":()=>Xc(i,n),"GET identity":()=>Jc(i),"GET identity/file":()=>Vc(i,String(o.path||"")),"PUT identity/file":()=>Yc(i,n),"GET skills":()=>Qc(i),"POST skills":()=>Zc(i,n),"DELETE skills":()=>ed(i,n),"GET skills/tree":()=>td(i,String(o.slug||"")),"GET skills/file":()=>ad(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>nd(i,n),"GET skills/deps":()=>rd(i,String(o.slug||"")),"POST skills/install":()=>od(i,n,t),"POST skills/deps":()=>sd(i,n,t),"GET channels":()=>id(i),"GET activity":()=>ld(i,t),"GET handovers":()=>cd(i),"POST handovers":()=>dd(i,n),"DELETE handovers":()=>pd(n)}[c];if(!u){wt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await u();wt(e,200,m)}catch(n){wt(e,400,{error:n?.message||"agent op failed"})}}function oo(){let t=ao(process.cwd(),"agentx.json");return Fc(t)?JSON.parse(Uc(t,"utf-8")):null}function X(t){let e=oo();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 Fe(t){let{def:e,cfg:a}=X(t),n=e.workspace?Le(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 Wc(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}=A(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:Fe(t)}}function Gc(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}=A(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:Fe(t)}}function Xc(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=A(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:Fe(t)}}function Kc(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}=A(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:Fe(t)}}function Jc(t){let{def:e}=X(t);return Le(e.workspace)}function Vc(t,e){if(!e)throw new Error("path query param required");let{def:a}=X(t);return rt(a.workspace,e)}function Yc(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=X(t);return ot(n.workspace,a,String(e?.content??""))}function Qc(t){let{def:e}=X(t),a=Le(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Zc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return st(n.workspace,a,{title:e?.title,content:e?.content})}function ed(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return it(n.workspace,a)}function td(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t),n=gn(a.workspace,e),r=lt(a.workspace,e);return{slug:e,tree:n,deps:r}}function ad(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=X(t);return xn(n.workspace,e,a)}function nd(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=X(t);return vn(r.workspace,a,n,String(e?.content??""))}function rd(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t);return lt(a.workspace,e)}async function od(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=so(e?.worker),{def:o}=X(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(`
9594
- `);return io(a,r,s,`install-${n}:${Date.now()}`)}async function sd(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=so(e?.worker),{def:o}=X(t),s=lt(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=ao(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(`
9595
- `);return io(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function so(t){if(t&&typeof t=="string")return t;let e=ae();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function io(t,e,a,n){let r=ae(),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}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}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 id(t){let e=oo(),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 ld(t,e){try{let n=(ae().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 la(){return new Da}function cd(t){let e=la(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function dd(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,c=la().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:c}}function pd(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:la().remove(e,a,n)?"Released":"No active handover for that chat"}}function wt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ud(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 Se={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 lo=[{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 ca(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Se)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9610
+ `;function io(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oo({agentId:a,peers:n,localToken:r}))}async function lo(t,e,a){try{let n=t.method==="GET"?void 0:await vd(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){wt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Fe(i),"PATCH ":()=>Yc(i,n),"PATCH capability":()=>ed(i,n),"POST mcp":()=>Qc(i,n),"DELETE mcp":()=>Zc(i,n),"GET identity":()=>td(i),"GET identity/file":()=>ad(i,String(o.path||"")),"PUT identity/file":()=>nd(i,n),"GET skills":()=>rd(i),"POST skills":()=>od(i,n),"DELETE skills":()=>sd(i,n),"GET skills/tree":()=>id(i,String(o.slug||"")),"GET skills/file":()=>ld(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>cd(i,n),"GET skills/deps":()=>dd(i,String(o.slug||"")),"POST skills/install":()=>pd(i,n,t),"POST skills/deps":()=>ud(i,n,t),"GET channels":()=>md(i),"GET activity":()=>fd(i,t),"GET handovers":()=>hd(i),"POST handovers":()=>gd(i,n),"DELETE handovers":()=>xd(n)}[c];if(!u){wt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await u();wt(e,200,m)}catch(n){wt(e,400,{error:n?.message||"agent op failed"})}}function co(){let t=so(process.cwd(),"agentx.json");return Jc(t)?JSON.parse(Vc(t,"utf-8")):null}function X(t){let e=co();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 Fe(t){let{def:e,cfg:a}=X(t),n=e.workspace?Le(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 Yc(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}=A(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:Fe(t)}}function Qc(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}=A(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:Fe(t)}}function Zc(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=A(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:Fe(t)}}function ed(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}=A(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:Fe(t)}}function td(t){let{def:e}=X(t);return Le(e.workspace)}function ad(t,e){if(!e)throw new Error("path query param required");let{def:a}=X(t);return rt(a.workspace,e)}function nd(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=X(t);return ot(n.workspace,a,String(e?.content??""))}function rd(t){let{def:e}=X(t),a=Le(e.workspace);return{skills:a.skills,workspace:a.workspace}}function od(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return st(n.workspace,a,{title:e?.title,content:e?.content})}function sd(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return it(n.workspace,a)}function id(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t),n=vn(a.workspace,e),r=lt(a.workspace,e);return{slug:e,tree:n,deps:r}}function ld(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=X(t);return bn(n.workspace,e,a)}function cd(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=X(t);return yn(r.workspace,a,n,String(e?.content??""))}function dd(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t);return lt(a.workspace,e)}async function pd(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=po(e?.worker),{def:o}=X(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(`
9611
+ `);return uo(a,r,s,`install-${n}:${Date.now()}`)}async function ud(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=po(e?.worker),{def:o}=X(t),s=lt(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=so(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(`
9612
+ `);return uo(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function po(t){if(t&&typeof t=="string")return t;let e=ae();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function uo(t,e,a,n){let r=ae(),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}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}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 md(t){let e=co(),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 fd(t,e){try{let n=(ae().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 la(){return new za}function hd(t){let e=la(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function gd(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,c=la().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:c}}function xd(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:la().remove(e,a,n)?"Released":"No active handover for that chat"}}function wt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function vd(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 Se={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 mo=[{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 ca(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Se)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9596
9613
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
9597
9614
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
9598
9615
  <section id="statstrip" class="ax-statstrip"></section>
9599
9616
  <main id="grid" class="ax-live__body"></main>
9600
9617
  </div>
9601
- `;return R({title:`${Se.brand} \xB7 ${Se.subtitle}`,activeTab:"live",subtitle:Se.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:md,scripts:e+`<script>${fd}</script>`,headExtras:`<script>
9618
+ `;return R({title:`${Se.brand} \xB7 ${Se.subtitle}`,activeTab:"live",subtitle:Se.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:bd,scripts:e+`<script>${yd}</script>`,headExtras:`<script>
9602
9619
  // rightExtras for the topbar are injected at runtime \u2014 they reference
9603
9620
  // IDs (#ts, #conn-dot) that the script below addresses directly.
9604
9621
  document.addEventListener('DOMContentLoaded', () => {
@@ -9609,7 +9626,7 @@ loadAgent();
9609
9626
  extras.innerHTML = ${JSON.stringify(a)};
9610
9627
  right.insertBefore(extras, right.firstChild);
9611
9628
  });
9612
- </script>`})}var md=`
9629
+ </script>`})}var bd=`
9613
9630
  /* --- Page frame --- */
9614
9631
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
9615
9632
 
@@ -9816,7 +9833,7 @@ loadAgent();
9816
9833
  border-top-color: var(--ax-accent); border-radius: 50%;
9817
9834
  animation: ax-spin 800ms linear infinite; display: inline-block;
9818
9835
  }
9819
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,fd=`
9836
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,yd=`
9820
9837
  'use strict';
9821
9838
 
9822
9839
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -10387,7 +10404,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10387
10404
  });
10388
10405
  }
10389
10406
 
10390
- `;var co=`
10407
+ `;var fo=`
10391
10408
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
10392
10409
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
10393
10410
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -10561,7 +10578,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10561
10578
  .mx-summary{max-width:56vw}
10562
10579
  }
10563
10580
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
10564
- `;var po=`<script>
10581
+ `;var ho=`<script>
10565
10582
  window.MX=(function(){
10566
10583
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
10567
10584
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -10670,7 +10687,7 @@ window.MX=(function(){
10670
10687
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
10671
10688
  setHealth:setHealth,get:get};
10672
10689
  })();
10673
- </script>`;var uo=`<script>
10690
+ </script>`;var go=`<script>
10674
10691
  window.MXD=(function(){
10675
10692
  function el(id){return document.getElementById(id)}
10676
10693
  function tz(){return -new Date().getTimezoneOffset()}
@@ -10884,7 +10901,7 @@ window.MXD=(function(){
10884
10901
 
10885
10902
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
10886
10903
  })();
10887
- </script>`;var mo=`<script>
10904
+ </script>`;var xo=`<script>
10888
10905
  (function(){
10889
10906
  var LANES=[
10890
10907
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -11200,7 +11217,7 @@ window.MXD=(function(){
11200
11217
  window.addEventListener('scroll',hideTip,{passive:true});
11201
11218
  load();
11202
11219
  })();
11203
- </script>`;var fo=`<script>
11220
+ </script>`;var vo=`<script>
11204
11221
  (function(){
11205
11222
  var showAll=document.getElementById('mx-show-all'),expanded=false;
11206
11223
  var esc=MX.esc;
@@ -11378,7 +11395,7 @@ window.MXD=(function(){
11378
11395
  }
11379
11396
  load();setInterval(load,5000);
11380
11397
  })();
11381
- </script>`;var ho=`
11398
+ </script>`;var bo=`
11382
11399
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
11383
11400
  .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}
11384
11401
  .mx-rt-wrap > .mx-empty{border:0}
@@ -11419,7 +11436,7 @@ window.MXD=(function(){
11419
11436
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
11420
11437
  .mx-rt-name{max-width:100%}
11421
11438
  }
11422
- `,go=`<script>
11439
+ `,yo=`<script>
11423
11440
  (function(){
11424
11441
  var root=document.getElementById('mx-routines');
11425
11442
  var bar=document.getElementById('mx-rt-filter');
@@ -11546,7 +11563,7 @@ window.MXD=(function(){
11546
11563
  syncBar();
11547
11564
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
11548
11565
  })();
11549
- </script>`;var xo=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],vo=`<script>
11566
+ </script>`;var wo=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],ko=`<script>
11550
11567
  (function(){
11551
11568
  var root=document.getElementById('mx-feed');
11552
11569
  if(!root)return;
@@ -11621,12 +11638,12 @@ window.MXD=(function(){
11621
11638
  }
11622
11639
  load();setInterval(load,5000);
11623
11640
  })();
11624
- </script>`;var Z={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 ee(t,e,a,n,r=""){return W({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var hd=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],gd=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],xd=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function bo(t){let e=ct({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+dt([{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">
11641
+ </script>`;var Z={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 ee(t,e,a,n,r=""){return W({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var wd=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],kd=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],_d=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function _o(t){let e=ct({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+dt([{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">
11625
11642
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
11626
- ${gd.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("")}
11643
+ ${kd.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("")}
11627
11644
  </div>
11628
11645
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
11629
- ${xd.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11646
+ ${_d.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11630
11647
  </div>
11631
11648
  </div>
11632
11649
  <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">
@@ -11679,7 +11696,7 @@ window.MXD=(function(){
11679
11696
  <section class="mx-section" aria-labelledby="mx-routines-title">
11680
11697
  ${ee(Z.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>')}
11681
11698
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
11682
- ${hd.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11699
+ ${wd.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11683
11700
  </div>
11684
11701
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
11685
11702
  </section>
@@ -11687,7 +11704,7 @@ window.MXD=(function(){
11687
11704
  <section class="mx-section" aria-labelledby="mx-feed-title">
11688
11705
  ${ee(Z.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>')}
11689
11706
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
11690
- ${xo.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11707
+ ${wo.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11691
11708
  </div>
11692
11709
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
11693
11710
  </section>
@@ -11720,7 +11737,7 @@ window.MXD=(function(){
11720
11737
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
11721
11738
  </header>
11722
11739
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
11723
- </aside>`;return R({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:co+ho,scripts:po+vd+uo+mo+go+fo+vo})}var vd=`<script>
11740
+ </aside>`;return R({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:fo+bo,scripts:ho+Sd+go+xo+yo+vo+ko})}var Sd=`<script>
11724
11741
  (function(){
11725
11742
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
11726
11743
  var range=document.getElementById('mx-range');
@@ -11748,7 +11765,7 @@ window.MXD=(function(){
11748
11765
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
11749
11766
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
11750
11767
  })();
11751
- </script>`;async function yo(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 c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return bd(s,e.days)}function bd(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=[],c=0,p=0,u=0,m=0,h=0,w=0;for(let{node:E,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let f=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])f[x][0]+=d[x]?.[0]||0,f[x][1]+=d[x]?.[1]||0;n.set(d.day,f)}for(let d of g.origins){let f=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};f.runs+=d.runs,f.errors+=d.errors,f.hours+=d.hours,r.set(d.channel,f)}for(let d of g.causes){let f=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};f.count+=d.count;for(let x of d.agents)f.agents.includes(x)||f.agents.push(x);f.example||(f.example=d.example),o.set(d.cause,f)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,m=Math.max(m,g.rotations.maxTokens),h+=g.retention.traces,w+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:E.name,nodeUrl:E.url});for(let d of g.threads)l.push({...d,node:E.name,nodeUrl:E.url})}let _=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):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,g)=>E.day.localeCompare(g.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,g)=>g.runs-E.runs),causes:[...o.values()].sort((E,g)=>g.count-E.count),jobs:i.sort((E,g)=>g.hours-E.hours),threads:l.sort((E,g)=>g.lastAt-g.firstAt-(E.lastAt-E.firstAt)||g.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,g])=>({reason:E,count:g})).sort((E,g)=>g.count-E.count),tokenSum:p,tokenSamples:u,maxTokens:m},retention:{traces:h,tracesWithSteps:w}}}async function wo(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 ko(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 c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return yd(s,e.day)}function yd(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 c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}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 _o(t={}){let e=`
11768
+ </script>`;async function So(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 c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Ed(s,e.days)}function Ed(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=[],c=0,p=0,u=0,m=0,h=0,w=0;for(let{node:E,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let f=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])f[x][0]+=d[x]?.[0]||0,f[x][1]+=d[x]?.[1]||0;n.set(d.day,f)}for(let d of g.origins){let f=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};f.runs+=d.runs,f.errors+=d.errors,f.hours+=d.hours,r.set(d.channel,f)}for(let d of g.causes){let f=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};f.count+=d.count;for(let x of d.agents)f.agents.includes(x)||f.agents.push(x);f.example||(f.example=d.example),o.set(d.cause,f)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,m=Math.max(m,g.rotations.maxTokens),h+=g.retention.traces,w+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:E.name,nodeUrl:E.url});for(let d of g.threads)l.push({...d,node:E.name,nodeUrl:E.url})}let _=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):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,g)=>E.day.localeCompare(g.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,g)=>g.runs-E.runs),causes:[...o.values()].sort((E,g)=>g.count-E.count),jobs:i.sort((E,g)=>g.hours-E.hours),threads:l.sort((E,g)=>g.lastAt-g.firstAt-(E.lastAt-E.firstAt)||g.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,g])=>({reason:E,count:g})).sort((E,g)=>g.count-E.count),tokenSum:p,tokenSamples:u,maxTokens:m},retention:{traces:h,tracesWithSteps:w}}}async function Eo(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 To(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 c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Td(s,e.day)}function Td(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 c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}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 Ao(t={}){let e=`
11752
11769
  <select id="boardPicker" title="Switch board"></select>
11753
11770
  <div class="search">
11754
11771
  <span class="icon">\u2315</span>
@@ -11849,7 +11866,7 @@ window.MXD=(function(){
11849
11866
  </footer>
11850
11867
  </div>
11851
11868
  </div>
11852
- <script src="/sortable.min.js"></script>`;return R({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:wd,scripts:`<script>${kd}</script>`,headExtras:`<script>
11869
+ <script src="/sortable.min.js"></script>`;return R({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Ad,scripts:`<script>${Cd}</script>`,headExtras:`<script>
11853
11870
  // The boards page has its own connection dot + wants body height:100%
11854
11871
  // for the full-viewport kanban layout. Inject the dot into the topbar
11855
11872
  // and override body height at runtime so the shared shell doesn't
@@ -11865,7 +11882,7 @@ window.MXD=(function(){
11865
11882
  right.insertBefore(dot, right.firstChild);
11866
11883
  }
11867
11884
  });
11868
- </script>`})}var wd=`
11885
+ </script>`})}var Ad=`
11869
11886
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
11870
11887
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
11871
11888
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -12118,7 +12135,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
12118
12135
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
12119
12136
  .draft-box .draft-row .hint.err { color: var(--red); }
12120
12137
  .draft-box .draft-row .hint.ok { color: var(--green); }
12121
- `,kd=`
12138
+ `,Cd=`
12122
12139
  'use strict';
12123
12140
  const state = {
12124
12141
  boards: [], current: null, items: {},
@@ -13171,9 +13188,9 @@ function appendEvents(events) {
13171
13188
  }
13172
13189
 
13173
13190
  loadBoards().catch(e => toast('Init failed: ' + e.message));
13174
- `;function So(t={}){let a=`<h1>Plain-English glossary</h1>
13191
+ `;function Co(t={}){let a=`<h1>Plain-English glossary</h1>
13175
13192
  <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>
13176
- ${lo.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${O(n.alias)}</span>`:"";return`<article class="term"><h3>${O(n.term)}${r}</h3><p>${O(n.definition)}</p></article>`}).join("")}`;return R({title:`${Se.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:_d})}var _d=`
13193
+ ${mo.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${O(n.alias)}</span>`:"";return`<article class="term"><h3>${O(n.term)}${r}</h3><p>${O(n.definition)}</p></article>`}).join("")}`;return R({title:`${Se.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Id})}var Id=`
13177
13194
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
13178
13195
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
13179
13196
  .lead {
@@ -13203,7 +13220,7 @@ article.term .alias {
13203
13220
  }
13204
13221
  article.term p {
13205
13222
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
13206
- }`;function Eo(t={}){let e=`<div class="ax-wf__root">
13223
+ }`;function Io(t={}){let e=`<div class="ax-wf__root">
13207
13224
  <aside class="ax-wf__list">
13208
13225
  <header>
13209
13226
  <h2>Workflows</h2>
@@ -13280,7 +13297,7 @@ article.term p {
13280
13297
  </aside>
13281
13298
  </div>
13282
13299
 
13283
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return R({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Sd,scripts:`<script>${U({workflowHealth:Xa})}${Ed}</script>`})}var Sd=`
13300
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return R({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Md,scripts:`<script>${U({workflowHealth:Ja})}${Rd}</script>`})}var Md=`
13284
13301
  .ax-wf__root {
13285
13302
  display: grid;
13286
13303
  grid-template-columns: 340px 1fr;
@@ -13664,7 +13681,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13664
13681
  font-size: 12px; z-index: 50;
13665
13682
  }
13666
13683
  .hint { color: var(--ax-muted); font-size: 11px; }
13667
- `,Ed=`
13684
+ `,Rd=`
13668
13685
  (() => {
13669
13686
  const $ = (sel) => document.querySelector(sel)
13670
13687
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -14453,7 +14470,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14453
14470
  setInterval(refresh, 15000)
14454
14471
  })
14455
14472
  })();
14456
- `;function To(t={}){let e=`<div class="ax-proc__root">
14473
+ `;function Mo(t={}){let e=`<div class="ax-proc__root">
14457
14474
  <header class="ax-proc__header">
14458
14475
  <h1>Procedures</h1>
14459
14476
  <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>
@@ -14497,7 +14514,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14497
14514
  <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>
14498
14515
  <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>
14499
14516
  </section>
14500
- </div>`;return R({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Td,scripts:`<script>${Ad}</script>`})}var Td=`
14517
+ </div>`;return R({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ld,scripts:`<script>${$d}</script>`})}var Ld=`
14501
14518
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
14502
14519
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
14503
14520
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -14523,7 +14540,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14523
14540
  .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); }
14524
14541
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
14525
14542
  .ax-proc__link:hover { text-decoration: underline; }
14526
- `,Ad=`
14543
+ `,$d=`
14527
14544
  (function(){
14528
14545
  function $(sel){ return document.querySelector(sel) }
14529
14546
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -14623,7 +14640,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14623
14640
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
14624
14641
  else bootAll()
14625
14642
  })();
14626
- `;function Ao(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14643
+ `;function Ro(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14627
14644
  data-task-id="${O(t.taskId)}"
14628
14645
  data-agent-id="${O(t.agentId)}"
14629
14646
  data-node-url="${O(t.nodeUrl)}"
@@ -14666,7 +14683,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14666
14683
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
14667
14684
  </div>
14668
14685
  </footer>
14669
- </div>`;return R({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Cd,scripts:`<script>${Id}</script>`})}var Cd=`
14686
+ </div>`;return R({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Pd,scripts:`<script>${jd}</script>`})}var Pd=`
14670
14687
  /* The shell gives <main> no padding, so page content butted straight against
14671
14688
  the sticky topbar. Breathe. */
14672
14689
  .ax-task-page {
@@ -14808,7 +14825,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14808
14825
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
14809
14826
  }
14810
14827
 
14811
- `,Id=`
14828
+ `,jd=`
14812
14829
  (function () {
14813
14830
  var root = document.querySelector('.ax-task-page');
14814
14831
  if (!root) return;
@@ -15193,7 +15210,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15193
15210
  });
15194
15211
 
15195
15212
  })();
15196
- `;function Co(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
15213
+ `;function Lo(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
15197
15214
  data-agent-id="${O(t.agentId)}"
15198
15215
  data-agent-name="${O(e)}"
15199
15216
  data-node-url="${O(t.nodeUrl)}">
@@ -15222,7 +15239,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15222
15239
  <div class="ax-history__list" id="hist-list">
15223
15240
  <div class="ax-history__empty">loading\u2026</div>
15224
15241
  </div>
15225
- </div>`;return R({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Md,scripts:`<script>${Rd}</script>`})}var Md=`
15242
+ </div>`;return R({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Od,scripts:`<script>${Nd}</script>`})}var Od=`
15226
15243
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
15227
15244
  flush against the sticky topbar. */
15228
15245
  .ax-history {
@@ -15274,7 +15291,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15274
15291
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
15275
15292
  }
15276
15293
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
15277
- `,Rd=`
15294
+ `,Nd=`
15278
15295
  (function () {
15279
15296
  var root = document.querySelector('.ax-history');
15280
15297
  if (!root) return;
@@ -15374,11 +15391,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15374
15391
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15375
15392
  });
15376
15393
  })();
15377
- `;function Mo(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 je(t,e,l=>Io(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:$d(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?je(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return L(e,200,{ok:!0,emission:c})}):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"])?je(t,e,l=>{try{let c=a.layouts.save(s,l);return L(e,200,{layout:c})}catch(c){return L(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?je(t,e,l=>{let c=Dt.safeParse(l);if(!c.success)return L(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=Ht(c.data).map(u=>({path:"",message:u}));return L(e,200,{ok:p.length===0,issues:p,workflow:c.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,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return je(t,e,p=>Io(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}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 Ld=["mesh"];function Io(t,e,a,n){let r=Dt.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=Ht(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,c=e.store.get(n.id);if(c)for(let p of Ld)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(c);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).":c,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 $d(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))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return L(e,200,{runs:u});let m=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return L(e,200,{runs:m})}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 je(t,e,c=>{let p=c?.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 Pd(t,e,a,l);let c=a.runs.get(l);return c?L(e,200,{run:c}):L(e,404,{error:"run not found"})}return L(e,404,{error:"unknown runs endpoint"})}function Pd(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)}
15394
+ `;function Po(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 je(t,e,l=>$o(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Hd(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?je(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return L(e,200,{ok:!0,emission:c})}):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"])?je(t,e,l=>{try{let c=a.layouts.save(s,l);return L(e,200,{layout:c})}catch(c){return L(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?je(t,e,l=>{let c=Dt.safeParse(l);if(!c.success)return L(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=Ht(c.data).map(u=>({path:"",message:u}));return L(e,200,{ok:p.length===0,issues:p,workflow:c.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,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return je(t,e,p=>$o(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}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 Dd=["mesh"];function $o(t,e,a,n){let r=Dt.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=Ht(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,c=e.store.get(n.id);if(c)for(let p of Dd)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(c);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).":c,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 Hd(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))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return L(e,200,{runs:u});let m=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return L(e,200,{runs:m})}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 je(t,e,c=>{let p=c?.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 Bd(t,e,a,l);let c=a.runs.get(l);return c?L(e,200,{run:c}):L(e,404,{error:"run not found"})}return L(e,404,{error:"unknown runs endpoint"})}function Bd(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)}
15378
15395
 
15379
15396
  `);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)}
15380
15397
 
15381
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function je(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{readFileSync as Cp}from"fs";import{createRequire as Ip}from"module";import{deflateSync as jd}from"zlib";var Od=[41,121,255],Nd=[255,255,255],Ro=new Map;function pa(t){let e=Ro.get(t);return e||(e=Hd(t,Dd(t)),Ro.set(t,e)),e}function Dd(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,c=i*i+l*l<=r*r?Nd:Od;a.set(c,o*e+1+s*3)}return a}function Hd(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]),da("IHDR",a),da("IDAT",jd(e)),da("IEND",Buffer.alloc(0))])}function da(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(zd(n)),Buffer.concat([a,n,r])}var Bd=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 zd(t){let e=4294967295;for(let a of t)e=Bd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function kt(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 qd(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:kt(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:kt(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:kt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Fd(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:kt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Ud=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Lo(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 h=Wd(s.searchParams.get("timezone")),w=await o.snapshot({date:Gd(h),timezone:h});return a==="/api/app/activity"?ue(e,200,{ts:w.ts,tasks:Fd(w.nodes)}):ue(e,200,{ts:w.ts,nodes:w.nodes.map(qd)})}if(n==="GET"&&a==="/api/app/approvals")return ue(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Ud);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await Ee(t)}catch(h){return ue(e,400,{error:h.message})}let p=Ue(c.node);if(!p)return ue(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,m;if(i){let h=Ue(c.taskId);if(!h)return ue(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")m=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let _=Ue(c.message);if(!_)return ue(e,400,{error:"message is required"});m=await o.nodePost(p,w,{message:_,sender:u})}}else if(a==="/api/app/nodes/restart")m=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")m=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=Ue(c.cronId);if(!h||typeof c.enabled!="boolean")return ue(e,400,{error:"cronId and enabled (true or false) are required"});m=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=Ue(c.key),w=c.action;if(!h||w!=="yes"&&w!=="no"&&w!=="later")return ue(e,400,{error:"key and action (yes, no or later) are required"});m=await o.decide(p,h,w,u)}return ue(e,m.status,m.body)}function Ue(t){return typeof t=="string"?t.trim():""}function Wd(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Gd(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function Ee(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 ue(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Xd=2048,$o=/^[A-Za-z0-9_-]{8,256}$/;async function Po(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 K(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):Kd()});if(n==="GET"&&a==="/api/app/alerts")return K(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return K(e,404,{error:"not found"});if(!s||l)return K(e,503,{error:l});let c;try{c=await Ee(t)}catch(h){return K(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),w=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return K(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return K(e,400,{error:`${w} must be true or false`});let E={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),E[ce[g].field]=c[ce[g].field];return K(e,200,{ok:!0,...E})}let p=Jd(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return K(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return K(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!$o.test(u)||typeof m!="string"||!$o.test(m)?K(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?K(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),K(e,200,{ok:!0}))}function Kd(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Jd(t,e){if(typeof t!="string"||t.length>Xd)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 K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Oo=50,Vd=280;async function No(t,e,a,n,r,o){if(a!=="/api/app/announcements")return!1;if(n==="GET"){let s=o.prefs(),i=[],l=null;try{i=Yd(await o.recent(Oo))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return jo(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return jo(e,404,{error:"not found"})}function Do(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||z(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=Me();return r?new wn(r):null}}}function Yd(t){let e=[];for(let a of Array.isArray(t)?t:[]){let n=a;!n||n.kind!=="announce"||typeof n.id!="string"||typeof n.at!="string"||e.push({id:n.id.slice(0,64),text:ua(typeof n.summary=="string"?n.summary:"",Vd),by:typeof n.agentId=="string"?ua(n.agentId,100):null,node:ua(typeof n.node=="string"?n.node:"",100),at:n.at.slice(0,40)})}return e.sort((a,n)=>(Date.parse(n.at)||0)-(Date.parse(a.at)||0)),e.slice(0,Oo)}function ua(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function jo(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Qd="operator",Zd=50,Ho=4,Bo=500;function ep(t){let e={channel:"app",chatId:t.chatId,sender:Qd,...t.spoken?{via:"voice"}:{}};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 zo(t,e,a,n){let{path:r,body:o}=ep(e),s="",i=!1,l=[],c=new Map,p=(u,m,h)=>{let w=u!=="done",_=i?{text:Ze(m,w),artifacts:[]}:Qe(m,le.perMessage,w),{cleanText:E,ui:g}=u==="done"?tt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ma(g);return{status:u,text:E,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=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(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of ap(u.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<Zd){let w={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(w),h.id&&c.set(String(h.id),w)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return p("error",s,tp(h.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(u){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${u?.message||u}`)}}function tp(t){let e=String(t||"The agent could not answer.");return Ha(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ma(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.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)}:{}});let r=(t.quickReplies??[]).slice(0,Ho).map(s=>s.slice(0,Bo));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Ho).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Bo)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*ap(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,`
15398
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function je(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{readFileSync as Pp}from"fs";import{createRequire as jp}from"module";import{deflateSync as zd}from"zlib";var qd=[41,121,255],Fd=[255,255,255],jo=new Map;function pa(t){let e=jo.get(t);return e||(e=Wd(t,Ud(t)),jo.set(t,e)),e}function Ud(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,c=i*i+l*l<=r*r?Fd:qd;a.set(c,o*e+1+s*3)}return a}function Wd(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]),da("IHDR",a),da("IDAT",zd(e)),da("IEND",Buffer.alloc(0))])}function da(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(Xd(n)),Buffer.concat([a,n,r])}var Gd=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 Xd(t){let e=4294967295;for(let a of t)e=Gd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function kt(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 Kd(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:kt(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:kt(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:kt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Jd(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:kt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Vd=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Oo(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 h=Yd(s.searchParams.get("timezone")),w=await o.snapshot({date:Qd(h),timezone:h});return a==="/api/app/activity"?ue(e,200,{ts:w.ts,tasks:Jd(w.nodes)}):ue(e,200,{ts:w.ts,nodes:w.nodes.map(Kd)})}if(n==="GET"&&a==="/api/app/approvals")return ue(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Vd);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await Ee(t)}catch(h){return ue(e,400,{error:h.message})}let p=Ue(c.node);if(!p)return ue(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,m;if(i){let h=Ue(c.taskId);if(!h)return ue(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")m=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let _=Ue(c.message);if(!_)return ue(e,400,{error:"message is required"});m=await o.nodePost(p,w,{message:_,sender:u})}}else if(a==="/api/app/nodes/restart")m=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")m=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=Ue(c.cronId);if(!h||typeof c.enabled!="boolean")return ue(e,400,{error:"cronId and enabled (true or false) are required"});m=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=Ue(c.key),w=c.action;if(!h||w!=="yes"&&w!=="no"&&w!=="later")return ue(e,400,{error:"key and action (yes, no or later) are required"});m=await o.decide(p,h,w,u)}return ue(e,m.status,m.body)}function Ue(t){return typeof t=="string"?t.trim():""}function Yd(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Qd(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function Ee(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 ue(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Zd=2048,No=/^[A-Za-z0-9_-]{8,256}$/;async function Do(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 K(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):ep()});if(n==="GET"&&a==="/api/app/alerts")return K(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return K(e,404,{error:"not found"});if(!s||l)return K(e,503,{error:l});let c;try{c=await Ee(t)}catch(h){return K(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),w=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return K(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return K(e,400,{error:`${w} must be true or false`});let E={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),E[ce[g].field]=c[ce[g].field];return K(e,200,{ok:!0,...E})}let p=tp(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return K(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return K(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!No.test(u)||typeof m!="string"||!No.test(m)?K(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?K(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),K(e,200,{ok:!0}))}function ep(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function tp(t,e){if(typeof t!="string"||t.length>Zd)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 K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Da();var Bo=50,ap=280;async function zo(t,e,a,n,r,o){if(a!=="/api/app/announcements")return!1;if(n==="GET"){let s=o.prefs(),i=[],l=null;try{i=np(await o.recent(Bo))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Ho(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Ho(e,404,{error:"not found"})}function qo(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||z(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=Me();return r?new _n(r):null}}}function np(t){let e=[];for(let a of Array.isArray(t)?t:[]){let n=a;!n||n.kind!=="announce"||typeof n.id!="string"||typeof n.at!="string"||e.push({id:n.id.slice(0,64),text:ua(typeof n.summary=="string"?n.summary:"",ap),by:typeof n.agentId=="string"?ua(n.agentId,100):null,node:ua(typeof n.node=="string"?n.node:"",100),at:n.at.slice(0,40)})}return e.sort((a,n)=>(Date.parse(n.at)||0)-(Date.parse(a.at)||0)),e.slice(0,Bo)}function ua(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Ho(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var rp="operator",op=50,Fo=4,Uo=500;function sp(t){let e={channel:"app",chatId:t.chatId,sender:rp,...t.spoken?{via:"voice"}:{}};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 Wo(t,e,a,n){let{path:r,body:o}=sp(e),s="",i=!1,l=[],c=new Map,p=(u,m,h)=>{let w=u!=="done",_=i?{text:Ze(m,w),artifacts:[]}:Qe(m,le.perMessage,w),{cleanText:E,ui:g}=u==="done"?tt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ma(g);return{status:u,text:E,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of lp(u.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<op){let w={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(w),h.id&&c.set(String(h.id),w)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return p("error",s,ip(h.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(u){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${u?.message||u}`)}}function ip(t){let e=String(t||"The agent could not answer.");return qa(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ma(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.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)}:{}});let r=(t.quickReplies??[]).slice(0,Fo).map(s=>s.slice(0,Uo));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Fo).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Uo)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*lp(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,`
15382
15399
  `);let s;for(;(s=n.indexOf(`
15383
15400
 
15384
15401
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
@@ -15388,12 +15405,12 @@ data: ${JSON.stringify(s)}
15388
15405
 
15389
15406
  `)},r=setInterval(()=>{a()&&e.write(`: ping
15390
15407
 
15391
- `)},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()}};function Fo(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=np(i.text);r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:l?"answering":"thinking",preview:l||i.title.slice(0,120),updatedAt:i.startedAt})}for(let i of a){if(r.length>=n)break;o.has(i.id)||(o.add(i.id),r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:"done",status:i.status,preview:fa(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function fa(t,e=120){for(let a of t.split(`
15392
- `)){let n=Uo(a);if(n)return ha(n,e)}return""}function np(t,e=120){let a=t.split(`
15393
- `).map(Uo).filter(Boolean);return a.length?ha(a[a.length-1],e):""}function Uo(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ha(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var St=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Et(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var qo=140;function Tt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${fa(r||"",qo-18)||"something went wrong."}`:fa(n,qo)||"Answered.";return{deviceId:t,title:ha(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var Go=8e3,op=/^[A-Za-z0-9_.:-]{1,64}$/,Te=new Map,ga=new Map,ba=new St;function Xo(){return ba}async function Ko(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/chat/active"&&a!=="/api/app/chat/away"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;let s=o.presence??ba;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await Jo(o)});let i=o.store();if(!i)return D(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),D(e,200,{conversations:Fo(r.id,lp(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),D(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return D(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return D(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Te.get(p.id);return D(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Te.get(p.id);if(!p||!u)return D(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Vo(e);let{id:m,title:h,node:w,nodeName:_,agent:E,agentName:g}=p;return e.write(xa("conversation",{id:m,title:h,node:w,nodeName:_,agent:E,agentName:g})),e.write(xa("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return D(e,404,{error:"not found"});let c;try{c=await Ee(t,64*1024)}catch(p){return D(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return D(e,404,{error:"no such conversation"});let u=Te.get(p.id);return u?(u.ac.abort(),va(p,o,r.name),D(e,200,{stopped:!0})):await va(p,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await ip(e,c,r,i,o),!0}function sp(t,e,a){let n=Oe(e.url),r=new Set,o=[];for(let s of t){let i=Oe(s.url),l=a.find(u=>Oe(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let m=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:m>0||(u.active??0)>0,running:m,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Jo(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return sp(e.nodes,t.daemon,a)}async function ip(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Go){D(t,400,{error:`message must be 1\u2013${Go} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!op.test(_)){D(t,400,{error:"pick an agent"});return}let E=(await Jo(r)).find(d=>d.target===w);if(!E){D(t,400,{error:`unknown node "${w}"`});return}if(!E.online){D(t,409,{error:`${E.name} is offline`});return}let g=E.agents.find(d=>d.id===_);if(!g){D(t,400,{error:`no agent "${_}" on ${E.name}`});return}s=n.create(a.id,{node:w,nodeName:E.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Te.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new _t(r.orphanLimitMs??18e5);Te.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h}=s;ga.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Vo(t),t.write(xa("conversation",{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h})),i.attach(t);try{let w=e.spoken===!0,_=await zo(r.daemon,{node:p,agent:m,message:o,chatId:`app:${l}`,spoken:w},i.ac.signal,(f,x)=>i.broadcast(f,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,va(s,r,a.name));let E=n.appendWithFiles(a.id,l,{role:"assistant",content:_.text,status:_.status,at:Date.now(),..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},..._.tools.length?{tools:_.tools}:{}},_.files)??[];i.broadcast("final",{status:_.status,content:_.text,..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},...E.length?{files:E}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:_.status,attached:g,appOpen:(r.presence??ba).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Et(d)&&r.notifyFinish(Tt(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Te.delete(l),ga.delete(l),i.finish()}}function lp(){let t=[];for(let[e,a]of ga){let n=Te.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Vo(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function xa(t,e){return`event: ${t}
15408
+ `)},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()}};function Xo(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=cp(i.text);r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:l?"answering":"thinking",preview:l||i.title.slice(0,120),updatedAt:i.startedAt})}for(let i of a){if(r.length>=n)break;o.has(i.id)||(o.add(i.id),r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:"done",status:i.status,preview:fa(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function fa(t,e=120){for(let a of t.split(`
15409
+ `)){let n=Ko(a);if(n)return ha(n,e)}return""}function cp(t,e=120){let a=t.split(`
15410
+ `).map(Ko).filter(Boolean);return a.length?ha(a[a.length-1],e):""}function Ko(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ha(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var St=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Et(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Go=140;function Tt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${fa(r||"",Go-18)||"something went wrong."}`:fa(n,Go)||"Answered.";return{deviceId:t,title:ha(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var Vo=8e3,pp=/^[A-Za-z0-9_.:-]{1,64}$/,Te=new Map,ga=new Map,ba=new St;function Yo(){return ba}async function Qo(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/chat/active"&&a!=="/api/app/chat/away"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;let s=o.presence??ba;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await Zo(o)});let i=o.store();if(!i)return D(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),D(e,200,{conversations:Xo(r.id,fp(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),D(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return D(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return D(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Te.get(p.id);return D(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Te.get(p.id);if(!p||!u)return D(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),es(e);let{id:m,title:h,node:w,nodeName:_,agent:E,agentName:g}=p;return e.write(xa("conversation",{id:m,title:h,node:w,nodeName:_,agent:E,agentName:g})),e.write(xa("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return D(e,404,{error:"not found"});let c;try{c=await Ee(t,64*1024)}catch(p){return D(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return D(e,404,{error:"no such conversation"});let u=Te.get(p.id);return u?(u.ac.abort(),va(p,o,r.name),D(e,200,{stopped:!0})):await va(p,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await mp(e,c,r,i,o),!0}function up(t,e,a){let n=Oe(e.url),r=new Set,o=[];for(let s of t){let i=Oe(s.url),l=a.find(u=>Oe(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let m=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:m>0||(u.active??0)>0,running:m,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Zo(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return up(e.nodes,t.daemon,a)}async function mp(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Vo){D(t,400,{error:`message must be 1\u2013${Vo} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!pp.test(_)){D(t,400,{error:"pick an agent"});return}let E=(await Zo(r)).find(d=>d.target===w);if(!E){D(t,400,{error:`unknown node "${w}"`});return}if(!E.online){D(t,409,{error:`${E.name} is offline`});return}let g=E.agents.find(d=>d.id===_);if(!g){D(t,400,{error:`no agent "${_}" on ${E.name}`});return}s=n.create(a.id,{node:w,nodeName:E.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Te.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new _t(r.orphanLimitMs??18e5);Te.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h}=s;ga.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),es(t),t.write(xa("conversation",{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h})),i.attach(t);try{let w=e.spoken===!0,_=await Wo(r.daemon,{node:p,agent:m,message:o,chatId:`app:${l}`,spoken:w},i.ac.signal,(f,x)=>i.broadcast(f,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,va(s,r,a.name));let E=n.appendWithFiles(a.id,l,{role:"assistant",content:_.text,status:_.status,at:Date.now(),..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},..._.tools.length?{tools:_.tools}:{}},_.files)??[];i.broadcast("final",{status:_.status,content:_.text,..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},...E.length?{files:E}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:_.status,attached:g,appOpen:(r.presence??ba).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Et(d)&&r.notifyFinish(Tt(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Te.delete(l),ga.delete(l),i.finish()}}function fp(){let t=[];for(let[e,a]of ga){let n=Te.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function es(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function xa(t,e){return`event: ${t}
15394
15411
  data: ${JSON.stringify(e)}
15395
15412
 
15396
- `}async function va(t,e,a){try{let n=Oe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Oe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Oe(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 Oe(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as cp}from"stream";var dp=/^\/api\/app\/files\/([^/]+)$/,pp=15e3;async function Qo(t,e,a,n,r,o){let s=dp.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ae(e,405,{error:"GET only"});let i=o.store();if(!i)return Ae(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return Ae(e,404,{error:"no such file"});let p=await up(c.node,o);if(!p)return Ae(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),pp),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${nn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Ae(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return Ae(e,f,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let w=Number(h.headers.get("content-length")||0);if(w>le.bytes)return u.abort(),Ae(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...rn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(w)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let E=0,g=cp.fromWeb(h.body);return g.on("data",d=>{E+=d.length,E>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function up(t,e){if(t==="local")return{url:Yo(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Yo(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Yo(t){return t.replace(/\/+$/,"")}function Ae(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var es=8e3;async function ts(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return J(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!mn(h))return J(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let w=un(t.headers["x-audio-duration-ms"]);if(w)return t.resume(),J(e,w.status,{error:w.error});let _=await Re(t,pn.bytes);if(!_)return J(e,413,{error:fn()});if(!_.length)return J(e,400,{error:"The recording is empty."});let E={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Zo(e,o.daemon,"/voice/transcribe",_,E,18e4)}let s,i=await Re(t,64*1024);if(!i)return J(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return J(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return J(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return J(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,es):"";if(!p.trim())return J(e,400,{error:"text is required"});if(!fp(c.messages,p))return J(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return Zo(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Zo(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(mp(l)?.endpoints)?J(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return J(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function mp(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function fp(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===es&&a.content.startsWith(e)))}var hp=new Set(["ring","offer","answer","ice","hangup"]),At=/^[A-Za-z0-9_-]{4,64}$/,gp=128*1024;async function as(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return $(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return $(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return $(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=He(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>He(String(h?.name??""))!==p),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return $(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,gp);if(!l)return $(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=xp(c,r.nodeName);if(typeof p=="string")return $(e,400,{error:p});let u=ns(p.to);if(u&&p.kind==="ring"){let m=await We(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return $(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return $(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return At.test(l)?vp(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):$(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,4096);if(!l)return $(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!At.test(p))return $(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await We(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return $(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return $(e,405,{error:"GET"});let l=await We(o,s,"GET","/calls/asking");if(l.status>=300)return $(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return $(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return $(e,405,{error:"POST"});let l=await We(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return $(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!At.test(l))return $(e,400,{error:"callId is required"});let c=await We(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return $(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return $(e,404,{error:"not found"})}function ns(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function We(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function xp(t,e){let a=String(t?.kind??"");if(!hp.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!At.test(n))return"callId must be 4 to 64 letters, digits, - or _";let r=typeof t?.to=="string"?t.to.trim():"";if(!r||r.length>100)return"to must name a machine or an agent";if(r.startsWith("bot:")&&!ns(r))return"to must be bot:<agent id> for an agent";if(He(r)===He(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function vp(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?$(e,503,{error:"Calls are off on this computer."}):$(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var bp={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},Ct=class{constructor(e=bp,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},yp="That code didn't work. Check it, or run agentx app pair for a new one.",wp=400;async function rs(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await Ee(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await kp(a,e.minMs??wp),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:yp}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function kp(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function ya(t,e){if(!t)return"absent";let a=Qa(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var It=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function ss(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=os(t.headers["sec-fetch-mode"]),n.site=os(t.headers["sec-fetch-site"]),n}function os(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var is=`
15413
+ `}async function va(t,e,a){try{let n=Oe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Oe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Oe(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 Oe(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as hp}from"stream";var gp=/^\/api\/app\/files\/([^/]+)$/,xp=15e3;async function as(t,e,a,n,r,o){let s=gp.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ae(e,405,{error:"GET only"});let i=o.store();if(!i)return Ae(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return Ae(e,404,{error:"no such file"});let p=await vp(c.node,o);if(!p)return Ae(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),xp),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${on}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Ae(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return Ae(e,f,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let w=Number(h.headers.get("content-length")||0);if(w>le.bytes)return u.abort(),Ae(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...sn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(w)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let E=0,g=hp.fromWeb(h.body);return g.on("data",d=>{E+=d.length,E>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function vp(t,e){if(t==="local")return{url:ts(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ts(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ts(t){return t.replace(/\/+$/,"")}function Ae(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var rs=8e3;async function os(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return J(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!hn(h))return J(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let w=fn(t.headers["x-audio-duration-ms"]);if(w)return t.resume(),J(e,w.status,{error:w.error});let _=await Re(t,mn.bytes);if(!_)return J(e,413,{error:gn()});if(!_.length)return J(e,400,{error:"The recording is empty."});let E={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return ns(e,o.daemon,"/voice/transcribe",_,E,18e4)}let s,i=await Re(t,64*1024);if(!i)return J(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return J(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return J(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return J(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,rs):"";if(!p.trim())return J(e,400,{error:"text is required"});if(!yp(c.messages,p))return J(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return ns(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function ns(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(bp(l)?.endpoints)?J(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return J(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function bp(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function yp(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===rs&&a.content.startsWith(e)))}var wp=new Set(["ring","offer","answer","ice","hangup"]),At=/^[A-Za-z0-9_-]{4,64}$/,kp=128*1024;async function ss(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return $(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return $(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return $(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=He(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>He(String(h?.name??""))!==p),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return $(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,kp);if(!l)return $(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=_p(c,r.nodeName);if(typeof p=="string")return $(e,400,{error:p});let u=is(p.to);if(u&&p.kind==="ring"){let m=await We(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return $(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return $(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return At.test(l)?Sp(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):$(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Re(t,4096);if(!l)return $(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!At.test(p))return $(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await We(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return $(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return $(e,405,{error:"GET"});let l=await We(o,s,"GET","/calls/asking");if(l.status>=300)return $(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return $(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return $(e,405,{error:"POST"});let l=await We(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return $(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!At.test(l))return $(e,400,{error:"callId is required"});let c=await We(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return $(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return $(e,404,{error:"not found"})}function is(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function We(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function _p(t,e){let a=String(t?.kind??"");if(!wp.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!At.test(n))return"callId must be 4 to 64 letters, digits, - or _";let r=typeof t?.to=="string"?t.to.trim():"";if(!r||r.length>100)return"to must name a machine or an agent";if(r.startsWith("bot:")&&!is(r))return"to must be bot:<agent id> for an agent";if(He(r)===He(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function Sp(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?$(e,503,{error:"Calls are off on this computer."}):$(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ep={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},Ct=class{constructor(e=Ep,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},Tp="That code didn't work. Check it, or run agentx app pair for a new one.",Ap=400;async function ls(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await Ee(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await Cp(a,e.minMs??Ap),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:Tp}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function Cp(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function ya(t,e){if(!t)return"absent";let a=en(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var It=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function ds(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=cs(t.headers["sec-fetch-mode"]),n.site=cs(t.headers["sec-fetch-site"]),n}function cs(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var ps=`
15397
15414
  (function () {
15398
15415
  var fleetPanel = document.getElementById('panel-fleet');
15399
15416
  var activityPanel = document.getElementById('panel-activity');
@@ -15637,7 +15654,7 @@ data: ${JSON.stringify(e)}
15637
15654
  setInterval(refresh, 15000);
15638
15655
  refresh();
15639
15656
  })();
15640
- `;var ls=`
15657
+ `;var us=`
15641
15658
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
15642
15659
  .fx-head h2 { margin: 4px 0 0; }
15643
15660
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -15694,7 +15711,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15694
15711
  }
15695
15712
  .fx-error:empty { display: none; }
15696
15713
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
15697
- `;var cs=`
15714
+ `;var ms=`
15698
15715
  (function () {
15699
15716
  var panel = document.getElementById('panel-alerts');
15700
15717
  if (!panel) return;
@@ -15875,7 +15892,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15875
15892
  refresh();
15876
15893
  loadRecent();
15877
15894
  })();
15878
- `;var ds=`
15895
+ `;var fs=`
15879
15896
  (function () {
15880
15897
  var panel = document.getElementById('panel-alerts');
15881
15898
  if (!panel) return;
@@ -15988,7 +16005,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15988
16005
  }
15989
16006
  load();
15990
16007
  })();
15991
- `;var ps=`
16008
+ `;var hs=`
15992
16009
  (function () {
15993
16010
  var panel = document.getElementById('panel-chat');
15994
16011
  var V = window.AXChatView;
@@ -16260,7 +16277,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16260
16277
  var last = recall('ax-chat-conv');
16261
16278
  if (!fromHash() && last) openConversation(last);
16262
16279
  })();
16263
- `;var us=`
16280
+ `;var gs=`
16264
16281
  window.AXChatView = (function () {
16265
16282
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
16266
16283
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -16541,7 +16558,7 @@ window.AXChatView = (function () {
16541
16558
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
16542
16559
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
16543
16560
  })();
16544
- `;var ms=`
16561
+ `;var xs=`
16545
16562
  window.AXChatSheets = function (o) {
16546
16563
  var V = o.V, picker = o.picker, hist = o.hist;
16547
16564
  function loadPicker() {
@@ -16587,7 +16604,7 @@ window.AXChatSheets = function (o) {
16587
16604
  });
16588
16605
  return { loadPicker: loadPicker, loadHistory: loadHistory };
16589
16606
  };
16590
- `;var fs=`
16607
+ `;var vs=`
16591
16608
  window.AXChatLog = function (o) {
16592
16609
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
16593
16610
  function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
@@ -16650,7 +16667,7 @@ window.AXChatLog = function (o) {
16650
16667
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
16651
16668
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
16652
16669
  };
16653
- `;var hs=`
16670
+ `;var bs=`
16654
16671
  (function () {
16655
16672
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
16656
16673
  var top = panel && panel.querySelector('.cx-top');
@@ -16800,7 +16817,7 @@ window.AXChatLog = function (o) {
16800
16817
  window.AXStrip = { poll: poll, update: update, banner: banner };
16801
16818
  poll();
16802
16819
  })();
16803
- `;var gs=`
16820
+ `;var ys=`
16804
16821
  .cs { margin: 0 -2px; }
16805
16822
  .cs[hidden] { display: none; }
16806
16823
  .cs-list {
@@ -16856,7 +16873,7 @@ window.AXChatLog = function (o) {
16856
16873
  @media (prefers-reduced-motion: reduce) {
16857
16874
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
16858
16875
  }
16859
- `;function xs(t,e,a=5){if(t.some(o=>o.key===e.key))return{queue:t.slice(),dropped:[]};let n=t.concat([e]),r=Math.max(0,n.length-Math.max(1,a));return{queue:n.slice(r),dropped:n.slice(0,r)}}function vs(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var bs=`
16876
+ `;function ws(t,e,a=5){if(t.some(o=>o.key===e.key))return{queue:t.slice(),dropped:[]};let n=t.concat([e]),r=Math.max(0,n.length-Math.max(1,a));return{queue:n.slice(r),dropped:n.slice(0,r)}}function ks(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var _s=`
16860
16877
  body { height: 100dvh; }
16861
16878
  main { min-height: 0; }
16862
16879
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -16966,7 +16983,7 @@ main { min-height: 0; }
16966
16983
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
16967
16984
  }
16968
16985
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
16969
- `;var ys=`
16986
+ `;var Ss=`
16970
16987
  window.AXOrb = (function () {
16971
16988
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
16972
16989
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -17097,7 +17114,7 @@ window.AXOrb = (function () {
17097
17114
  }
17098
17115
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
17099
17116
  })();
17100
- `;var ws=`
17117
+ `;var Es=`
17101
17118
  window.AXVoiceIO = (function () {
17102
17119
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
17103
17120
  var ac = null, playing = null;
@@ -17215,7 +17232,7 @@ window.AXVoiceIO = (function () {
17215
17232
 
17216
17233
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
17217
17234
  })();
17218
- `;var ks=`
17235
+ `;var Ts=`
17219
17236
  (function () {
17220
17237
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
17221
17238
  if (!panel || !C || !IO || !O) return;
@@ -17423,7 +17440,7 @@ window.AXVoiceIO = (function () {
17423
17440
  idle();
17424
17441
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
17425
17442
  })();
17426
- `;var _s=`
17443
+ `;var As=`
17427
17444
  .vx {
17428
17445
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
17429
17446
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -17459,7 +17476,7 @@ window.AXVoiceIO = (function () {
17459
17476
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
17460
17477
  .cx-typing-on .vx-row { gap: 16px; }
17461
17478
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
17462
- `;var Ss=`
17479
+ `;var Cs=`
17463
17480
  <main class="card">
17464
17481
  <h1>This phone isn't paired</h1>
17465
17482
  <p>On the computer running AgentX, open a terminal in the folder that holds <code>agentx.json</code> and run <code>agentx app pair</code>. Scan the QR code it shows, or type the code under it.</p>
@@ -17473,7 +17490,7 @@ window.AXVoiceIO = (function () {
17473
17490
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
17474
17491
  </form>
17475
17492
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
17476
- </main>`,Es=`
17493
+ </main>`,Is=`
17477
17494
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
17478
17495
  .pair-form label { font-weight: 600; }
17479
17496
  .pair-form input {
@@ -17495,7 +17512,7 @@ window.AXVoiceIO = (function () {
17495
17512
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
17496
17513
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
17497
17514
  }
17498
- `,Ts=`
17515
+ `,Ms=`
17499
17516
  (function () {
17500
17517
  var form = document.getElementById('pair-form');
17501
17518
  var input = document.getElementById('pair-code');
@@ -17587,7 +17604,7 @@ window.AXVoiceIO = (function () {
17587
17604
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
17588
17605
  }
17589
17606
  })();
17590
- `;function As(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Cs(t,e){return!t||e-t>=3e4||t>e}function Is(t,e){let a="23456789ABCDEFGHJKMNPQRSTUVWXYZ",n=String(t||"").toUpperCase(),r=Math.max(0,Math.min(Number(e)||0,n.length)),o="",s=0;for(let l=0;l<n.length&&o.length<8;l++)a.indexOf(n.charAt(l))<0||(o+=n.charAt(l),l<r&&s++);let i=o.length>4?o.slice(0,4)+"-"+o.slice(4):o;return{value:i,caret:Math.min(s>4?s+1:s,i.length)}}function Ms(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}var Rs=`
17607
+ `;function Rs(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Ls(t,e){return!t||e-t>=3e4||t>e}function $s(t,e){let a="23456789ABCDEFGHJKMNPQRSTUVWXYZ",n=String(t||"").toUpperCase(),r=Math.max(0,Math.min(Number(e)||0,n.length)),o="",s=0;for(let l=0;l<n.length&&o.length<8;l++)a.indexOf(n.charAt(l))<0||(o+=n.charAt(l),l<r&&s++);let i=o.length>4?o.slice(0,4)+"-"+o.slice(4):o;return{value:i,caret:Math.min(s>4?s+1:s,i.length)}}function Ps(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}var js=`
17591
17608
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
17592
17609
  <video id="scan-video" playsinline muted autoplay></video>
17593
17610
  <div class="scan-frame" aria-hidden="true"></div>
@@ -17596,7 +17613,7 @@ window.AXVoiceIO = (function () {
17596
17613
  <button type="button" id="scan-close" class="scan-close">Close</button>
17597
17614
  </div>
17598
17615
  <p id="scan-msg" class="scan-msg" role="status" aria-live="polite">Point the camera at the QR code shown by agentx app pair.</p>
17599
- </div>`,Ls=`
17616
+ </div>`,Os=`
17600
17617
  .pair-form .scan-btn {
17601
17618
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
17602
17619
  }
@@ -17625,7 +17642,7 @@ window.AXVoiceIO = (function () {
17625
17642
  }
17626
17643
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
17627
17644
  body.scanning { overflow: hidden; }
17628
- `,$s=`
17645
+ `,Ns=`
17629
17646
  (function () {
17630
17647
  var openBtn = document.getElementById('scan-btn');
17631
17648
  var box = document.getElementById('scan');
@@ -17833,7 +17850,7 @@ body.scanning { overflow: hidden; }
17833
17850
  border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
17834
17851
  }
17835
17852
  .cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
17836
- `;var Ps='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',js=`
17853
+ `;var Ds='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',Hs=`
17837
17854
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
17838
17855
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
17839
17856
  <span class="cam-dot" aria-hidden="true"></span>
@@ -17858,7 +17875,7 @@ body.scanning { overflow: hidden; }
17858
17875
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
17859
17876
  </div>
17860
17877
  </div>
17861
- </div>`,Os=`
17878
+ </div>`,Bs=`
17862
17879
  (function () {
17863
17880
  var btn = document.getElementById('cam-btn');
17864
17881
  var sheet = document.getElementById('cam');
@@ -18127,7 +18144,7 @@ body.scanning { overflow: hidden; }
18127
18144
  });
18128
18145
  window.addEventListener('pagehide', function () { stop(); });
18129
18146
  })();
18130
- `;var Ns=`
18147
+ `;var zs=`
18131
18148
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
18132
18149
  <div class="cam-askbar-text">
18133
18150
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -18137,7 +18154,7 @@ body.scanning { overflow: hidden; }
18137
18154
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
18138
18155
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
18139
18156
  </div>
18140
- </div>`,Ds=`
18157
+ </div>`,qs=`
18141
18158
  .cam-askbar[hidden] { display: none; }
18142
18159
  .cam-askbar {
18143
18160
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -18152,7 +18169,7 @@ body.scanning { overflow: hidden; }
18152
18169
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
18153
18170
  }
18154
18171
  .cam-askbar-no { background: transparent; color: #fff; }
18155
- `,Hs=`
18172
+ `,Fs=`
18156
18173
  (function () {
18157
18174
  var bar = document.getElementById('cam-ask-bar');
18158
18175
  if (!bar) return;
@@ -18222,8 +18239,8 @@ body.scanning { overflow: hidden; }
18222
18239
  setInterval(poll, 5000);
18223
18240
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
18224
18241
  })();
18225
- `;function Bs(t,e){let a={width:1280,height:720,frameRate:15},n=t||a;return{audio:!1,video:{facingMode:{ideal:e==="user"?"user":"environment"},width:{ideal:n.width||a.width},height:{ideal:n.height||a.height},frameRate:{ideal:n.frameRate||a.frameRate}}}}function zs(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}var ka=`
18226
- ${U({afterUnauthorized:As})}
18242
+ `;function Us(t,e){let a={width:1280,height:720,frameRate:15},n=t||a;return{audio:!1,video:{facingMode:{ideal:e==="user"?"user":"environment"},width:{ideal:n.width||a.width},height:{ideal:n.height||a.height},frameRate:{ideal:n.frameRate||a.frameRate}}}}function Ws(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}var ka=`
18243
+ ${U({afterUnauthorized:Rs})}
18227
18244
  var CACHE = 'agentx-app-v3';
18228
18245
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
18229
18246
  self.addEventListener('install', function (e) {
@@ -18314,7 +18331,7 @@ self.addEventListener('notificationclick', function (e) {
18314
18331
  return self.clients.openWindow(target);
18315
18332
  }));
18316
18333
  });
18317
- `;var _p="<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 _a(t){return`<meta charset="utf-8">
18334
+ `;var Ip="<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 _a(t){return`<meta charset="utf-8">
18318
18335
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
18319
18336
  <meta name="theme-color" content="#2979FF">
18320
18337
  <meta name="referrer" content="no-referrer">
@@ -18325,37 +18342,37 @@ self.addEventListener('notificationclick', function (e) {
18325
18342
  <link rel="icon" type="image/png" href="/app/icon-192.png">
18326
18343
  <link rel="apple-touch-icon" href="/app/icon-192.png">
18327
18344
  <title>${t}</title>
18328
- ${_p}
18329
- <style>${_n}${Tp}</style>`}var qs=[{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 Fs(){let t=qs.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=qs.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
18345
+ ${Ip}
18346
+ <style>${En}${Lp}</style>`}var Gs=[{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 Xs(){let t=Gs.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=Gs.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
18330
18347
  <h2>${a.label}</h2>
18331
18348
  <p class="soon">${a.soon}</p>
18332
18349
  </section>`).join("");return`<!doctype html>
18333
18350
  <html lang="en">
18334
- <head>${_a("AgentX")}<style>${Ap}${ls}${bs}${gs}${_s}${wa}${Ds}</style></head>
18351
+ <head>${_a("AgentX")}<style>${$p}${us}${_s}${ys}${As}${wa}${qs}</style></head>
18335
18352
  <body>
18336
18353
  <header class="bar">
18337
18354
  <div>
18338
18355
  <h1>AgentX</h1>
18339
18356
  <p id="who" class="who">Connecting\u2026</p>
18340
18357
  </div>
18341
- <div class="bar-btns">${Ps}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
18358
+ <div class="bar-btns">${Ds}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
18342
18359
  </header>
18343
18360
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
18344
- ${Ns}
18361
+ ${zs}
18345
18362
  <main>${e}</main>
18346
18363
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
18347
- ${js}
18348
- <script>${Sp}</script>
18349
- <script>${is}</script>
18350
- <script>${cs}</script>
18351
- <script>${ds}</script>
18352
- <script>${U({markdownToHtml:Sn})}${us}${fs}${ms}${ps}</script>
18353
- <script>${U({queueSpeech:xs,nextSpeech:vs})}${ys}${ws}${ks}</script>
18354
- <script>${hs}</script>
18355
- <script>${U({cameraConstraints:Bs,shareClock:zs})}${Os}</script>
18356
- <script>${Hs}</script>
18364
+ ${Hs}
18365
+ <script>${Mp}</script>
18366
+ <script>${ps}</script>
18367
+ <script>${ms}</script>
18368
+ <script>${fs}</script>
18369
+ <script>${U({markdownToHtml:Tn})}${gs}${vs}${xs}${hs}</script>
18370
+ <script>${U({queueSpeech:ws,nextSpeech:ks})}${Ss}${Es}${Ts}</script>
18371
+ <script>${bs}</script>
18372
+ <script>${U({cameraConstraints:Us,shareClock:Ws})}${Bs}</script>
18373
+ <script>${Fs}</script>
18357
18374
  </body>
18358
- </html>`}function Us(){return`<!doctype html>
18375
+ </html>`}function Ks(){return`<!doctype html>
18359
18376
  <html lang="en">
18360
18377
  <head>${_a("Pair \xB7 AgentX")}</head>
18361
18378
  <body>
@@ -18363,17 +18380,17 @@ ${js}
18363
18380
  <h1>Pairing this phone\u2026</h1>
18364
18381
  <p id="msg" role="status">One moment.</p>
18365
18382
  </main>
18366
- <script>${Ep}</script>
18383
+ <script>${Rp}</script>
18367
18384
  </body>
18368
- </html>`}function Ws(){return`<!doctype html>
18385
+ </html>`}function Js(){return`<!doctype html>
18369
18386
  <html lang="en">
18370
- <head>${_a("Not paired \xB7 AgentX")}<style>${Es}${Ls}</style></head>
18371
- <body>${Ss}${Rs}
18372
- <script>${U({mayBounce:Cs,formatPairInput:Is,parsePairScan:Ms})}</script>
18373
- <script>${Ts}</script>
18374
- <script>${$s}</script>
18387
+ <head>${_a("Not paired \xB7 AgentX")}<style>${Is}${Os}</style></head>
18388
+ <body>${Cs}${js}
18389
+ <script>${U({mayBounce:Ls,formatPairInput:$s,parsePairScan:Ps})}</script>
18390
+ <script>${Ms}</script>
18391
+ <script>${Ns}</script>
18375
18392
  </body>
18376
- </html>`}function Gs(){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 Sp=`
18393
+ </html>`}function Vs(){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 Mp=`
18377
18394
  (function () {
18378
18395
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
18379
18396
  function select(tab, focus, keepHash) {
@@ -18443,7 +18460,7 @@ ${js}
18443
18460
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
18444
18461
  }
18445
18462
  })();
18446
- `,Ep=`
18463
+ `,Rp=`
18447
18464
  (function () {
18448
18465
  var msg = document.getElementById('msg');
18449
18466
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -18460,7 +18477,7 @@ ${js}
18460
18477
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
18461
18478
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
18462
18479
  })();
18463
- `,Tp=`
18480
+ `,Lp=`
18464
18481
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
18465
18482
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
18466
18483
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -18472,7 +18489,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
18472
18489
  .card h1 { font-size: 22px; margin: 0 0 12px; }
18473
18490
  .muted { color: var(--ax-text-2); }
18474
18491
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
18475
- `,Ap=`
18492
+ `,$p=`
18476
18493
  body { display: flex; flex-direction: column; }
18477
18494
  .bar {
18478
18495
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -18510,8 +18527,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
18510
18527
  }
18511
18528
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
18512
18529
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
18513
- `;var Mt="agentx_app",Mp=400*86400,Rp=new Ct,Lp=new It;async function Xs(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new ne;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ge(e,200,"application/manifest+json",Gs());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ge(e,200,"text/javascript; charset=utf-8",ka);if(a==="/app/icon-192.png")return ge(e,200,"image/png",pa(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ge(e,200,"image/png",pa(512),"public, max-age=86400");if(a==="/app/pair")return ge(e,200,"text/html; charset=utf-8",Us());if(a==="/app/qr.js"){let i=$p();return i?ge(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Ce(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Sa(Xe(t),o);return i?(e.setHeader("Set-Cookie",Ea(Xe(t))),Ce(e,200,{device:i.name})):Ce(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await rs(t,{codes:r.pairCodes??new $n,limiter:r.pairLimiter??Rp,verify:l=>Sa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ea(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ce(e,i.status,i.body)}let s=Sa(Pp(t),o);if(!s){let i=Xe(t);return(r.rejectLog??Lp).record(a.slice(0,120),ss(t,ya(Ta(t,Mt),o),i?ya(i,o):null)),a==="/app"?ge(e,401,"text/html; charset=utf-8",Ws()):Ce(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Ta(t,Mt);return i&&!Xe(t)&&e.setHeader("Set-Cookie",Ea(i)),ge(e,200,"text/html; charset=utf-8",Fs())}return n==="GET"&&a==="/api/app/me"?Ce(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Lo(t,e,a,n,s.name,r.fleet)||r.push&&await Po(t,e,a,n,s,r.push)||r.announce&&await No(t,e,a,n,s,r.announce)||r.chat&&await Ko(t,e,a,n,s,r.chat)||r.chat&&await Qo(t,e,a,n,s,r.chat)||r.voice&&await ts(t,e,a,n,s,r.voice)||r.camera&&await as(t,e,a,n,r.camera)?!0:Ce(e,404,{error:"not found"})}var Ge;function $p(){if(Ge!==void 0)return Ge;try{let t=Ip(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
18514
- `;Ge=Buffer.concat([Buffer.from(a),Cp(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ge=null}return Ge}function Sa(t,e){if(!t)return null;let a=e.verify(t);return a&&ye(a,"app")?a:null}function Ea(t){return`${Mt}=${t}; Path=/; Max-Age=${Mp}; HttpOnly; Secure; SameSite=Lax`}function Pp(t){return Xe(t)??Ta(t,Mt)}function Xe(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ta(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 ge(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ce(t,e,a){return ge(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Ks}from"crypto";var Ie={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},jp=/^[a-f0-9]{32}$/,Op=/^c[a-z0-9]{8,32}$/,Np=/^#[0-9a-fA-F]{6}$/;function Aa(t){return Op.test(t)}var Ke=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
18530
+ `;var Mt="agentx_app",Op=400*86400,Np=new Ct,Dp=new It;async function Ys(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new ne;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ge(e,200,"application/manifest+json",Vs());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ge(e,200,"text/javascript; charset=utf-8",ka);if(a==="/app/icon-192.png")return ge(e,200,"image/png",pa(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ge(e,200,"image/png",pa(512),"public, max-age=86400");if(a==="/app/pair")return ge(e,200,"text/html; charset=utf-8",Ks());if(a==="/app/qr.js"){let i=Hp();return i?ge(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Ce(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Sa(Xe(t),o);return i?(e.setHeader("Set-Cookie",Ea(Xe(t))),Ce(e,200,{device:i.name})):Ce(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await ls(t,{codes:r.pairCodes??new jn,limiter:r.pairLimiter??Np,verify:l=>Sa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ea(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ce(e,i.status,i.body)}let s=Sa(Bp(t),o);if(!s){let i=Xe(t);return(r.rejectLog??Dp).record(a.slice(0,120),ds(t,ya(Ta(t,Mt),o),i?ya(i,o):null)),a==="/app"?ge(e,401,"text/html; charset=utf-8",Js()):Ce(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Ta(t,Mt);return i&&!Xe(t)&&e.setHeader("Set-Cookie",Ea(i)),ge(e,200,"text/html; charset=utf-8",Xs())}return n==="GET"&&a==="/api/app/me"?Ce(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Oo(t,e,a,n,s.name,r.fleet)||r.push&&await Do(t,e,a,n,s,r.push)||r.announce&&await zo(t,e,a,n,s,r.announce)||r.chat&&await Qo(t,e,a,n,s,r.chat)||r.chat&&await as(t,e,a,n,s,r.chat)||r.voice&&await os(t,e,a,n,s,r.voice)||r.camera&&await ss(t,e,a,n,r.camera)?!0:Ce(e,404,{error:"not found"})}var Ge;function Hp(){if(Ge!==void 0)return Ge;try{let t=jp(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
18531
+ `;Ge=Buffer.concat([Buffer.from(a),Pp(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ge=null}return Ge}function Sa(t,e){if(!t)return null;let a=e.verify(t);return a&&ye(a,"app")?a:null}function Ea(t){return`${Mt}=${t}; Path=/; Max-Age=${Op}; HttpOnly; Secure; SameSite=Lax`}function Bp(t){return Xe(t)??Ta(t,Mt)}function Xe(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ta(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 ge(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ce(t,e,a){return ge(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Qs}from"crypto";var Ie={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},zp=/^[a-f0-9]{32}$/,qp=/^c[a-z0-9]{8,32}$/,Fp=/^#[0-9a-fA-F]{6}$/;function Aa(t){return qp.test(t)}var Ke=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
18515
18532
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
18516
18533
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
18517
18534
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -18524,39 +18541,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
18524
18541
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
18525
18542
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
18526
18543
  CREATE INDEX IF NOT EXISTS app_chat_files_conversation ON app_chat_files(conversation_id);`),e.prepare("PRAGMA table_info(app_chat_messages)").all().some(r=>r.name==="files")||e.exec("ALTER TABLE app_chat_messages ADD COLUMN files TEXT");let n=e.prepare("PRAGMA table_info(app_chat_conversations)").all();n.some(r=>r.name==="read_at")||e.transaction(()=>{e.prepare("PRAGMA table_info(app_chat_conversations)").all().some(o=>o.name==="read_at")||(e.exec("ALTER TABLE app_chat_conversations ADD COLUMN read_at INTEGER"),e.exec("UPDATE app_chat_conversations SET read_at = updated_at"))}).immediate(),n.some(r=>r.name==="color")||e.exec("ALTER TABLE app_chat_conversations ADD COLUMN color TEXT"),e.exec(`CREATE TABLE IF NOT EXISTS app_chat_delivered (
18527
- key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Aa(e)?this.db.prepare("SELECT device_id FROM app_chat_conversations WHERE id = ?").get(e)?.device_id??null:null}appendOnce(e,a,n,r,o=[],s=Date.now()){return!n||n.length>200?null:this.db.transaction(()=>!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e)||this.db.prepare("INSERT OR IGNORE INTO app_chat_delivered (key, conversation_id, at) VALUES (?, ?, ?)").run(n,a,s).changes===0?null:(this.db.prepare("DELETE FROM app_chat_delivered WHERE at < ?").run(s-30*24*60*6e4),this.appendWithFiles(e,a,r,o))).immediate()}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${Ks(4).toString("hex")}`,{color:s,...i}=a,l=s&&Np.test(s)?s:void 0,c={id:o,title:Hp(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
18528
- (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!Aa(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(Dp);return{...Js(n),messages:r}}list(e,a=Ie.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
18544
+ key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Aa(e)?this.db.prepare("SELECT device_id FROM app_chat_conversations WHERE id = ?").get(e)?.device_id??null:null}appendOnce(e,a,n,r,o=[],s=Date.now()){return!n||n.length>200?null:this.db.transaction(()=>!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e)||this.db.prepare("INSERT OR IGNORE INTO app_chat_delivered (key, conversation_id, at) VALUES (?, ?, ?)").run(n,a,s).changes===0?null:(this.db.prepare("DELETE FROM app_chat_delivered WHERE at < ?").run(s-30*24*60*6e4),this.appendWithFiles(e,a,r,o))).immediate()}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${Qs(4).toString("hex")}`,{color:s,...i}=a,l=s&&Fp.test(s)?s:void 0,c={id:o,title:Wp(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
18545
+ (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!Aa(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(Up);return{...Zs(n),messages:r}}list(e,a=Ie.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
18529
18546
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
18530
18547
  (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
18531
- 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{...Js(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Aa(a)&&this.db.prepare("UPDATE app_chat_conversations SET read_at = MAX(COALESCE(read_at, 0), ?) WHERE id = ? AND device_id = ?").run(n,a,e)}unread(e,a){return this.db.prepare(`SELECT c.id, c.title, c.agent, c.agent_name, c.color,
18548
+ 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{...Zs(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Aa(a)&&this.db.prepare("UPDATE app_chat_conversations SET read_at = MAX(COALESCE(read_at, 0), ?) WHERE id = ? AND device_id = ?").run(n,a,e)}unread(e,a){return this.db.prepare(`SELECT c.id, c.title, c.agent, c.agent_name, c.color,
18532
18549
  substr(m.content, 1, 240) AS answer, m.status, m.at
18533
18550
  FROM app_chat_conversations c
18534
18551
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
18535
18552
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
18536
18553
  ORDER BY m.at DESC, m.id DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>({id:r.id,title:r.title,agent:r.agent,...r.agent_name?{agentName:r.agent_name}:{},...r.color?{color:r.color}:{},answer:String(r.answer??"").trim(),status:r.status==="error"||r.status==="stopped"?r.status:"done",at:r.at}))}append(e,a,n){return this.appendWithFiles(e,a,n)!==null}appendWithFiles(e,a,n,r=[]){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return null;let s=n.content.length>Ie.content?n.content.slice(0,Ie.content)+`
18537
18554
 
18538
- [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Ie.toolsPerMessage),l=[];for(let m of r){if(l.length>=Ie.filesPerMessage)break;let h=m.filename.trim(),w=Ua(h);if(!w||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Ks(16).toString("hex"),name:_,mime:w.mime,kind:w.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
18555
+ [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Ie.toolsPerMessage),l=[];for(let m of r){if(l.length>=Ie.filesPerMessage)break;let h=m.filename.trim(),w=Ga(h);if(!w||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Qs(16).toString("hex"),name:_,mime:w.mime,kind:w.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
18539
18556
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,c.length?JSON.stringify(c):null,n.at),u=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
18540
18557
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)u.run(m.id,a,Number(p.lastInsertRowid),m.path,m.name,m.mime,m.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
18541
18558
  (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ie.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
18542
- (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!jp.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
18559
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!zp.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
18543
18560
  JOIN app_chat_conversations c ON c.id = f.conversation_id WHERE f.id = ? AND c.device_id = ?`).get(a,e);return n?{id:n.id,name:n.name,mime:n.mime,kind:n.kind,path:n.path,conversationId:n.conversation_id,node:n.node,agent:n.agent}:null}pruneDevice(e){let a=this.db.prepare(`SELECT id FROM app_chat_conversations WHERE device_id = ?
18544
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ie.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),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 Js(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}:{},...t.color?{color:t.color}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function Dp(t){let e=o=>{if(o)try{return JSON.parse(o)}catch{return}},a=e(t.ui),n=e(t.tools),r=e(t.files);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}:{},...r?{files:r}:{}}}function Hp(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Bp=4e3,Ca=100,zp=15,Vs=t=>t.replace(/\/+$/,""),Rt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Bp){this.timer||(this.timer=setInterval(()=>{this.tick()},e),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async tick(){if(this.running)return 0;this.running=!0;try{let e,a=!1;try{let o=await this.deps.recent(this.cursor,Ca);e=Array.isArray(o)?o:o.events,a=!Array.isArray(o)&&o.gap===!0}catch{return 0}this.warnIfSkipped(e.length,a),e.length&&(this.cursor=e[e.length-1].id);let n=[...this.retry.values()].map(o=>o.event);for(let o of e)o.kind==="delegation"&&o.type==="reply"&&typeof o.ref=="string"&&o.ref&&!this.retry.has(o.id)&&n.push(o);let r=0;for(let o of n){let s=await this.file(o).catch(()=>"retry");if(s==="retry"){let i=(this.retry.get(o.id)?.left??zp)-1;i>0?this.retry.set(o.id,{event:o,left:i}):(this.retry.delete(o.id),this.deps.log?.(`[app] callback reply ${o.ref} from ${o.node} could not be read; it stays in the agent's session`))}else this.retry.delete(o.id),s==="filed"&&r++}return r}finally{this.running=!1}}warnIfSkipped(e,a){let n=this.deps.warn??this.deps.log,r=this.cursor?`after event ${this.cursor}`:"on the first read";a&&n?.(`[app] warning: callback event cursor ${this.cursor} is no longer in the daemon's event ring; replies published before the oldest kept event were skipped`),e>=Ca&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Ca}); older replies ${r} may have been skipped`)}async file(e){let a=this.deps.store();if(!a)return"retry";let n=await this.deps.nodeUrl(e.node);if(!n)return"retry";let r=await this.deps.fetchReply(n,e.ref);if(!r||r.taskId!==e.ref||r.channel!=="app"||!r.chatId.startsWith("app:"))return"skip";let o=r.chatId.slice(4),s=a.ownerOf(o);if(!s)return"skip";let i=a.get(s,o);if(!i)return"skip";let l=await this.deps.conversationUrl(i);if(!l||Vs(l)!==Vs(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=qp(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&Et(h)&&this.deps.notifyFinish(Tt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function qp(t,e){let a=t.plain?{text:Ze(t.text,!1),artifacts:[]}:Qe(t.text,le.perMessage,!1),{cleanText:n,ui:r}=tt(a.text),o=t.plain?void 0:ma(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Fp(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Fp(t){return t.replace(/\s+/g," ").trim().slice(0,300)}function mv(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let h of a)try{s.set(h.id,tu(h,t))}catch(w){console.error(` Board "${h.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Je(process.cwd(),t.workflows.dir):void 0,c=new Ba(l?{baseDir:l}:void 0),p=new za(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new qa(l?{baseDir:l}:void 0);Yr(t),ln({business:t.business?.enabled===!0});let m=Up(async(h,w)=>{try{await Yp(h,w,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){y(w,500,{error:_.message||"internal error"})}});vu(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
18561
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ie.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),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 Zs(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}:{},...t.color?{color:t.color}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function Up(t){let e=o=>{if(o)try{return JSON.parse(o)}catch{return}},a=e(t.ui),n=e(t.tools),r=e(t.files);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}:{},...r?{files:r}:{}}}function Wp(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Gp=4e3,Ca=100,Xp=15,ei=t=>t.replace(/\/+$/,""),Rt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Gp){this.timer||(this.timer=setInterval(()=>{this.tick()},e),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async tick(){if(this.running)return 0;this.running=!0;try{let e,a=!1;try{let o=await this.deps.recent(this.cursor,Ca);e=Array.isArray(o)?o:o.events,a=!Array.isArray(o)&&o.gap===!0}catch{return 0}this.warnIfSkipped(e.length,a),e.length&&(this.cursor=e[e.length-1].id);let n=[...this.retry.values()].map(o=>o.event);for(let o of e)o.kind==="delegation"&&o.type==="reply"&&typeof o.ref=="string"&&o.ref&&!this.retry.has(o.id)&&n.push(o);let r=0;for(let o of n){let s=await this.file(o).catch(()=>"retry");if(s==="retry"){let i=(this.retry.get(o.id)?.left??Xp)-1;i>0?this.retry.set(o.id,{event:o,left:i}):(this.retry.delete(o.id),this.deps.log?.(`[app] callback reply ${o.ref} from ${o.node} could not be read; it stays in the agent's session`))}else this.retry.delete(o.id),s==="filed"&&r++}return r}finally{this.running=!1}}warnIfSkipped(e,a){let n=this.deps.warn??this.deps.log,r=this.cursor?`after event ${this.cursor}`:"on the first read";a&&n?.(`[app] warning: callback event cursor ${this.cursor} is no longer in the daemon's event ring; replies published before the oldest kept event were skipped`),e>=Ca&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Ca}); older replies ${r} may have been skipped`)}async file(e){let a=this.deps.store();if(!a)return"retry";let n=await this.deps.nodeUrl(e.node);if(!n)return"retry";let r=await this.deps.fetchReply(n,e.ref);if(!r||r.taskId!==e.ref||r.channel!=="app"||!r.chatId.startsWith("app:"))return"skip";let o=r.chatId.slice(4),s=a.ownerOf(o);if(!s)return"skip";let i=a.get(s,o);if(!i)return"skip";let l=await this.deps.conversationUrl(i);if(!l||ei(l)!==ei(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=Kp(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&Et(h)&&this.deps.notifyFinish(Tt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Kp(t,e){let a=t.plain?{text:Ze(t.text,!1),artifacts:[]}:Qe(t.text,le.perMessage,!1),{cleanText:n,ui:r}=tt(a.text),o=t.plain?void 0:ma(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Jp(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Jp(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Da();function wv(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let h of a)try{s.set(h.id,iu(h,t))}catch(w){console.error(` Board "${h.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Je(process.cwd(),t.workflows.dir):void 0,c=new Fa(l?{baseDir:l}:void 0),p=new Ua(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new Wa(l?{baseDir:l}:void 0);to(t),dn({business:t.business?.enabled===!0});let m=Vp(async(h,w)=>{try{await nu(h,w,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){y(w,500,{error:_.message||"internal error"})}});Su(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
18545
18562
  Live dashboard: http://${h}:${n}
18546
18563
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
18547
18564
  Kanban dashboard: http://${h}:${n}
18548
- `),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 Vp=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 Yp(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(on(t.headers)==="foreign"&&sn(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Xs(t,e,r,o,{nodeName:a.config.node?.name,fleet:ai(a.config),push:ti(a.config),announce:Do(a.config),chat:ni(a.config),voice:bu(a.config),camera:yu(a.config)}))return;if(o==="GET"&&Vp.has(r)&&On("page",r),o==="GET"&&r==="/"){let d=In();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ca({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_o({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ca({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await be(a.config);if(!d){y(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let k="";t.on("data",b=>k+=b),t.on("end",()=>v(k)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await be(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await xe(t):void 0,v=x?.node??f,k=v?d.find(I=>I.url===v):d[0];if(!k){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",S=await fetch(k.url+r+b,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,S.status,await S.json().catch(()=>({error:`HTTP ${S.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await xe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await be(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gn({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wn({peers:H(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(zn({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,f=setTimeout(()=>d.abort(),8e3);try{let x=Ga(await be(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await Wa(t)):void 0,S=await fetch(v.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,S.status,await S.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(bo({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(So({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Eo({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(To({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Cn({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ao({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:H(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(Co({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Mn(t,e);return}if(o==="POST"&&r==="/api/setup"){await Rn(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ln(t,e);return}if(o==="GET"&&r==="/admin"){nr(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){br(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){dr(t,e,H(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}Tr(t,e,H(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Tu(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await ia(t,e,r,x=>oi(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),v=x.indexOf("::");if(v>0){let k=x.slice(0,v),b=x.slice(v+2),S=a.config.node?.id||a.config.node?.name||"local";if(k===S)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(I){let C=Ve(I.url.replace(/\/+$/,""),a.config);if(C){await Qs(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let f=Ve(d,a.config);if(!f){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Qs(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ar(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Au(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-7K3NRBNN.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rr({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Mr(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lr({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({peers:H(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 ru(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 Qr(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ia(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await eo(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){no(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ne,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await rr(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,dn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await yr(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await pr(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await ro(t,e,r);return}if(r.startsWith("/api/admin/")){await or(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(Xn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let f=Su("web/"+d);try{let x=await Eu(f),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ne(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await Ne(a.config,{date:d,timezone:f});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(f,x,v,k)=>{let b=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(k,b)):x};try{let f=await be(a.config);y(e,200,await yo(f,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,v,k,b)=>{let S=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(S)?Math.max(k,Math.min(b,S)):v};try{let x=await be(a.config);y(e,200,await ko(x,{day:d,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,k]=[f.get("kind"),f.get("key")];if(!v||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await wo(e,await be(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){pu(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!f||!x||!v){y(e,400,{error:"node, agent, task query params required"});return}await uu(t,e,a,f,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await hu(e,a,f,x,v,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!f||!x||v!=="cancel"&&v!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await gu(t,e,a,f,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await La(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await xe(t);try{let f=await ku(a.config,d);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!mu(t,e,[`agent:${d}`]))return;await fu(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ne,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await ou(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await La(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(S=>({name:S.name,url:S.url,token:S.token}))],v={flag:!1},k=[];t.on("close",()=>{v.flag=!0;for(let S of k)try{S.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
18565
+ `),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 au=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 nu(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ln(t.headers)==="foreign"&&cn(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Ys(t,e,r,o,{nodeName:a.config.node?.name,fleet:si(a.config),push:oi(a.config),announce:qo(a.config),chat:ii(a.config),voice:Eu(a.config),camera:Tu(a.config)}))return;if(o==="GET"&&au.has(r)&&Bn("page",r),o==="GET"&&r==="/"){let d=Rn();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ca({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ao({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ca({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await be(a.config);if(!d){y(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let k="";t.on("data",b=>k+=b),t.on("end",()=>v(k)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await be(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await xe(t):void 0,v=x?.node??f,k=v?d.find(I=>I.url===v):d[0];if(!k){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",S=await fetch(k.url+r+b,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,S.status,await S.json().catch(()=>({error:`HTTP ${S.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await xe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await be(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vn({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Jn({peers:H(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(Wn({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,f=setTimeout(()=>d.abort(),8e3);try{let x=Ka(await be(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await Xa(t)):void 0,S=await fetch(v.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,S.status,await S.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_o({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Co({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Io({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mo({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mn({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ro({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:H(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(Lo({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Ln(t,e);return}if(o==="POST"&&r==="/api/setup"){await $n(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Pn(t,e);return}if(o==="GET"&&r==="/admin"){ir(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){_r(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){fr(t,e,H(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}Mr(t,e,H(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Lu(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await ia(t,e,r,x=>ci(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),v=x.indexOf("::");if(v>0){let k=x.slice(0,v),b=x.slice(v+2),S=a.config.node?.id||a.config.node?.name||"local";if(k===S)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(I){let C=Ve(I.url.replace(/\/+$/,""),a.config);if(C){await ai(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let f=Ve(d,a.config);if(!f){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await ai(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Rr(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await $u(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-6EWW7NC2.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(jr({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Pr(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Or({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nr({peers:H(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 du(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 ao(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ia(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ro(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){io(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ne,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await lr(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,un()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Sr(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await hr(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await lo(t,e,r);return}if(r.startsWith("/api/admin/")){await cr(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(Yn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let f=Mu("web/"+d);try{let x=await Ru(f),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ne(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await Ne(a.config,{date:d,timezone:f});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(f,x,v,k)=>{let b=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(k,b)):x};try{let f=await be(a.config);y(e,200,await So(f,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,v,k,b)=>{let S=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(S)?Math.max(k,Math.min(b,S)):v};try{let x=await be(a.config);y(e,200,await To(x,{day:d,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,k]=[f.get("kind"),f.get("key")];if(!v||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await Eo(e,await be(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){xu(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!f||!x||!v){y(e,400,{error:"node, agent, task query params required"});return}await vu(t,e,a,f,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await wu(e,a,f,x,v,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!f||!x||v!=="cancel"&&v!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await ku(t,e,a,f,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await La(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await xe(t);try{let f=await Cu(a.config,d);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!bu(t,e,[`agent:${d}`]))return;await yu(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ne,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await pu(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await La(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(S=>({name:S.name,url:S.url,token:S.token}))],v={flag:!1},k=[];t.on("close",()=>{v.flag=!0;for(let S of k)try{S.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
18549
18566
 
18550
18567
  `)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let S of x)(async()=>{let I={Accept:"text/event-stream"};S.token&&(I.Authorization=`Bearer ${S.token}`);let C=new AbortController;k.push(C);try{let T=await fetch(`${S.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:I,signal:C.signal});if(!T.ok||!T.body)return;let M=T.body.getReader(),P=new TextDecoder,j="";for(;!v.flag;){let{done:B,value:se}=await M.read();if(B)break;j+=P.decode(se,{stream:!0});let q;for(;(q=j.indexOf(`
18551
18568
 
18552
18569
  `))>=0;){let te=j.slice(0,q);if(j=j.slice(q+2),v.flag)break;try{e.write(te+`
18553
18570
 
18554
- `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:f,workflowId:x}),b=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,S=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(P=>({url:P.url,token:P.token}))],I=await Promise.all(S.map(async P=>{let j={};P.token&&(j.Authorization=`Bearer ${P.token}`);try{let B=new AbortController,se=setTimeout(()=>B.abort(),5e3);try{let q=await fetch(`${P.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:j,signal:B.signal});if(!q.ok)return[];let te=await q.json();return Array.isArray(te.runs)?te.runs:[]}finally{clearTimeout(se)}}catch{return[]}})),C=new Map;for(let P of k)C.set(P.id,P);for(let P of I)for(let j of P)C.set(j.id,j);let T=Array.from(C.values()).sort((P,j)=>P.updatedAt<j.updatedAt?1:-1).slice(0,f),M=v?T.map(P=>eu(P)):T;y(e,200,{runs:M})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let m=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(m){let d=decodeURIComponent(m[1]),f=a.workflowRuns.get(d);if(f){y(e,200,{run:f});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let k={};v.token&&(k.Authorization=`Bearer ${v.token}`);let b=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(b.ok){y(e,200,await b.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${f}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,v)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await xe(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Mo(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,x,v)=>{if(a.token)return!0;let k=zt(f);if(!k)return!0;let b=new ne().verify(k);if(!b)return y(x,401,{error:"invalid or revoked token"}),!1;for(let S of v)if(!ye(b,S))return y(x,403,{error:`token missing scope: ${S}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let d=a.sources.get(w[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,d,f]=E,x=decodeURIComponent(f),v=a.boards.find(C=>C.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let b=await xe(t),S=v.columns.find(C=>C.id===b.to),I=v.columns.find(C=>C.id===b.from);if(!S){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await Zp(k,x,I,S),Ia({actor:Ma(t),action:"move",boardId:d,itemId:x,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,f]=g,x=f?decodeURIComponent(f):void 0,v=a.boards.find(b=>b.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:b,totals:S}=await Qp(v,k,n.searchParams);y(e,200,{columns:b,totals:S});return}if(o==="GET"&&x){try{let b=typeof k.getItem=="function"?await k.getItem(x):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&x){let b=await xe(t);try{let S=typeof k.updateItem=="function"?await k.updateItem(x,b):null;if(!S){y(e,501,{error:"update unsupported"});return}Ia({actor:Ma(t),action:"update",boardId:d,itemId:x,payload:b}),y(e,200,S)}catch(S){y(e,502,{error:S.message})}return}if(o==="POST"&&!x){let b=await xe(t);if(!b.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let S=await k.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});Ia({actor:Ma(t),action:"create",boardId:d,itemId:S.id,payload:{title:b.title}}),y(e,201,S)}catch(S){y(e,502,{error:S.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}y(e,404,{error:"not found",path:r})}async function Qp(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let f of t.columns)d[f.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(f=>[f.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),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let d of t.columns)w[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&w[_.id].push({...d,stage:_.id});let E=t.columns.filter(d=>d.kind!=="closed");for(let d of m){let f=ja(d,E);if(!f)continue;let x=w[f];x&&x.push({...d,stage:f})}if(i)for(let d of Object.keys(w))w[d]=w[d].filter(f=>f.assignee===i);for(let d of Object.keys(w))w[d].sort((f,x)=>{let v=(f.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(f.updatedAt||"")});let g=Object.fromEntries(Object.entries(w).map(([d,f])=>[d,f.length]));return{columns:w,totals:g}}async function Zp(t,e,a,n){let r=Oa(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 eu(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 tu(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 hn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ia(t){try{let e=Je(process.cwd(),".agentx");Zs(e)||Gp(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
18555
- `;Wp(Je(e,"board-audit.jsonl"),a)}catch{}}function Ma(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var au=2e3;async function nu(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=g=>{let d=new AbortController,f=setTimeout(()=>d.abort(),au),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let k=v.ok?await v.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",x)})},[l,c,p,u,m,h,w,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let E=await c.json();if(o.agents=E.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},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:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));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(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Ja.routines))}if(h&&h.ok){let g=await h.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(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.sessions)&&du(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Lt=null;function ru(t){if(Lt)return Lt;let e=Je(process.cwd(),".agentx/wiki");return Lt=Hn({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Lt}async function Pt(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function ou(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||z(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function be(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=z(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:z(a,l)})}let s=await Pt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:z(a,i.url)});return[...o.values()]}var su=3e3,iu=6e3,lu=5*6e4,Ra=new Map,$t=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=$t.get(a);if(n)return n;let r=(async()=>{let o=await be(t,AbortSignal.timeout(su)),s=await Promise.all(o.map(async i=>{let l=await nu(i.url,i.token,AbortSignal.timeout(iu),e);return e?l:cu(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>$t.delete(a));return $t.set(a,r),r}function cu(t,e,a=Date.now()){if(e.reachable&&!e.error)return Ra.set(t,{node:e,at:a}),e;let n=Ra.get(t);return!n||a-n.at>lu?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function fv(){Ra.clear(),$t.clear()}function du(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 pu(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,c)=>{n||e.write(`event: ${l}
18571
+ `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:f,workflowId:x}),b=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,S=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(P=>({url:P.url,token:P.token}))],I=await Promise.all(S.map(async P=>{let j={};P.token&&(j.Authorization=`Bearer ${P.token}`);try{let B=new AbortController,se=setTimeout(()=>B.abort(),5e3);try{let q=await fetch(`${P.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:j,signal:B.signal});if(!q.ok)return[];let te=await q.json();return Array.isArray(te.runs)?te.runs:[]}finally{clearTimeout(se)}}catch{return[]}})),C=new Map;for(let P of k)C.set(P.id,P);for(let P of I)for(let j of P)C.set(j.id,j);let T=Array.from(C.values()).sort((P,j)=>P.updatedAt<j.updatedAt?1:-1).slice(0,f),M=v?T.map(P=>su(P)):T;y(e,200,{runs:M})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let m=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(m){let d=decodeURIComponent(m[1]),f=a.workflowRuns.get(d);if(f){y(e,200,{run:f});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let k={};v.token&&(k.Authorization=`Bearer ${v.token}`);let b=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(b.ok){y(e,200,await b.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${f}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,v)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await xe(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Po(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,x,v)=>{if(a.token)return!0;let k=zt(f);if(!k)return!0;let b=new ne().verify(k);if(!b)return y(x,401,{error:"invalid or revoked token"}),!1;for(let S of v)if(!ye(b,S))return y(x,403,{error:`token missing scope: ${S}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let d=a.sources.get(w[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,d,f]=E,x=decodeURIComponent(f),v=a.boards.find(C=>C.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let b=await xe(t),S=v.columns.find(C=>C.id===b.to),I=v.columns.find(C=>C.id===b.from);if(!S){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await ou(k,x,I,S),Ia({actor:Ma(t),action:"move",boardId:d,itemId:x,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,f]=g,x=f?decodeURIComponent(f):void 0,v=a.boards.find(b=>b.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:b,totals:S}=await ru(v,k,n.searchParams);y(e,200,{columns:b,totals:S});return}if(o==="GET"&&x){try{let b=typeof k.getItem=="function"?await k.getItem(x):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&x){let b=await xe(t);try{let S=typeof k.updateItem=="function"?await k.updateItem(x,b):null;if(!S){y(e,501,{error:"update unsupported"});return}Ia({actor:Ma(t),action:"update",boardId:d,itemId:x,payload:b}),y(e,200,S)}catch(S){y(e,502,{error:S.message})}return}if(o==="POST"&&!x){let b=await xe(t);if(!b.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let S=await k.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});Ia({actor:Ma(t),action:"create",boardId:d,itemId:S.id,payload:{title:b.title}}),y(e,201,S)}catch(S){y(e,502,{error:S.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}y(e,404,{error:"not found",path:r})}async function ru(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let f of t.columns)d[f.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(f=>[f.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),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let d of t.columns)w[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&w[_.id].push({...d,stage:_.id});let E=t.columns.filter(d=>d.kind!=="closed");for(let d of m){let f=ja(d,E);if(!f)continue;let x=w[f];x&&x.push({...d,stage:f})}if(i)for(let d of Object.keys(w))w[d]=w[d].filter(f=>f.assignee===i);for(let d of Object.keys(w))w[d].sort((f,x)=>{let v=(f.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(f.updatedAt||"")});let g=Object.fromEntries(Object.entries(w).map(([d,f])=>[d,f.length]));return{columns:w,totals:g}}async function ou(t,e,a,n){let r=Oa(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 su(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 iu(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 xn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ia(t){try{let e=Je(process.cwd(),".agentx");ni(e)||Qp(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
18572
+ `;Yp(Je(e,"board-audit.jsonl"),a)}catch{}}function Ma(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var lu=2e3;async function cu(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=g=>{let d=new AbortController,f=setTimeout(()=>d.abort(),lu),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let k=v.ok?await v.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",x)})},[l,c,p,u,m,h,w,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let E=await c.json();if(o.agents=E.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},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:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));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(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Ya.routines))}if(h&&h.ok){let g=await h.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(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.sessions)&&gu(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Lt=null;function du(t){if(Lt)return Lt;let e=Je(process.cwd(),".agentx/wiki");return Lt=Fn({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Lt}async function Pt(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function pu(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||z(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function be(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=z(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:z(a,l)})}let s=await Pt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:z(a,i.url)});return[...o.values()]}var uu=3e3,mu=6e3,fu=5*6e4,Ra=new Map,$t=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=$t.get(a);if(n)return n;let r=(async()=>{let o=await be(t,AbortSignal.timeout(uu)),s=await Promise.all(o.map(async i=>{let l=await cu(i.url,i.token,AbortSignal.timeout(mu),e);return e?l:hu(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>$t.delete(a));return $t.set(a,r),r}function hu(t,e,a=Date.now()){if(e.reachable&&!e.error)return Ra.set(t,{node:e,at:a}),e;let n=Ra.get(t);return!n||a-n.at>fu?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function kv(){Ra.clear(),$t.clear()}function gu(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 xu(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,c)=>{n||e.write(`event: ${l}
18556
18573
  data: ${JSON.stringify(c)}
18557
18574
 
18558
- `)},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 uu(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await Pt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of w)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:_}=await m.read();if(_)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function mu(t,e,a){let n=zt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ne().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ye(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function fu(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await xe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=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 c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function hu(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await Pt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of u)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.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:c}),m=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function gu(t,e,a,n,r,o){await La(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function La(t,e,a,n,r){let o={};try{o=await xe(t)??{}}catch{}let s=await ei(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function ei(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await Pt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=z(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function ti(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=Za(e.keysFile);return{store:()=>{let r=Me();return r?new kn(r):null},publicKey:()=>en(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function ai(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 ei(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=at({root:process.cwd()}).items.map(Ys)}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=Ve(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 c=await l.json();s.items=(c.items??[]).map(Ys)}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 c=we(),p=await nt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=Ve(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=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:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}function ni(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=z(t.dashboard,e),n=ai(t);return{store:()=>{let r=Me();return r?new Ke(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),tokenFor:r=>z(t.dashboard,r.replace(/\/+$/,"")),...xu(t,e,a)}}function xu(t,e,a){let n=ti(t);return{finishAlerts:r=>{let o=n.store();return!!o&&o.chatFinishOn(r)&&o.list(r).length>0},notifyFinish:async r=>{try{let o=await fetch(e+"/channel/send",{method:"POST",headers:{"Content-Type":"application/json",...a?{Authorization:`Bearer ${a}`}:{}},body:JSON.stringify({channel:"push",chatId:r.deviceId,text:`${r.title}
18559
- ${r.body}`,buttons:[{label:"Open",url:r.url}]}),signal:AbortSignal.timeout(1e4)});o.ok||console.error(`[app] finish notification not sent: HTTP ${o.status} ${(await o.text()).slice(0,160)}`)}catch(o){console.error(`[app] finish notification not sent: ${o?.message||o}`)}}}}function vu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>z(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=ni(t);return new Rt({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await Ne(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:Xo(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function bu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Me();return a?new Ke(a):null},daemon:{url:e,token:z(t.dashboard,e)}}}function yu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:z(t.dashboard,e)},nodeName:t.node.name}}function Ys(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 wu=`
18575
+ `)},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 vu(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await Pt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of w)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:_}=await m.read();if(_)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function bu(t,e,a){let n=zt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ne().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ye(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function yu(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await xe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=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 c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function wu(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await Pt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of u)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.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:c}),m=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function ku(t,e,a,n,r,o){await La(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function La(t,e,a,n,r){let o={};try{o=await xe(t)??{}}catch{}let s=await ri(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function ri(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await Pt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=z(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function oi(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=tn(e.keysFile);return{store:()=>{let r=Me();return r?new Sn(r):null},publicKey:()=>an(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function si(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 ri(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=at({root:process.cwd()}).items.map(ti)}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=Ve(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 c=await l.json();s.items=(c.items??[]).map(ti)}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 c=we(),p=await nt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=Ve(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=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:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}function ii(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=z(t.dashboard,e),n=si(t);return{store:()=>{let r=Me();return r?new Ke(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:Ha(process.cwd())??void 0},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),tokenFor:r=>z(t.dashboard,r.replace(/\/+$/,"")),..._u(t,e,a)}}function _u(t,e,a){let n=oi(t);return{finishAlerts:r=>{let o=n.store();return!!o&&o.chatFinishOn(r)&&o.list(r).length>0},notifyFinish:async r=>{try{let o=await fetch(e+"/channel/send",{method:"POST",headers:{"Content-Type":"application/json",...a?{Authorization:`Bearer ${a}`}:{}},body:JSON.stringify({channel:"push",chatId:r.deviceId,text:`${r.title}
18576
+ ${r.body}`,buttons:[{label:"Open",url:r.url}]}),signal:AbortSignal.timeout(1e4)});o.ok||console.error(`[app] finish notification not sent: HTTP ${o.status} ${(await o.text()).slice(0,160)}`)}catch(o){console.error(`[app] finish notification not sent: ${o?.message||o}`)}}}}function Su(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>z(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=ii(t);return new Rt({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await Ne(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:Yo(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Eu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Me();return a?new Ke(a):null},daemon:{url:e,token:z(t.dashboard,e)}}}function Tu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:z(t.dashboard,e)},nodeName:t.node.name}}function ti(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 Au=`
18560
18577
  You are helping draft a new GitLab issue. Follow these conventions strictly.
18561
18578
 
18562
18579
  Title pattern:
@@ -18588,10 +18605,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
18588
18605
  Shape:
18589
18606
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
18590
18607
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
18591
- `;async function ku(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):
18608
+ `;async function Cu(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):
18592
18609
  - ${r.knownLabels.slice(0,60).join(`
18593
18610
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
18594
- `),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:wu}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),u=_u(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:m,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function _u(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 Su(t){let e=Jp(Kp(import.meta.url));return Je(e,t)}async function Eu(t){return Xp(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function xe(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 ri(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(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:ri(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 Tu(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await yt(await oi(r,a.config)))}async function oi(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=sa(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=Ve(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.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:c.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 Vr(n)}async function Au(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||"",m=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(w=>Zs(w));if(!h){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:m}));return}r="tail",o=["-F","-n","200",h]}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}
18611
+ `),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:Au}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),u=Iu(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:m,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function Iu(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 Mu(t){let e=tu(eu(import.meta.url));return Je(e,t)}async function Ru(t){return Zp(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function xe(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 li(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(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:li(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 Lu(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await yt(await ci(r,a.config)))}async function ci(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=sa(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=Ve(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.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:c.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 eo(n)}async function $u(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||"",m=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(w=>ni(w));if(!h){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:m}));return}r="tail",o=["-F","-n","200",h]}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}
18595
18612
 
18596
18613
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let m;for(;(m=i.indexOf(`
18597
18614
  `))>=0;){let h=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
@@ -18599,5 +18616,5 @@ data: ${h.replace(/\n/g," ")}
18599
18616
 
18600
18617
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
18601
18618
 
18602
- `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function Qs(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,m)=>{let h=[];t.on("data",w=>h.push(w)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);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}),m=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Ve(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:ri(n),token:n.dashboardToken||n.token}:null}export{du as applyAttachSessions,nu as fetchDaemonAgents,Yp as handleBoardRequest,fv as resetLiveCaches,be as resolveNodeTargets,mv as startBoardDashboard,cu as withLastGood};
18603
- //# sourceMappingURL=board-dashboard-OS5J3F73.js.map
18619
+ `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function ai(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,m)=>{let h=[];t.on("data",w=>h.push(w)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);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}),m=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Ve(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:li(n),token:n.dashboardToken||n.token}:null}export{gu as applyAttachSessions,cu as fetchDaemonAgents,nu as handleBoardRequest,kv as resetLiveCaches,be as resolveNodeTargets,wv as startBoardDashboard,hu as withLastGood};
18620
+ //# sourceMappingURL=board-dashboard-TWEF5XVE.js.map