agentix-cli 0.137.2 → 0.138.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-TOAWET76.js → App-F42CYCKX.js} +2 -2
  2. package/dist/{ChatApp-4DRCRKFS.js → ChatApp-RPMQBKHV.js} +2 -2
  3. package/dist/{absorb-eval-OXNL5QGQ.js → absorb-eval-HRPEHJSO.js} +2 -2
  4. package/dist/{agent-GALMGMNJ.js → agent-L5CJF3GH.js} +2 -2
  5. package/dist/{board-dashboard-2A6VSQ7V.js → board-dashboard-33NGOGWC.js} +440 -285
  6. package/dist/board-dashboard-33NGOGWC.js.map +1 -0
  7. package/dist/{chunk-XZIKAHFU.js → chunk-375MXG3H.js} +2 -2
  8. package/dist/{chunk-5ADXRVYT.js → chunk-4HHHVWDB.js} +5 -5
  9. package/dist/{chunk-Q72TK3DO.js → chunk-5HLD66CW.js} +2 -2
  10. package/dist/{chunk-5RHCM3L7.js → chunk-6AUWEL6V.js} +2 -2
  11. package/dist/{chunk-635B6SXI.js → chunk-6VP2KMUM.js} +2 -2
  12. package/dist/{chunk-WCXXXAHV.js → chunk-7DYVNET6.js} +1 -1
  13. package/dist/chunk-7DYVNET6.js.map +1 -0
  14. package/dist/{chunk-3K3LRLZX.js → chunk-7V73QTQ7.js} +2 -2
  15. package/dist/{chunk-PNITKKDR.js → chunk-7YZL5MUL.js} +9 -9
  16. package/dist/{chunk-PNITKKDR.js.map → chunk-7YZL5MUL.js.map} +1 -1
  17. package/dist/chunk-A5GYG56I.js +2 -0
  18. package/dist/chunk-A5GYG56I.js.map +1 -0
  19. package/dist/{chunk-GIQKQD2B.js → chunk-AGQYUOZY.js} +2 -2
  20. package/dist/{chunk-2JKKGS77.js → chunk-AP4DADXG.js} +2 -2
  21. package/dist/{chunk-DIE6XXJF.js → chunk-CZZJEFUM.js} +2 -2
  22. package/dist/{chunk-23LWLYOK.js → chunk-DBJUGKX2.js} +2 -2
  23. package/dist/{chunk-B6PMIUVV.js → chunk-EGPCEQJN.js} +2 -2
  24. package/dist/{chunk-ZYUVKFX2.js → chunk-GAIXI26T.js} +2 -2
  25. package/dist/{chunk-KHYF6KTY.js → chunk-HJCFLGVT.js} +13 -13
  26. package/dist/chunk-HJCFLGVT.js.map +1 -0
  27. package/dist/{chunk-VDG6Y5L3.js → chunk-HQH44RGL.js} +2 -2
  28. package/dist/chunk-IS2IWRP7.js +4 -0
  29. package/dist/chunk-IS2IWRP7.js.map +1 -0
  30. package/dist/{chunk-BXXP6DTB.js → chunk-JIJDBCV7.js} +2 -2
  31. package/dist/{chunk-Z2QOQBUS.js → chunk-LA6P3TUK.js} +2 -2
  32. package/dist/{chunk-SQ37I2MD.js → chunk-MTDVAO5C.js} +2 -2
  33. package/dist/{chunk-7JUISIE7.js → chunk-QGSUENRK.js} +2 -2
  34. package/dist/{chunk-PNYBZPPB.js → chunk-SK47VJMQ.js} +3 -3
  35. package/dist/{chunk-RWMDDMYX.js → chunk-TFH6S7IT.js} +2 -2
  36. package/dist/{chunk-QY5YUHGW.js → chunk-TVW5ZKJY.js} +2 -2
  37. package/dist/{chunk-RTKSSFX2.js → chunk-UPNKRCFX.js} +7 -7
  38. package/dist/{chunk-IIFHX625.js → chunk-UPQTTOVQ.js} +2 -2
  39. package/dist/{chunk-E3AEOQMK.js → chunk-VVX4RXMV.js} +2 -2
  40. package/dist/{chunk-PLPDG6GE.js → chunk-XBARUCG5.js} +2 -2
  41. package/dist/{chunk-MXDWLBIA.js → chunk-XVYIPVSC.js} +2 -2
  42. package/dist/{chunk-JC5KLH2K.js → chunk-Y7IHOQC7.js} +2 -2
  43. package/dist/cli.js +1 -1
  44. package/dist/cli.js.map +1 -1
  45. package/dist/{client-PWE4BJH4.js → client-EB55Y6EJ.js} +2 -2
  46. package/dist/{config-E53FBZ47.js → config-7DRUA5R3.js} +2 -2
  47. package/dist/{config-mutate-ZEHN6JMZ.js → config-mutate-GGA7VXXH.js} +2 -2
  48. package/dist/config-mutator-POFVILXH.js +2 -0
  49. package/dist/{contributions-CLLCLS3O.js → contributions-TZ26MTML.js} +2 -2
  50. package/dist/{doctor-XKT5FWPO.js → doctor-GTRZ7GWF.js} +2 -2
  51. package/dist/{follow-up-tool-ZFRZUZLI.js → follow-up-tool-PNB7KMCY.js} +2 -2
  52. package/dist/{hub-N5ADP3LO.js → hub-QWJR4E6V.js} +2 -2
  53. package/dist/index.js +1 -1
  54. package/dist/net-family-X2P3OVDP.js +2 -0
  55. package/dist/ntfy-Q4YHFKWW.js +2 -0
  56. package/dist/{program-AMQ7JGHO.js → program-KMUCHLDU.js} +23 -23
  57. package/dist/{program-AMQ7JGHO.js.map → program-KMUCHLDU.js.map} +1 -1
  58. package/dist/{promote-M4UBD2R6.js → promote-HAPXWGYH.js} +2 -2
  59. package/dist/push-PRFZMCIK.js +2 -0
  60. package/dist/push-bridge-276ZLSUT.js +2 -0
  61. package/dist/{query-KMQHF5HW.js → query-ICLOVLZ3.js} +2 -2
  62. package/dist/{query-settings-PENAE4UG.js → query-settings-7AXUOHDL.js} +2 -2
  63. package/dist/{registry-GYKSYSDD.js → registry-IUNSHCOL.js} +2 -2
  64. package/dist/{request-planner-GBX6DHRQ.js → request-planner-TDCLF2CH.js} +2 -2
  65. package/dist/{review-candidates-SYMRJGI2.js → review-candidates-QCBXLWG6.js} +2 -2
  66. package/dist/{routing-S3L44JLL.js → routing-YUP3HHL5.js} +2 -2
  67. package/dist/schedule-tool-3C22NBMN.js +2 -0
  68. package/dist/{scheduler-AW4F5ZKS.js → scheduler-7NK2FH5V.js} +2 -2
  69. package/dist/{seat-QBBNCOFO.js → seat-PTPPQOTP.js} +2 -2
  70. package/dist/{select-ZCFIMYWS.js → select-2XSTWMBR.js} +2 -2
  71. package/dist/{set-enabled-4F27A3U2.js → set-enabled-SS5Q3OX7.js} +2 -2
  72. package/dist/{tool-M462KSMF.js → tool-QCMSXEDB.js} +2 -2
  73. package/dist/{tool-G6XTO24J.js → tool-RK4LDFFH.js} +2 -2
  74. package/dist/{wiki-JXVHIEZI.js → wiki-Q2E44YAE.js} +2 -2
  75. package/dist/wiki-enrich-6ULCDOTX.js +2 -0
  76. package/package.json +1 -1
  77. package/dist/board-dashboard-2A6VSQ7V.js.map +0 -1
  78. package/dist/chunk-GFKLKPPY.js +0 -4
  79. package/dist/chunk-GFKLKPPY.js.map +0 -1
  80. package/dist/chunk-KHYF6KTY.js.map +0 -1
  81. package/dist/chunk-PBP3D2BM.js +0 -2
  82. package/dist/chunk-PBP3D2BM.js.map +0 -1
  83. package/dist/chunk-WCXXXAHV.js.map +0 -1
  84. package/dist/config-mutator-AK775RTM.js +0 -2
  85. package/dist/net-family-OFHIZDHS.js +0 -2
  86. package/dist/ntfy-W56TUC5C.js +0 -2
  87. package/dist/push-B2GNI3VQ.js +0 -2
  88. package/dist/push-bridge-F4PCXWJF.js +0 -2
  89. package/dist/schedule-tool-FXUFRZHR.js +0 -2
  90. package/dist/wiki-enrich-6776OMUB.js +0 -2
  91. /package/dist/{App-TOAWET76.js.map → App-F42CYCKX.js.map} +0 -0
  92. /package/dist/{ChatApp-4DRCRKFS.js.map → ChatApp-RPMQBKHV.js.map} +0 -0
  93. /package/dist/{absorb-eval-OXNL5QGQ.js.map → absorb-eval-HRPEHJSO.js.map} +0 -0
  94. /package/dist/{agent-GALMGMNJ.js.map → agent-L5CJF3GH.js.map} +0 -0
  95. /package/dist/{chunk-XZIKAHFU.js.map → chunk-375MXG3H.js.map} +0 -0
  96. /package/dist/{chunk-5ADXRVYT.js.map → chunk-4HHHVWDB.js.map} +0 -0
  97. /package/dist/{chunk-Q72TK3DO.js.map → chunk-5HLD66CW.js.map} +0 -0
  98. /package/dist/{chunk-5RHCM3L7.js.map → chunk-6AUWEL6V.js.map} +0 -0
  99. /package/dist/{chunk-635B6SXI.js.map → chunk-6VP2KMUM.js.map} +0 -0
  100. /package/dist/{chunk-3K3LRLZX.js.map → chunk-7V73QTQ7.js.map} +0 -0
  101. /package/dist/{chunk-GIQKQD2B.js.map → chunk-AGQYUOZY.js.map} +0 -0
  102. /package/dist/{chunk-2JKKGS77.js.map → chunk-AP4DADXG.js.map} +0 -0
  103. /package/dist/{chunk-DIE6XXJF.js.map → chunk-CZZJEFUM.js.map} +0 -0
  104. /package/dist/{chunk-23LWLYOK.js.map → chunk-DBJUGKX2.js.map} +0 -0
  105. /package/dist/{chunk-B6PMIUVV.js.map → chunk-EGPCEQJN.js.map} +0 -0
  106. /package/dist/{chunk-ZYUVKFX2.js.map → chunk-GAIXI26T.js.map} +0 -0
  107. /package/dist/{chunk-VDG6Y5L3.js.map → chunk-HQH44RGL.js.map} +0 -0
  108. /package/dist/{chunk-BXXP6DTB.js.map → chunk-JIJDBCV7.js.map} +0 -0
  109. /package/dist/{chunk-Z2QOQBUS.js.map → chunk-LA6P3TUK.js.map} +0 -0
  110. /package/dist/{chunk-SQ37I2MD.js.map → chunk-MTDVAO5C.js.map} +0 -0
  111. /package/dist/{chunk-7JUISIE7.js.map → chunk-QGSUENRK.js.map} +0 -0
  112. /package/dist/{chunk-PNYBZPPB.js.map → chunk-SK47VJMQ.js.map} +0 -0
  113. /package/dist/{chunk-RWMDDMYX.js.map → chunk-TFH6S7IT.js.map} +0 -0
  114. /package/dist/{chunk-QY5YUHGW.js.map → chunk-TVW5ZKJY.js.map} +0 -0
  115. /package/dist/{chunk-RTKSSFX2.js.map → chunk-UPNKRCFX.js.map} +0 -0
  116. /package/dist/{chunk-IIFHX625.js.map → chunk-UPQTTOVQ.js.map} +0 -0
  117. /package/dist/{chunk-E3AEOQMK.js.map → chunk-VVX4RXMV.js.map} +0 -0
  118. /package/dist/{chunk-PLPDG6GE.js.map → chunk-XBARUCG5.js.map} +0 -0
  119. /package/dist/{chunk-MXDWLBIA.js.map → chunk-XVYIPVSC.js.map} +0 -0
  120. /package/dist/{chunk-JC5KLH2K.js.map → chunk-Y7IHOQC7.js.map} +0 -0
  121. /package/dist/{client-PWE4BJH4.js.map → client-EB55Y6EJ.js.map} +0 -0
  122. /package/dist/{config-E53FBZ47.js.map → config-7DRUA5R3.js.map} +0 -0
  123. /package/dist/{config-mutate-ZEHN6JMZ.js.map → config-mutate-GGA7VXXH.js.map} +0 -0
  124. /package/dist/{config-mutator-AK775RTM.js.map → config-mutator-POFVILXH.js.map} +0 -0
  125. /package/dist/{contributions-CLLCLS3O.js.map → contributions-TZ26MTML.js.map} +0 -0
  126. /package/dist/{doctor-XKT5FWPO.js.map → doctor-GTRZ7GWF.js.map} +0 -0
  127. /package/dist/{follow-up-tool-ZFRZUZLI.js.map → follow-up-tool-PNB7KMCY.js.map} +0 -0
  128. /package/dist/{hub-N5ADP3LO.js.map → hub-QWJR4E6V.js.map} +0 -0
  129. /package/dist/{net-family-OFHIZDHS.js.map → net-family-X2P3OVDP.js.map} +0 -0
  130. /package/dist/{ntfy-W56TUC5C.js.map → ntfy-Q4YHFKWW.js.map} +0 -0
  131. /package/dist/{promote-M4UBD2R6.js.map → promote-HAPXWGYH.js.map} +0 -0
  132. /package/dist/{push-B2GNI3VQ.js.map → push-PRFZMCIK.js.map} +0 -0
  133. /package/dist/{push-bridge-F4PCXWJF.js.map → push-bridge-276ZLSUT.js.map} +0 -0
  134. /package/dist/{query-KMQHF5HW.js.map → query-ICLOVLZ3.js.map} +0 -0
  135. /package/dist/{query-settings-PENAE4UG.js.map → query-settings-7AXUOHDL.js.map} +0 -0
  136. /package/dist/{registry-GYKSYSDD.js.map → registry-IUNSHCOL.js.map} +0 -0
  137. /package/dist/{request-planner-GBX6DHRQ.js.map → request-planner-TDCLF2CH.js.map} +0 -0
  138. /package/dist/{review-candidates-SYMRJGI2.js.map → review-candidates-QCBXLWG6.js.map} +0 -0
  139. /package/dist/{routing-S3L44JLL.js.map → routing-YUP3HHL5.js.map} +0 -0
  140. /package/dist/{schedule-tool-FXUFRZHR.js.map → schedule-tool-3C22NBMN.js.map} +0 -0
  141. /package/dist/{scheduler-AW4F5ZKS.js.map → scheduler-7NK2FH5V.js.map} +0 -0
  142. /package/dist/{seat-QBBNCOFO.js.map → seat-PTPPQOTP.js.map} +0 -0
  143. /package/dist/{select-ZCFIMYWS.js.map → select-2XSTWMBR.js.map} +0 -0
  144. /package/dist/{set-enabled-4F27A3U2.js.map → set-enabled-SS5Q3OX7.js.map} +0 -0
  145. /package/dist/{tool-M462KSMF.js.map → tool-QCMSXEDB.js.map} +0 -0
  146. /package/dist/{tool-G6XTO24J.js.map → tool-RK4LDFFH.js.map} +0 -0
  147. /package/dist/{wiki-JXVHIEZI.js.map → wiki-Q2E44YAE.js.map} +0 -0
  148. /package/dist/{wiki-enrich-6776OMUB.js.map → wiki-enrich-6ULCDOTX.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{C as Ot,D as ro,E as oo,F as so,H as io,I as lo,a as qr,b as zr,c as Fr,d as Ur,e as Ae,f as Wr,g as Gr,h as jt,j as Xr,p as Kr,q as Jr,r as Vr,s as Yr,t as Qr,x as Zr,y as eo}from"./chunk-QY5YUHGW.js";import"./chunk-H4NSB54D.js";import"./chunk-MTX4UPNB.js";import{a as to}from"./chunk-5NTWGUSJ.js";import{a as ao,b as no}from"./chunk-NZQBS7GN.js";import"./chunk-QAWKN2N4.js";import{a as Br}from"./chunk-BKHIR2YJ.js";import{a as qe,b as z,c as I,h as pe,i as Pt,j as se,k as K,l as $t,m as Nr,n as Dr,o as Hr}from"./chunk-B2QYMUTD.js";import{a as C}from"./chunk-GIQKQD2B.js";import{a as Or}from"./chunk-LNY6N73E.js";import{$a as Pr,A as ur,B as St,Ba as Tr,C as mr,Ca as Ar,D as Et,Da as Cr,E as Tt,F as At,G as fr,H as gr,K as xr,L as br,La as Ir,M as vr,Na as Te,Sa as Mr,T as U,U as yr,Ua as Be,V as wr,Va as Ct,Wa as It,Xa as Mt,Ya as Lt,Za as Lr,_a as Rr,a as er,ab as Rt,c as bt,cb as $r,d as _a,e as tr,fb as jr,i as vt,l as Ze,n as ar,z as _t,za as Er}from"./chunk-PNITKKDR.js";import"./chunk-GTJIKXDB.js";import{h as Qn,i as Zn}from"./chunk-Z2QOQBUS.js";import{a as H,b as kr,c as _r,g as Sr}from"./chunk-7LN4VKDU.js";import{a as hr}from"./chunk-IMLAPB7G.js";import{p as nr,t as rr}from"./chunk-S2GAEH2F.js";import"./chunk-AKWBDCMU.js";import{b as G,c as Ee,d as or,e as Sa}from"./chunk-EMGB23H5.js";import{a as ir,b as yt,d as lr,e as dr,f as wt}from"./chunk-WCXXXAHV.js";import{b as sr}from"./chunk-JWDJMFU6.js";import{g as kt}from"./chunk-LQE73AZR.js";import{b as cr,c as pr}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import"./chunk-635B6SXI.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{F as Vn,W as ht,X as gt,Y as xt,Z as ce,_ as Yn,a as Fn,f as Un,g as wa,h as ka,l as Wn,n as Gn,o as Xn,z as Jn}from"./chunk-3K3LRLZX.js";import"./chunk-QSKG754X.js";import"./chunk-MEFPXHQJ.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-5RHCM3L7.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-23LWLYOK.js";import{a as Kn}from"./chunk-BXXP6DTB.js";import"./chunk-3UOTLMXD.js";import"./chunk-PE5V2LI7.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-RWMDDMYX.js";import"./chunk-MXDWLBIA.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import{g as zn}from"./chunk-E3AEOQMK.js";import"./chunk-WPNRDEHW.js";import"./chunk-SQ37I2MD.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-MCI3DIWW.js";import"./chunk-6TURWSMN.js";import"./chunk-QD6IICK7.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import{A as ba,Aa as ft,E as nc,L as Nn,O as va,R as Dn,T as mt,U as Hn,W as Bn,Y as qn,a as Mn,aa as ya,b as Ln,c as ec,sa as X,x as ct,y as tc,z as xa}from"./chunk-KHYF6KTY.js";import{a as Rn,b as pt,c as ga,d as Pn,h as $n}from"./chunk-BRK6M6LA.js";import{d as jn,e as ac,f as ut,n as On}from"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ea(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 co(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ea(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ie={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"/>'},Ce=(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>",Nt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Ce(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function po(t={}){return I({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{C as Ht,D as xo,E as bo,F as vo,H as yo,I as wo,a as Zr,b as eo,c as to,d as ao,e as Ie,f as no,g as ro,h as Dt,j as oo,p as so,q as io,r as lo,s as co,t as po,x as uo,y as mo}from"./chunk-TVW5ZKJY.js";import"./chunk-H4NSB54D.js";import"./chunk-MTX4UPNB.js";import{a as fo}from"./chunk-5NTWGUSJ.js";import{a as ho,b as go}from"./chunk-NZQBS7GN.js";import"./chunk-QAWKN2N4.js";import{a as Qr}from"./chunk-BKHIR2YJ.js";import{a as Ue,b as z,c as I,h as ue,i as Ot,j as se,k as K,l as Nt,m as Jr,n as Vr,o as Yr}from"./chunk-B2QYMUTD.js";import{a as C}from"./chunk-AGQYUOZY.js";import{a as Kr}from"./chunk-LNY6N73E.js";import{$a as Ur,A as _r,Aa as Nr,B as ze,C as Sr,Ca as Dr,D as Ct,Da as Hr,E as It,Ea as Br,F as Mt,G as Er,H as Ar,I as Cr,L as Ir,M as Mr,Ma as qr,N as Rr,Oa as Ce,Ta as zr,U,V as Lr,Va as Fe,W as Pr,Wa as Rt,Xa as Lt,Ya as Pt,Za as $t,_a as Fr,a as dr,ab as Wr,bb as jt,c as _t,d as Ca,db as Gr,e as cr,gb as Xr,i as St,l as at,n as pr,t as kr,z as At}from"./chunk-7YZL5MUL.js";import"./chunk-GTJIKXDB.js";import{h as ir,i as lr}from"./chunk-LA6P3TUK.js";import{a as H,b as $r,c as jr,g as Or}from"./chunk-7LN4VKDU.js";import{a as Tr}from"./chunk-IMLAPB7G.js";import{p as ur,t as mr}from"./chunk-S2GAEH2F.js";import{j as wr}from"./chunk-AKWBDCMU.js";import{b as G,c as Ae,d as fr,e as Ia}from"./chunk-EMGB23H5.js";import{a as gr,b as qe,d as xr,e as br,f as Et}from"./chunk-7DYVNET6.js";import{b as hr}from"./chunk-JWDJMFU6.js";import{g as Tt}from"./chunk-LQE73AZR.js";import{b as vr,c as yr}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import"./chunk-6VP2KMUM.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{F as or,W as yt,X as wt,Y as kt,Z as pe,_ as sr,a as Qn,f as Zn,g as Ta,h as Aa,l as er,n as tr,o as ar,z as rr}from"./chunk-7V73QTQ7.js";import"./chunk-QSKG754X.js";import"./chunk-MEFPXHQJ.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-6AUWEL6V.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-DBJUGKX2.js";import{a as nr}from"./chunk-JIJDBCV7.js";import"./chunk-3UOTLMXD.js";import"./chunk-PE5V2LI7.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-TFH6S7IT.js";import"./chunk-XVYIPVSC.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import{g as Yn}from"./chunk-VVX4RXMV.js";import"./chunk-WPNRDEHW.js";import"./chunk-MTDVAO5C.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-MCI3DIWW.js";import"./chunk-6TURWSMN.js";import"./chunk-QD6IICK7.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import{A as _a,Aa as vt,E as wc,L as Gn,O as Sa,R as Xn,T as bt,U as Kn,W as Jn,Y as Vn,a as Hn,aa as Ea,b as Bn,c as bc,sa as X,x as ht,y as vc,z as ka}from"./chunk-HJCFLGVT.js";import{a as qn,b as gt,c as wa,d as zn,h as Fn}from"./chunk-BRK6M6LA.js";import{d as Un,e as yc,f as xt,n as Wn}from"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ma(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 ko(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ma(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ie={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"/>'},Me=(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>",Bt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Me(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function _o(t={}){return I({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
2
2
 
3
3
  <div class="bf-head">
4
4
  <div>
@@ -7,8 +7,8 @@ import{C as Ot,D as ro,E as oo,F as so,H as io,I as lo,a as qr,b as zr,c as Fr,d
7
7
  </div>
8
8
  <div class="bf-sync">
9
9
  <span class="bf-sync__t" id="synced">Gathering&hellip;</span>
10
- <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${Ce(ie.pulse,13)} Activity</a>
11
- <button class="ax-btn" id="refresh" title="Refresh now">${Ce(ie.refresh)} Refresh</button>
10
+ <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${Me(ie.pulse,13)} Activity</a>
11
+ <button class="ax-btn" id="refresh" title="Refresh now">${Me(ie.refresh)} Refresh</button>
12
12
  </div>
13
13
  </div>
14
14
 
@@ -21,24 +21,24 @@ import{C as Ot,D as ro,E as oo,F as so,H as io,I as lo,a as qr,b as zr,c as Fr,d
21
21
 
22
22
  <div class="bf-grid">
23
23
  <section class="bf-col">
24
- ${Nt(ie.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
24
+ ${Bt(ie.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
25
25
  <div id="you" class="bf-col"></div>
26
26
 
27
- ${Nt(ie.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed &mdash; not yet automatic</span>')}
27
+ ${Bt(ie.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed &mdash; not yet automatic</span>')}
28
28
  <div id="agents" class="bf-col"></div>
29
29
  <button class="ax-btn ax-btn--sm" id="more-actions" hidden></button>
30
30
 
31
31
  <div id="handled"></div>
32
32
  </section>
33
33
  <aside class="bf-col">
34
- ${Nt(ie.pulse,"In motion","run-count")}
34
+ ${Bt(ie.pulse,"In motion","run-count")}
35
35
  <div id="running" class="bf-col"></div>
36
36
  </aside>
37
37
  </div>
38
38
 
39
- ${Nt(ie.file,"Session briefings","brief-count")}
39
+ ${Bt(ie.file,"Session briefings","brief-count")}
40
40
  <div class="bf-toolbar">
41
- <div class="bf-search">${Ce(ie.search)}
41
+ <div class="bf-search">${Me(ie.search)}
42
42
  <input id="search" type="search" placeholder="Search sessions&hellip;" aria-label="Search sessions">
43
43
  </div>
44
44
  <div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
@@ -46,15 +46,15 @@ ${Nt(ie.file,"Session briefings","brief-count")}
46
46
  <div id="reviews" class="bf-col"></div>
47
47
 
48
48
  <section class="ax-panel bf-connect">
49
- <div class="bf-connect__head">${Ce(ie.plug,17)}<h2>Connect a CLI session</h2>
49
+ <div class="bf-connect__head">${Me(ie.plug,17)}<h2>Connect a CLI session</h2>
50
50
  <span class="bf-connect__note">Daemon-owned processes only</span></div>
51
51
  <div class="bf-discover">
52
52
  <div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
53
- <button class="ax-btn" id="discover">${Ce(ie.search)} Discover CLIs</button>
53
+ <button class="ax-btn" id="discover">${Me(ie.search)} Discover CLIs</button>
54
54
  </div>
55
55
  <div class="bf-cli" id="discovered"></div>
56
56
  <details class="bf-manual">
57
- <summary>${Ce(ie.chev,12)} Register manually</summary>
57
+ <summary>${Me(ie.chev,12)} Register manually</summary>
58
58
  <div class="bf-forms">
59
59
  <form id="register" class="bf-form">
60
60
  <div class="ax-sec-label"><h3>Register a session</h3></div>
@@ -85,7 +85,7 @@ ${Nt(ie.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:rc,scripts:`<script>${z({decayOf:Ea,rankByDecay:co})}const ICON = ${JSON.stringify(ie)};${oc}</script>`})}var rc=`
88
+ </div>`,css:kc,scripts:`<script>${z({decayOf:Ma,rankByDecay:ko})}const ICON = ${JSON.stringify(ie)};${_c}</script>`})}var kc=`
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
- }`,oc=String.raw`
364
+ }`,_c=String.raw`
365
365
  (function(){
366
366
  const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
367
367
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -776,22 +776,22 @@ if(document.querySelector('form :focus'))return;
776
776
  if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
777
777
  refresh();
778
778
  },15000);
779
- })();`;function Ta(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),c=r[r.length-1];c&&l.startedAt-c.to<=e?(c.to=Math.max(c.to,d),c.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let c=1;c<r.length;c++){let p=r[c].from-r[c-1].to;p<d&&(d=p,l=c)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function Aa(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 uo(t,e=[],a){let{bands:n,gaps:r}=Ta(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(y=>l.startedAt>=y.from&&l.startedAt<=y.to);if(d===-1)continue;let c=n[d],p=c.to-c.from||1,m=(l.startedAt-c.from)/p*100,g=Math.min(Math.max((l.durationMs||0)/p*100,1.2),100-m),_=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};_.runs.push({...l,band:d,track:0,left:m,width:g,marks:o.get(l.id)??[]}),s.set(l.laneKey,_)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,c)=>Aa(l.runs.filter(p=>p.band===c))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as sc}from"crypto";import{readFileSync as ic,statSync as lc}from"fs";import{resolve as dc,dirname as cc}from"path";import{fileURLToPath as pc}from"url";var mo=new Map;function Dt(t){let e=mo.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=cc(pc(import.meta.url)),r=dc(n,"web",t),o=lc(r),s=o.size<8e6?sc("sha1").update(ic(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return mo.set(t,a),a}var le={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"/>'},Ht=(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>",uc=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],fo={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 ho(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return I({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function Ra(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,d),p.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let p=1;p<r.length;p++){let c=r[p].from-r[p-1].to;c<d&&(d=c,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function La(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 So(t,e=[],a){let{bands:n,gaps:r}=Ra(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(b=>l.startedAt>=b.from&&l.startedAt<=b.to);if(d===-1)continue;let p=n[d],c=p.to-p.from||1,m=(l.startedAt-p.from)/c*100,g=Math.min(Math.max((l.durationMs||0)/c*100,1.2),100-m),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:d,track:0,left:m,width:g,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>La(l.runs.filter(c=>c.band===p))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Sc}from"crypto";import{readFileSync as Ec,statSync as Tc}from"fs";import{resolve as Ac,dirname as Cc}from"path";import{fileURLToPath as Ic}from"url";var Eo=new Map;function qt(t){let e=Eo.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Cc(Ic(import.meta.url)),r=Ac(n,"web",t),o=Tc(r),s=o.size<8e6?Sc("sha1").update(Ec(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Eo.set(t,a),a}var le={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"/>'},zt=(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>",Mc=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],To={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 Ao(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return I({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">${fo[e]}</p>
785
+ <p class="ac-sub" id="sub">${To[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
789
- ${[["timeline","Timeline",le.timeline],["map","Map",le.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${Ht(o,13)}${r}</button>`).join("")}
789
+ ${[["timeline","Timeline",le.timeline],["map","Map",le.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${zt(o,13)}${r}</button>`).join("")}
790
790
  </div>
791
791
  <div class="ac-seg" id="hours" role="radiogroup" aria-label="Window">
792
792
  ${[["6","6h"],["24","24h"],["72","3d"],["168","7d"]].map(([n,r],o)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${o===1}"${o===1?' class="is-on"':""}>${r}</button>`).join("")}
793
793
  </div>
794
- <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${Ht(le.refresh,13)} Refresh</button>
794
+ <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${zt(le.refresh,13)} Refresh</button>
795
795
  </div>
796
796
  </div>
797
797
 
@@ -799,14 +799,14 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${uc.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ht(o,13)}${r}</button>`).join("")}
802
+ ${Mc.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${zt(o,13)}${r}</button>`).join("")}
803
803
  </div>
804
804
  <div class="ac-key">
805
805
  <span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
806
806
  <span class="ac-k"><i class="ac-d ac-d--warning"></i>warning</span>
807
807
  <span class="ac-k"><i class="ac-d ac-d--recommendation"></i>friction</span>
808
808
  <span class="ac-k"><i class="ac-d ac-d--later"></i>do later</span>
809
- <span class="ac-k">${Ht(le.x,11)}canceled</span>
809
+ <span class="ac-k">${zt(le.x,11)}canceled</span>
810
810
  </div>
811
811
  </div>
812
812
 
@@ -816,10 +816,10 @@ refresh();
816
816
  </div>
817
817
 
818
818
  <div id="view-map" class="ac-map"${a?"":" hidden"}>
819
- <div id="ax-fleet-root" data-hours="24" data-src="${Dt("activity-graph.global.js")}"></div>
819
+ <div id="ax-fleet-root" data-hours="24" data-src="${qt("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:mc,scripts:`<script>${z({computeBands:Ta,packTracks:Aa,buildTimeline:uo})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(fo)};${fc}</script>`})}var mc=`
822
+ </div>`,css:Rc,scripts:`<script>${z({computeBands:Ra,packTracks:La,buildTimeline:So})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(To)};${Lc}</script>`})}var Rc=`
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
- `,fc=String.raw`
908
+ `,Lc=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>';
@@ -1024,7 +1024,7 @@ history.replaceState(null,'',u);
1024
1024
  if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
1025
1025
  $('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
1026
1026
  show(view);
1027
- `;function go(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return I({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:hc,scripts:`<script src="${Dt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var hc=`
1027
+ `;function Co(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return I({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Pc,scripts:`<script src="${qt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Pc=`
1028
1028
  /* Preload the fonts the redesign's CSS references. Placed in the shell so
1029
1029
  * they start fetching while the React bundle is still parsing. */
1030
1030
  @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");
@@ -1045,11 +1045,11 @@ body { margin: 0; overflow: hidden; }
1045
1045
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
1046
1046
  text-align: center;
1047
1047
  }
1048
- `;import{createServer as Th}from"http";import{appendFileSync as Ah,existsSync as Wd,mkdirSync as Ch}from"fs";import{readFile as Ih}from"fs/promises";import{fileURLToPath as Mh}from"url";import{dirname as Lh,resolve as it}from"path";Dn();function ze(t,e){if(!t)return"absent";let a=or(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ie=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 Bt(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=xo(t.headers["sec-fetch-mode"]),n.site=xo(t.headers["sec-fetch-site"]),n}function xo(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as bc}from"zlib";var gc=[[[441,393],[600,393],[614,396],[625,401],[634,410],[1028,940],[846,940],[833,937],[823,931],[818,925],[440,414],[435,406],[436,398]],[[893,393],[1079,393],[861,653],[771,535]],[[413,439],[510,574],[282,874],[100,874]],[[451,709],[610,709],[615,712],[698,824],[599,939],[447,719],[446,713]]],ye={x:100,y:393,width:979,height:547},Ca="#1a1a18",Ia="#ffffff",bo=Math.hypot(ye.width,ye.height)/2/ye.width,qt={full:.74,safe:.37/bo,android:.29/bo,mac:.6};function Ma(t,e){let a=t*e/ye.width,n=t/2-(ye.x+ye.width/2)*a,r=t/2-(ye.y+ye.height/2)*a;return gc.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function xc(t,e){let a=n=>String(Math.round(n*100)/100);return Ma(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function vo(t=64,e=qt.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${Ia}"/><path fill="${Ca}" d="${xc(t,e)}"/></svg>`}var vc=Ao(Ca),yo=Ao(Ia),wo=new Map;function Fe(t){let e=wo.get(t);return e||(e=To({size:t,width:qt.safe,background:"square"}),wo.set(t,e)),e}var yc=vo();function Eo(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:yc}:t==="/favicon.ico"?{type:"image/png",body:_o(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:_o(180)}:null}var ko=new Map;function _o(t){let e=ko.get(t);return e||(e=To({size:t,width:qt.full,background:"square"}),ko.set(t,e)),e}function To(t){let{size:e}=t,a=t.background==="mac"?So(e,[wc(e)]):null,n=So(e,Ma(e,t.width)),r=1+e*4,o=Buffer.alloc(r*e);for(let s=0;s<e;s++)for(let i=0;i<e;i++){let l=s*e+i,d=n[l],c=s*r+1+i*4;for(let p=0;p<3;p++)o[c+p]=Math.round(yo[p]+(vc[p]-yo[p])*d);o[c+3]=Math.round(255*(a?a[l]:1))}return kc(e,o)}function wc(t){let e=t/1024,a=100*e,n=924*e,r=185*e,o=[],s=[[n-r,a+r,-90],[n-r,n-r,0],[a+r,n-r,90],[a+r,a+r,180]];for(let[i,l,d]of s)for(let c=0;c<=12;c++){let p=(d+90*c/12)*Math.PI/180;o.push([i+r*Math.cos(p),l+r*Math.sin(p)])}return o}var La=8;function So(t,e){let a=new Float32Array(t*t),n=[];for(let o of e)for(let s=0;s<o.length;s++){let[i,l]=o[s],[d,c]=o[(s+1)%o.length];l!==c&&n.push([i,l,d,c])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<La;s++){let i=o+(s+.5)/La;r.length=0;for(let[l,d,c,p]of n)(i>=d&&i<p||i>=p&&i<d)&&r.push(l+(i-d)*(c-l)/(p-d));r.sort((l,d)=>l-d);for(let l=0;l+1<r.length;l+=2){let d=Math.max(0,r[l]),c=Math.min(t,r[l+1]);for(let p=Math.floor(d);p<c;p++){let m=Math.min(p+1,c)-Math.max(p,d);m>0&&(a[o*t+p]+=m/La)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function Ao(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function kc(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=6,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Ra("IHDR",a),Ra("IDAT",bc(e)),Ra("IEND",Buffer.alloc(0))])}function Ra(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(Sc(n)),Buffer.concat([a,n,r])}var _c=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 Sc(t){let e=4294967295;for(let a of t)e=_c[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}ft();nc();var zt=7,Ec=["waiting_owner","needs_attention"],Tc={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Ue(t,e){let a=t.toLowerCase().split("@")[0],n=Tc[a]??t,r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(r){let o=r[2]==="issue"?"issue":r[2]==="pull"?"pull request":"merge request";return`${n} ${o} #${r[3]} in ${r[1]}`}return n}function Co(t,e,a){let n=t.toLowerCase().split("@")[0],r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(!r)return null;let[,o,s,i]=r;return n==="gitlab"?`${(a.gitlab||"https://gitlab.com").replace(/\/+$/,"")}/${o}/-/${s==="issue"?"issues":"merge_requests"}/${i}`:n==="github"?`${(a.github||"https://github.com").replace(/\/+$/,"")}/${o}/${s==="issue"?"issues":"pull"}/${i}`:null}function Io(t,e,a={}){let n=a.now??Date.now(),s=(t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?t.prepare("PRAGMA table_info(requests)").all():[]).some(y=>y.name==="person"),i=y=>({id:y.id,state:y.state,agentId:y.agent_id,text:y.text,channel:y.channel,chatId:y.chat_id,createdAt:y.created_at,updatedAt:y.updated_at,closedAt:y.closed_at??null,question:y.question??null,attentionReason:y.attention_reason??null,evidence:y.evidence??null,where:{label:Ue(y.channel,y.chat_id),url:a.linkFor?.(y.channel,y.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${xa.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...xa).map(i):[],d=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ba.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1049
- ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...ba,n-zt*864e5).map(i):[],c=[];try{c=jt(t,e,50).filter(y=>y.startedAt>=n-zt*864e5)}catch{}let p=new Map;if(s&&c.length){let y=t.prepare(`SELECT l.ref, r.id, r.state, r.evidence FROM request_links l JOIN requests r ON r.id = l.request_id
1050
- WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${c.map(()=>"?").join(",")})`).all(e,...c.map(S=>S.taskId));for(let S of y)p.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=c.map(y=>({...y,where:y.channel?{label:Ue(y.channel,y.chatId??""),url:a.linkFor?.(y.channel,y.chatId??"")??null}:null,request:p.get(y.taskId)??null})),g=new Set(m.map(y=>y.request?.id).filter(Boolean)),_=[...l.filter(y=>!Ec.includes(y.state)),...d].filter(y=>!g.has(y.id));return{open:l,recent:d,runs:m,other:_}}ya();ac();var Mo={waiting:0,yours:0,ahead:null};function Lo(t,e,a={}){let n=jn(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,d=s.get(l)??0;s.set(l,d+1);let c=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};c.waiting++,i.person===e&&(c.yours++,c.ahead===null&&(c.ahead=d),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Ue(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:d})),r.set(i.agentId,c)}return{byAgent:r,mine:o}}var Ac=4e3;function Ro(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
1048
+ `;import{createServer as Qh}from"http";import{appendFileSync as Zh,existsSync as cc,mkdirSync as eg}from"fs";import{readFile as tg}from"fs/promises";import{fileURLToPath as ag}from"url";import{dirname as ng,resolve as ut}from"path";Xn();function We(t,e){if(!t)return"absent";let a=fr(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Re=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 Ft(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Io(t.headers["sec-fetch-mode"]),n.site=Io(t.headers["sec-fetch-site"]),n}function Io(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Oc}from"zlib";var $c=[[[441,393],[600,393],[614,396],[625,401],[634,410],[1028,940],[846,940],[833,937],[823,931],[818,925],[440,414],[435,406],[436,398]],[[893,393],[1079,393],[861,653],[771,535]],[[413,439],[510,574],[282,874],[100,874]],[[451,709],[610,709],[615,712],[698,824],[599,939],[447,719],[446,713]]],ke={x:100,y:393,width:979,height:547},Pa="#1a1a18",$a="#ffffff",Mo=Math.hypot(ke.width,ke.height)/2/ke.width,Ut={full:.74,safe:.37/Mo,android:.29/Mo,mac:.6};function ja(t,e){let a=t*e/ke.width,n=t/2-(ke.x+ke.width/2)*a,r=t/2-(ke.y+ke.height/2)*a;return $c.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function jc(t,e){let a=n=>String(Math.round(n*100)/100);return ja(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function Ro(t=64,e=Ut.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${$a}"/><path fill="${Pa}" d="${jc(t,e)}"/></svg>`}var Nc=Ho(Pa),Lo=Ho($a),Po=new Map;function Ge(t){let e=Po.get(t);return e||(e=Do({size:t,width:Ut.safe,background:"square"}),Po.set(t,e)),e}var Dc=Ro();function No(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:Dc}:t==="/favicon.ico"?{type:"image/png",body:jo(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:jo(180)}:null}var $o=new Map;function jo(t){let e=$o.get(t);return e||(e=Do({size:t,width:Ut.full,background:"square"}),$o.set(t,e)),e}function Do(t){let{size:e}=t,a=t.background==="mac"?Oo(e,[Hc(e)]):null,n=Oo(e,ja(e,t.width)),r=1+e*4,o=Buffer.alloc(r*e);for(let s=0;s<e;s++)for(let i=0;i<e;i++){let l=s*e+i,d=n[l],p=s*r+1+i*4;for(let c=0;c<3;c++)o[p+c]=Math.round(Lo[c]+(Nc[c]-Lo[c])*d);o[p+3]=Math.round(255*(a?a[l]:1))}return Bc(e,o)}function Hc(t){let e=t/1024,a=100*e,n=924*e,r=185*e,o=[],s=[[n-r,a+r,-90],[n-r,n-r,0],[a+r,n-r,90],[a+r,a+r,180]];for(let[i,l,d]of s)for(let p=0;p<=12;p++){let c=(d+90*p/12)*Math.PI/180;o.push([i+r*Math.cos(c),l+r*Math.sin(c)])}return o}var Oa=8;function Oo(t,e){let a=new Float32Array(t*t),n=[];for(let o of e)for(let s=0;s<o.length;s++){let[i,l]=o[s],[d,p]=o[(s+1)%o.length];l!==p&&n.push([i,l,d,p])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Oa;s++){let i=o+(s+.5)/Oa;r.length=0;for(let[l,d,p,c]of n)(i>=d&&i<c||i>=c&&i<d)&&r.push(l+(i-d)*(p-l)/(c-d));r.sort((l,d)=>l-d);for(let l=0;l+1<r.length;l+=2){let d=Math.max(0,r[l]),p=Math.min(t,r[l+1]);for(let c=Math.floor(d);c<p;c++){let m=Math.min(c+1,p)-Math.max(c,d);m>0&&(a[o*t+c]+=m/Oa)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function Ho(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function Bc(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=6,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Na("IHDR",a),Na("IDAT",Oc(e)),Na("IEND",Buffer.alloc(0))])}function Na(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(zc(n)),Buffer.concat([a,n,r])}var qc=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 zc(t){let e=4294967295;for(let a of t)e=qc[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}vt();wc();var Wt=7,Fc=["waiting_owner","needs_attention"],Uc={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Xe(t,e){let a=t.toLowerCase().split("@")[0],n=Uc[a]??t,r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(r){let o=r[2]==="issue"?"issue":r[2]==="pull"?"pull request":"merge request";return`${n} ${o} #${r[3]} in ${r[1]}`}return n}function Bo(t,e,a){let n=t.toLowerCase().split("@")[0],r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(!r)return null;let[,o,s,i]=r;return n==="gitlab"?`${(a.gitlab||"https://gitlab.com").replace(/\/+$/,"")}/${o}/-/${s==="issue"?"issues":"merge_requests"}/${i}`:n==="github"?`${(a.github||"https://github.com").replace(/\/+$/,"")}/${o}/${s==="issue"?"issues":"pull"}/${i}`:null}function qo(t,e,a={}){let n=a.now??Date.now(),s=(t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?t.prepare("PRAGMA table_info(requests)").all():[]).some(b=>b.name==="person"),i=b=>({id:b.id,state:b.state,agentId:b.agent_id,text:b.text,channel:b.channel,chatId:b.chat_id,createdAt:b.created_at,updatedAt:b.updated_at,closedAt:b.closed_at??null,question:b.question??null,attentionReason:b.attention_reason??null,evidence:b.evidence??null,where:{label:Xe(b.channel,b.chat_id),url:a.linkFor?.(b.channel,b.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ka.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...ka).map(i):[],d=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${_a.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1049
+ ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,..._a,n-Wt*864e5).map(i):[],p=[];try{p=Dt(t,e,50).filter(b=>b.startedAt>=n-Wt*864e5)}catch{}let c=new Map;if(s&&p.length){let b=t.prepare(`SELECT l.ref, r.id, r.state, r.evidence FROM request_links l JOIN requests r ON r.id = l.request_id
1050
+ WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${p.map(()=>"?").join(",")})`).all(e,...p.map(S=>S.taskId));for(let S of b)c.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=p.map(b=>({...b,where:b.channel?{label:Xe(b.channel,b.chatId??""),url:a.linkFor?.(b.channel,b.chatId??"")??null}:null,request:c.get(b.taskId)??null})),g=new Set(m.map(b=>b.request?.id).filter(Boolean)),k=[...l.filter(b=>!Fc.includes(b.state)),...d].filter(b=>!g.has(b.id));return{open:l,recent:d,runs:m,other:k}}Ea();yc();var zo={waiting:0,yours:0,ahead:null};function Fo(t,e,a={}){let n=Un(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,d=s.get(l)??0;s.set(l,d+1);let p=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};p.waiting++,i.person===e&&(p.yours++,p.ahead===null&&(p.ahead=d),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Xe(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:d})),r.set(i.agentId,p)}return{byAgent:r,mine:o}}var Wc=4e3;function Uo(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
1051
1051
  WHERE person = ? AND started_at >= ? AND (channel IS NULL OR channel != 'a2a')
1052
- GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-zt*864e5).map(r=>r.agent_id)}function Po(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(mt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let d=n.queue?.get(l)??Mo,c=s.get(l),p=c??i.get(l);if(!p)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:d};let m=o(p.person??null),g=p.status==="error"||p.status==="timeout",_=c?"working":g&&m==="you"?"blocked":"free",y=m==="you"&&p.channel!=="a2a",S=y&&p.channel;return{agentId:l,state:_,by:m,at:c?p.started_at:p.finished_at??p.started_at,text:c||y?p.message_preview??null:null,fullText:y&&c&&String(p.original_message??p.message_preview??"").slice(0,Ac)||null,where:S?{label:Ue(p.channel,p.chat_id??""),url:n.linkFor?.(p.channel,p.chat_id??"")??null}:null,queue:d}})}function $o(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function jo(t,e){return!t||e-t>=3e4||t>e}function Ft(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 Oo(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"}}function Ut(t,e,a,n){return t?e?{text:"Can't reach the server. "+(n?"Showing what was last loaded. ":"")+"Trying again every "+a+" seconds.",retry:!0}:{text:"Offline. Showing what was last loaded; live state needs a connection.",retry:!1}:null}function Wt(t){return String(t??"").replace(/```[\w-]*|`/g,"").replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^[ \t]*(?:#{1,6}|>+|[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm,"").replace(/\*\*|~~/g,"").replace(/(^|[\s(])\*(\S(?:[^*\n]*\S)?)\*(?=[\s).,;:!?]|$)/gm,"$1$2").replace(/\s+/g," ").trim()}function No(t){let e=t.by==="you"?"you":t.by==="owner"?"the owner":t.by?"someone else":null;if(t.state==="working"){let a=t.queue||{waiting:0,yours:0,ahead:null},n=a.ahead||0,r;return a.yours>0?r=(a.yours===1?"Your message is in line":a.yours+" messages of yours are in line")+(n===0?a.yours===1?": it runs when this ends.":": the first runs when this ends.":", "+n+(n===1?" message":" messages")+" ahead of "+(a.yours===1?"it.":"the first.")):a.waiting>0?r=a.waiting+(a.waiting===1?" message waits":" messages wait")+" in line. A new one from you waits behind "+(a.waiting===1?"it.":"them."):r=t.by==="you"?"Busy. A new message waits in line until this ends.":"A message you send now waits in line until this ends.",t.by==="you"?{label:"Working",tone:"work",what:t.text,by:e,hint:r}:{label:"Working",tone:"work",what:t.text||"Busy with someone else's task",by:e,hint:r}}return t.state==="blocked"?{label:"Blocked",tone:"stuck",what:t.text?"Stopped on: "+t.text:null,by:e,hint:"It stopped before finishing. It needs a person."}:{label:"Free",tone:"free",what:t.by==="you"&&t.text?"Finished: "+t.text:null,by:t.by==="you"?e:null,hint:"Free. Ready for your next message."}}function Do(t){let e=t.request?t.request.state:"";return e==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:e==="needs_attention"?{label:"Stuck",tone:"stuck"}:t.status==="queued"?{label:"In line",tone:"wait"}:t.status==="in-flight"?{label:"Running",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function Ho(t){return t==="in_progress"?{label:"In progress",tone:"work"}:t==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:t==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:t==="needs_attention"?{label:"Stuck",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Declined",tone:"off"}:t==="dropped"?{label:"Dropped",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function Bo(t,e){if(!t.length&&!e)return"Nothing sent yet.";let a=t.slice(0,4).map(function(n){return n.state==="working"?n.agentId+(n.by==="you"?" is working on your task.":" is busy with someone else's task."):n.state==="blocked"?n.agentId+" stopped on your task.":n.agentId+" is free."});return t.length>4&&a.push(t.length-4+" more below."),a.join(" ")||"Nothing running now."}function qo(t,e){if(!t)return[];let a={};return t.forEach(function(n){a[n.agentId]=n.state}),e.filter(function(n){return n.state==="free"&&a[n.agentId]==="working"}).map(function(n){return n.agentId})}var zo=`
1052
+ GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-Wt*864e5).map(r=>r.agent_id)}function Wo(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(bt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let d=n.queue?.get(l)??zo,p=s.get(l),c=p??i.get(l);if(!c)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:d};let m=o(c.person??null),g=c.status==="error"||c.status==="timeout",k=p?"working":g&&m==="you"?"blocked":"free",b=m==="you"&&c.channel!=="a2a",S=b&&c.channel;return{agentId:l,state:k,by:m,at:p?c.started_at:c.finished_at??c.started_at,text:p||b?c.message_preview??null:null,fullText:b&&p&&String(c.original_message??c.message_preview??"").slice(0,Wc)||null,where:S?{label:Xe(c.channel,c.chat_id??""),url:n.linkFor?.(c.channel,c.chat_id??"")??null}:null,queue:d}})}function Go(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Xo(t,e){return!t||e-t>=3e4||t>e}function Gt(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 Ko(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"}}function Xt(t,e,a,n){return t?e?{text:"Can't reach the server. "+(n?"Showing what was last loaded. ":"")+"Trying again every "+a+" seconds.",retry:!0}:{text:"Offline. Showing what was last loaded; live state needs a connection.",retry:!1}:null}function Kt(t){return String(t??"").replace(/```[\w-]*|`/g,"").replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^[ \t]*(?:#{1,6}|>+|[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm,"").replace(/\*\*|~~/g,"").replace(/(^|[\s(])\*(\S(?:[^*\n]*\S)?)\*(?=[\s).,;:!?]|$)/gm,"$1$2").replace(/\s+/g," ").trim()}function Jo(t){let e=t.by==="you"?"you":t.by==="owner"?"the owner":t.by?"someone else":null;if(t.state==="working"){let a=t.queue||{waiting:0,yours:0,ahead:null},n=a.ahead||0,r;return a.yours>0?r=(a.yours===1?"Your message is in line":a.yours+" messages of yours are in line")+(n===0?a.yours===1?": it runs when this ends.":": the first runs when this ends.":", "+n+(n===1?" message":" messages")+" ahead of "+(a.yours===1?"it.":"the first.")):a.waiting>0?r=a.waiting+(a.waiting===1?" message waits":" messages wait")+" in line. A new one from you waits behind "+(a.waiting===1?"it.":"them."):r=t.by==="you"?"Busy. A new message waits in line until this ends.":"A message you send now waits in line until this ends.",t.by==="you"?{label:"Working",tone:"work",what:t.text,by:e,hint:r}:{label:"Working",tone:"work",what:t.text||"Busy with someone else's task",by:e,hint:r}}return t.state==="blocked"?{label:"Blocked",tone:"stuck",what:t.text?"Stopped on: "+t.text:null,by:e,hint:"It stopped before finishing. It needs a person."}:{label:"Free",tone:"free",what:t.by==="you"&&t.text?"Finished: "+t.text:null,by:t.by==="you"?e:null,hint:"Free. Ready for your next message."}}function Vo(t){let e=t.request?t.request.state:"";return e==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:e==="needs_attention"?{label:"Stuck",tone:"stuck"}:t.status==="queued"?{label:"In line",tone:"wait"}:t.status==="in-flight"?{label:"Running",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function Yo(t){return t==="in_progress"?{label:"In progress",tone:"work"}:t==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:t==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:t==="needs_attention"?{label:"Stuck",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Declined",tone:"off"}:t==="dropped"?{label:"Dropped",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function Qo(t,e){if(!t.length&&!e)return"Nothing sent yet.";let a=t.slice(0,4).map(function(n){return n.state==="working"?n.agentId+(n.by==="you"?" is working on your task.":" is busy with someone else's task."):n.state==="blocked"?n.agentId+" stopped on your task.":n.agentId+" is free."});return t.length>4&&a.push(t.length-4+" more below."),a.join(" ")||"Nothing running now."}function Zo(t,e){if(!t)return[];let a={};return t.forEach(function(n){a[n.agentId]=n.state}),e.filter(function(n){return n.state==="free"&&a[n.agentId]==="working"}).map(function(n){return n.agentId})}var es=`
1053
1053
  (function () {
1054
1054
  var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
1055
1055
  var who = document.getElementById('who');
@@ -1261,7 +1261,7 @@ body { margin: 0; overflow: hidden; }
1261
1261
  showConn();
1262
1262
  load();
1263
1263
  })();
1264
- `;var Gt=`
1264
+ `;var Jt=`
1265
1265
  :root { --link: var(--ax-blue-d); --ring: var(--ax-blue); --tick: var(--ax-green-d); }
1266
1266
  [data-theme="dark"] { --link: var(--ax-blue); --tick: var(--ax-green); }
1267
1267
  * { box-sizing: border-box; }
@@ -1289,7 +1289,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
1289
1289
  .card h2 { font-size: 24px; font-weight: 700; line-height: 1.2; margin-bottom: 8px; }
1290
1290
  .card p { color: var(--ax-text-2); }
1291
1291
  .help { margin-top: 20px; font-size: 14px; color: var(--ax-text-2); }
1292
- `,Xt=`
1292
+ `,Vt=`
1293
1293
  .icon-btn { min-width: 44px; min-height: 44px; font-size: 20px; line-height: 1; border: var(--ax-border-w) solid var(--ax-border-2); border-radius: var(--ax-radius-pill); background: var(--ax-surface); color: var(--ax-text); cursor: pointer; }
1294
1294
  .strip, .install { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 10px 20px; font-size: 14px; background: var(--ax-amber-t); color: var(--ax-amber-ink); border-bottom: var(--ax-border-w) solid var(--ax-amber-e); }
1295
1295
  .strip[hidden], .install[hidden] { display: none; }
@@ -1364,7 +1364,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
1364
1364
  .blank { padding: 28px 24px; border: var(--ax-border-w) dashed var(--ax-border-2); border-radius: var(--ax-radius-lg); }
1365
1365
  .blank p + p { margin-top: 8px; color: var(--ax-text-2); }
1366
1366
  .foot { margin-top: 28px; font-size: 14px; color: var(--ax-text-2); }
1367
- `,Fo=`
1367
+ `,ts=`
1368
1368
  .pair-form { display: grid; gap: 8px; margin-top: 20px; }
1369
1369
  .pair-form label { font-weight: 600; margin-top: 8px; }
1370
1370
  .pair-form input { width: 100%; min-height: 52px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: var(--ax-border-w) solid var(--ax-text-2); border-radius: var(--ax-radius-sm); }
@@ -1376,11 +1376,11 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
1376
1376
  .card .pair-msg.bad { color: var(--ax-red-ink); }
1377
1377
  [data-theme="dark"] .card .pair-msg.bad { color: var(--ax-red); }
1378
1378
  .card .pair-offline { padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: 14px; background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
1379
- `,Uo=`
1379
+ `,as=`
1380
1380
  .pulse { display: inline-block; width: 12px; height: 12px; margin-right: 10px; border-radius: 50%; border: 3px solid var(--ax-amber-ink); box-sizing: border-box; animation: breathe 2.4s ease-in-out infinite; }
1381
1381
  @keyframes breathe { 50% { opacity: 0.35; } }
1382
1382
  @media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }
1383
- `;var Cc="<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 Pa(t,e={}){return`<meta charset="utf-8">
1383
+ `;var Gc="<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 Da(t,e={}){return`<meta charset="utf-8">
1384
1384
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
1385
1385
  <meta name="theme-color" content="#2979FF">
1386
1386
  <meta name="referrer" content="no-referrer">
@@ -1390,8 +1390,8 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
1390
1390
  <link rel="icon" type="image/png" href="/member/icon-192.png">
1391
1391
  <link rel="apple-touch-icon" href="/member/icon-192.png">
1392
1392
  <title>${t}</title>
1393
- ${Cc}
1394
- <style>${qe}${Gt}</style>`}function Wo(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#FFFFFF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Go=`
1393
+ ${Gc}
1394
+ <style>${Ue}${Jt}</style>`}function ns(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#FFFFFF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var rs=`
1395
1395
  var CACHE = 'agentx-member-v1';
1396
1396
  var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
1397
1397
  self.addEventListener('install', function (e) {
@@ -1421,14 +1421,14 @@ self.addEventListener('fetch', function (e) {
1421
1421
  e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
1422
1422
  }
1423
1423
  });
1424
- `;function $a(t,e="",a="My work"){return`<header class="bar">
1424
+ `;function Ha(t,e="",a="My work"){return`<header class="bar">
1425
1425
  <img class="mark" src="/member/icon-192.png" alt="" width="36" height="36">
1426
1426
  <div class="grow"><h1>${a}</h1><p id="who" class="who">${t}</p></div>${e}
1427
- </header>`}var ja=Pa,Oa=$a;function Xo(t){return`<ol class="steps" role="list" aria-label="Steps">${["Type the code","The owner says yes","Your work opens"].map((a,n)=>n<t?`<li class="done"><span class="sr">Done: </span>${a}</li>`:n===t?`<li class="now" aria-current="step">${a}</li>`:`<li>${a}</li>`).join("")}</ol>`}function Ko(){return`<!doctype html>
1427
+ </header>`}var Ba=Da,qa=Ha;function os(t){return`<ol class="steps" role="list" aria-label="Steps">${["Type the code","The owner says yes","Your work opens"].map((a,n)=>n<t?`<li class="done"><span class="sr">Done: </span>${a}</li>`:n===t?`<li class="now" aria-current="step">${a}</li>`:`<li>${a}</li>`).join("")}</ol>`}function ss(){return`<!doctype html>
1428
1428
  <html lang="en">
1429
- <head>${ja("My work \xB7 AgentX")}<style>${Xt}</style></head>
1429
+ <head>${Ba("My work \xB7 AgentX")}<style>${Vt}</style></head>
1430
1430
  <body>
1431
- ${Oa("Connecting\u2026",`
1431
+ ${qa("Connecting\u2026",`
1432
1432
  <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`)}
1433
1433
  <p id="offline" class="strip" role="status" hidden><span id="offline-text"></span><button type="button" id="retry" hidden>Try now</button></p>
1434
1434
  <aside id="install" class="install" aria-label="Keep this window" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</aside>
@@ -1439,15 +1439,15 @@ ${Oa("Connecting\u2026",`
1439
1439
  <section aria-labelledby="h-sent"><h2 id="h-sent" tabindex="-1">What you sent <span class="n">(last 7 days)</span></h2><ul id="sent" class="rows" role="list"></ul></section>
1440
1440
  <p id="updated" class="foot"></p>
1441
1441
  </main>
1442
- <script>${z({workState:Ic,ageText:Na,connectionNote:Ut,plainPreview:Wt,agentLine:No,sentState:Do,requestState:Ho,summaryLine:Bo,freedAgents:qo})}${zo}</script>
1442
+ <script>${z({workState:Xc,ageText:za,connectionNote:Xt,plainPreview:Kt,agentLine:Jo,sentState:Vo,requestState:Yo,summaryLine:Qo,freedAgents:Zo})}${es}</script>
1443
1443
  </body>
1444
- </html>`}function Jo(){return`<!doctype html>
1444
+ </html>`}function is(){return`<!doctype html>
1445
1445
  <html lang="en">
1446
- <head>${ja("Pair this machine \xB7 AgentX")}<style>${Fo}</style></head>
1446
+ <head>${Ba("Pair this machine \xB7 AgentX")}<style>${ts}</style></head>
1447
1447
  <body>
1448
- ${Oa("This machine is not paired yet")}
1448
+ ${qa("This machine is not paired yet")}
1449
1449
  <main class="narrow">
1450
- ${Xo(0)}
1450
+ ${os(0)}
1451
1451
  <div class="card">
1452
1452
  <h2>Pair this machine</h2>
1453
1453
  <p>The owner sent you a pairing code. Type it with a name for this machine. The owner then approves the machine, and your work page opens.</p>
@@ -1464,24 +1464,24 @@ ${Oa("This machine is not paired yet")}
1464
1464
  <p class="help">No code? Ask the person who invited you for one. A code works once, for 10 minutes.</p>
1465
1465
  </div>
1466
1466
  </main>
1467
- <script>${z({formatPairInput:Ft})}${Mc}</script>
1467
+ <script>${z({formatPairInput:Gt})}${Kc}</script>
1468
1468
  </body>
1469
- </html>`}function Vo(){return`<!doctype html>
1469
+ </html>`}function ls(){return`<!doctype html>
1470
1470
  <html lang="en">
1471
- <head>${ja("Waiting for the owner \xB7 AgentX")}<style>${Uo}</style></head>
1471
+ <head>${Ba("Waiting for the owner \xB7 AgentX")}<style>${as}</style></head>
1472
1472
  <body>
1473
- ${Oa("This machine is paired")}
1473
+ ${qa("This machine is paired")}
1474
1474
  <main class="narrow">
1475
- ${Xo(1)}
1475
+ ${os(1)}
1476
1476
  <div class="card">
1477
1477
  <h2><span class="pulse" aria-hidden="true"></span>Waiting for the owner</h2>
1478
1478
  <p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens your work by itself when they do.</p>
1479
1479
  <p class="help">If they say no, this page asks for a new code.</p>
1480
1480
  </div>
1481
1481
  </main>
1482
- <script>${Lc}</script>
1482
+ <script>${Jc}</script>
1483
1483
  </body>
1484
- </html>`}function Ic(t){let e=String(t||"");return e==="in_progress"?{label:"In progress",tone:"ok"}:e==="waiting_owner"?{label:"Waiting on the owner",tone:"warn"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"warn"}:e==="needs_attention"?{label:"Stuck: needs attention",tone:"bad"}:e==="done"?{label:"Done",tone:"ok"}:e==="declined"?{label:"Declined",tone:"bad"}:e==="dropped"?{label:"Dropped",tone:"muted"}:{label:e.replace(/_/g," "),tone:"muted"}}function Na(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min ago";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min ago":Math.floor(r/24)+" d "+r%24+" h ago"}var Mc=`
1484
+ </html>`}function Xc(t){let e=String(t||"");return e==="in_progress"?{label:"In progress",tone:"ok"}:e==="waiting_owner"?{label:"Waiting on the owner",tone:"warn"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"warn"}:e==="needs_attention"?{label:"Stuck: needs attention",tone:"bad"}:e==="done"?{label:"Done",tone:"ok"}:e==="declined"?{label:"Declined",tone:"bad"}:e==="dropped"?{label:"Dropped",tone:"muted"}:{label:e.replace(/_/g," "),tone:"muted"}}function za(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min ago";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min ago":Math.floor(r/24)+" d "+r%24+" h ago"}var Kc=`
1485
1485
  (function () {
1486
1486
  var form = document.getElementById('pair-form');
1487
1487
  var machine = document.getElementById('machine');
@@ -1525,7 +1525,7 @@ ${Oa("This machine is paired")}
1525
1525
  }).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
1526
1526
  });
1527
1527
  })();
1528
- `,Lc=`
1528
+ `,Jc=`
1529
1529
  (function () {
1530
1530
  var msg = document.getElementById('msg');
1531
1531
  function check() {
@@ -1536,16 +1536,16 @@ ${Oa("This machine is paired")}
1536
1536
  }
1537
1537
  setInterval(check, 5000);
1538
1538
  })();
1539
- `;function Yo(t){let e=t.request?t.request.state:"";return e==="waiting_owner"||e==="waiting_other"?{label:"Waiting on us",tone:"wait"}:e==="needs_attention"?{label:"Needs a look from us",tone:"stuck"}:t.status==="in-flight"?{label:"Being worked on",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped, we will look at it",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function Qo(t){return t==="in_progress"?{label:"Being worked on",tone:"work"}:t==="waiting_owner"||t==="waiting_other"?{label:"Waiting on us",tone:"wait"}:t==="needs_attention"?{label:"Needs a look from us",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Not taken on",tone:"off"}:t==="dropped"?{label:"Set aside",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function Zo(t){if(!t.length)return"Nothing asked for yet.";let e=0,a=0,n=0,r=0;for(let s=0;s<t.length;s++)t[s]==="work"?e++:t[s]==="wait"?a++:t[s]==="stuck"?n++:t[s]==="done"&&r++;let o=[];return e&&o.push(e===1?"1 request is being worked on for you.":e+" requests are being worked on for you."),a&&o.push(a===1?"1 is waiting on us.":a+" are waiting on us."),n&&o.push(n===1?"1 needs a look from us.":n+" need a look from us."),o.length?o.join(" "):r?"Nothing in progress right now. "+(r===1?"1 request finished":r+" requests finished")+" this week.":"Nothing in progress right now."}var Da="/member/client.webmanifest",et="Your project";function es(){return JSON.stringify({id:"/member?client",name:`${et} \xB7 AgentX`,short_name:et,description:"What you asked for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Rc=`
1539
+ `;function ds(t){let e=t.request?t.request.state:"";return e==="waiting_owner"||e==="waiting_other"?{label:"Waiting on us",tone:"wait"}:e==="needs_attention"?{label:"Needs a look from us",tone:"stuck"}:t.status==="in-flight"?{label:"Being worked on",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped, we will look at it",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function cs(t){return t==="in_progress"?{label:"Being worked on",tone:"work"}:t==="waiting_owner"||t==="waiting_other"?{label:"Waiting on us",tone:"wait"}:t==="needs_attention"?{label:"Needs a look from us",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Not taken on",tone:"off"}:t==="dropped"?{label:"Set aside",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function ps(t){if(!t.length)return"Nothing asked for yet.";let e=0,a=0,n=0,r=0;for(let s=0;s<t.length;s++)t[s]==="work"?e++:t[s]==="wait"?a++:t[s]==="stuck"?n++:t[s]==="done"&&r++;let o=[];return e&&o.push(e===1?"1 request is being worked on for you.":e+" requests are being worked on for you."),a&&o.push(a===1?"1 is waiting on us.":a+" are waiting on us."),n&&o.push(n===1?"1 needs a look from us.":n+" need a look from us."),o.length?o.join(" "):r?"Nothing in progress right now. "+(r===1?"1 request finished":r+" requests finished")+" this week.":"Nothing in progress right now."}var Fa="/member/client.webmanifest",nt="Your project";function us(){return JSON.stringify({id:"/member?client",name:`${nt} \xB7 AgentX`,short_name:nt,description:"What you asked for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Vc=`
1540
1540
  .about { margin-top: 32px; padding: 16px 20px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-lg); background: var(--ax-surface); font-size: 15px; color: var(--ax-text-2); }
1541
1541
  .wrap .about h2 { margin: 0 0 6px; }
1542
1542
  .about p + p { margin-top: 6px; }
1543
- `;function ts(){return`<!doctype html>
1543
+ `;function ms(){return`<!doctype html>
1544
1544
  <html lang="en">
1545
- <head>${Pa(`${et} \xB7 AgentX`,{manifest:Da,appTitle:et})}<style>${qe}${Gt}${Xt}${Rc}</style></head>
1545
+ <head>${Da(`${nt} \xB7 AgentX`,{manifest:Fa,appTitle:nt})}<style>${Ue}${Jt}${Vt}${Vc}</style></head>
1546
1546
  <body>
1547
- ${$a("Connecting\u2026",`
1548
- <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,et)}
1547
+ ${Ha("Connecting\u2026",`
1548
+ <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,nt)}
1549
1549
  <p id="offline" class="strip" role="status" hidden><span id="offline-text"></span><button type="button" id="retry" hidden>Try now</button></p>
1550
1550
  <aside id="install" class="install" aria-label="Keep this window" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</aside>
1551
1551
  <main class="wrap">
@@ -1557,9 +1557,9 @@ ${$a("Connecting\u2026",`
1557
1557
  </section>
1558
1558
  <p id="updated" class="foot"></p>
1559
1559
  </main>
1560
- <script>${z({ageText:Na,connectionNote:Ut,plainPreview:Wt,clientSentState:Yo,clientRequestState:Qo,clientSummary:Zo})}${Pc}</script>
1560
+ <script>${z({ageText:za,connectionNote:Xt,plainPreview:Kt,clientSentState:ds,clientRequestState:cs,clientSummary:ps})}${Yc}</script>
1561
1561
  </body>
1562
- </html>`}var Pc=`
1562
+ </html>`}var Yc=`
1563
1563
  (function () {
1564
1564
  var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
1565
1565
  var who = document.getElementById('who');
@@ -1666,10 +1666,10 @@ ${$a("Connecting\u2026",`
1666
1666
  showConn();
1667
1667
  load();
1668
1668
  })();
1669
- `;var Kt="agentx_member",$c=90*86400,jc=new At,os=t=>t.replace(/^\[app\]/,"[member]"),Oc=new Ie(t=>console.log(os(t))),as=new WeakMap;function Nc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Oc;let e=as.get(t.log);return e||as.set(t.log,e=new Ie(a=>t.log(os(a)))),e}var ns=null;function tt(t,e=X){try{return ns=e().people}catch{return ns??t}}async function ss(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new G(r.root),s=r.members??new ht(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new kt(r.root),limiter:r.pairLimiter??jc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return fe(e,200,"application/manifest+json",Wo());if(a===Da)return fe(e,200,"application/manifest+json",es());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),fe(e,200,"text/javascript; charset=utf-8",Go);if(a==="/member/icon-192.png")return fe(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/member/icon-512.png")return fe(e,200,"image/png",Fe(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Jr(t,i);return p.status===200&&e.setHeader("Set-Cookie",rs(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),we(e,p.status,p.body)}let l=Yr(Hc(t),i,Kr(t));if(!l.ok){if(l.status===401){let p=Ha(t);return Nc(r).record(a.slice(0,120),Bt(t,ze(Ba(t,Kt),o),p?ze(p,o):null)),a==="/member"?fe(e,401,"text/html; charset=utf-8",Jo()):we(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?fe(e,202,"text/html; charset=utf-8",Vo()):we(e,403,{error:l.error,waiting:!0})}let d=r.people().find(p=>p.id===l.personId),c=d?.role==="client";if(n==="GET"&&a==="/member"){let p=Ba(t,Kt);return p&&!Ha(t)&&e.setHeader("Set-Cookie",rs(p)),fe(e,200,"text/html; charset=utf-8",c?ts():Ko())}if(n==="GET"&&a==="/api/member/me")return we(e,200,{person:l.personId,name:d?.name??l.personId,role:d?.role??"member",device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let p=r.db?.()??null;if(!p)return we(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=Io(p,l.personId,{now:m,linkFor:r.linkFor}),_=(T,h)=>{let u=h instanceof Error?h.message:String(h);/no such table/i.test(u)||r.log?.(`[member] ${T} failed: ${u}`)},y={byAgent:new Map,mine:[]};try{y=Lo(p,l.personId,{linkFor:r.linkFor})}catch(T){_("the line",T)}let S=[];if(c)return we(e,200,{...Dc(g),agents:S});try{let T=Ro(p,d??{id:l.personId},m);S=Po(p,l.personId,T,{people:r.people(),linkFor:r.linkFor,queue:y.byAgent})}catch(T){_("agent cards",T)}return we(e,200,{...g,agents:S,queued:y.mine})}return we(e,404,{error:"not found"})}function Dc(t){let e=a=>a.map(({agentId:n,...r})=>r);return{...t,open:e(t.open),recent:e(t.recent),runs:e(t.runs),other:e(t.other)}}function rs(t){return`${Kt}=${t}; Path=/; Max-Age=${$c}; HttpOnly; Secure; SameSite=Lax`}function Hc(t){return Ha(t)??Ba(t,Kt)}function Ha(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ba(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function we(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}ec();var is='/*! 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 Vt,readFileSync as hs,writeFileSync as gs,rmSync as Rx,mkdirSync as Wc,copyFileSync as Gc,readdirSync as Xc}from"fs";import{resolve as Ge}from"path";tc();function ds(t){let e=ct.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ct.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 Jt(t){return C(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=ct.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 ls=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function cs(t){return Jt(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 ps(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Jt((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:ls(t?.chats),senders:ls(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 us(t){let e=String(t?.id??"");return Jt(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 ms(t){let e=String(t?.id??"");return Jt(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}"`})}ft();var ue={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 fs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=pe({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.`})+Pt([{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 I({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+qc()+Nr,css:Fc,scripts:`${e}<script>${Dr}
1670
- ${Hr}
1671
- ${Bc}
1672
- ${Uc}</script>`})}var Bc=`
1669
+ `;var Yt="agentx_member",Qc=90*86400,Zc=new Mt,xs=t=>t.replace(/^\[app\]/,"[member]"),ep=new Re(t=>console.log(xs(t))),fs=new WeakMap;function tp(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return ep;let e=fs.get(t.log);return e||fs.set(t.log,e=new Re(a=>t.log(xs(a)))),e}var hs=null;function rt(t,e=X){try{return hs=e().people}catch{return hs??t}}async function bs(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new G(r.root),s=r.members??new yt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new Tt(r.root),limiter:r.pairLimiter??Zc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return he(e,200,"application/manifest+json",ns());if(a===Fa)return he(e,200,"application/manifest+json",us());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),he(e,200,"text/javascript; charset=utf-8",rs);if(a==="/member/icon-192.png")return he(e,200,"image/png",Ge(192),"public, max-age=86400");if(a==="/member/icon-512.png")return he(e,200,"image/png",Ge(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let c=await io(t,i);return c.status===200&&e.setHeader("Set-Cookie",gs(c.token)),c.status===429&&e.setHeader("Retry-After",String(c.retryAfter)),_e(e,c.status,c.body)}let l=co(np(t),i,so(t));if(!l.ok){if(l.status===401){let c=Ua(t);return tp(r).record(a.slice(0,120),Ft(t,We(Wa(t,Yt),o),c?We(c,o):null)),a==="/member"?he(e,401,"text/html; charset=utf-8",is()):_e(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?he(e,202,"text/html; charset=utf-8",ls()):_e(e,403,{error:l.error,waiting:!0})}let d=r.people().find(c=>c.id===l.personId),p=d?.role==="client";if(n==="GET"&&a==="/member"){let c=Wa(t,Yt);return c&&!Ua(t)&&e.setHeader("Set-Cookie",gs(c)),he(e,200,"text/html; charset=utf-8",p?ms():ss())}if(n==="GET"&&a==="/api/member/me")return _e(e,200,{person:l.personId,name:d?.name??l.personId,role:d?.role??"member",device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let c=r.db?.()??null;if(!c)return _e(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=qo(c,l.personId,{now:m,linkFor:r.linkFor}),k=(T,h)=>{let u=h instanceof Error?h.message:String(h);/no such table/i.test(u)||r.log?.(`[member] ${T} failed: ${u}`)},b={byAgent:new Map,mine:[]};try{b=Fo(c,l.personId,{linkFor:r.linkFor})}catch(T){k("the line",T)}let S=[];if(p)return _e(e,200,{...ap(g),agents:S});try{let T=Uo(c,d??{id:l.personId},m);S=Wo(c,l.personId,T,{people:r.people(),linkFor:r.linkFor,queue:b.byAgent})}catch(T){k("agent cards",T)}return _e(e,200,{...g,agents:S,queued:b.mine})}return _e(e,404,{error:"not found"})}function ap(t){let e=a=>a.map(({agentId:n,...r})=>r);return{...t,open:e(t.open),recent:e(t.recent),runs:e(t.runs),other:e(t.other)}}function gs(t){return`${Yt}=${t}; Path=/; Max-Age=${Qc}; HttpOnly; Secure; SameSite=Lax`}function np(t){return Ua(t)??Wa(t,Yt)}function Ua(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Wa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function he(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function _e(t,e,a){return he(t,e,"application/json",JSON.stringify(a))}bc();var vs='/*! 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 Zt,readFileSync as As,writeFileSync as Cs,rmSync as ob,mkdirSync as dp,copyFileSync as cp,readdirSync as pp}from"fs";import{resolve as Je}from"path";vc();function ws(t){let e=ht.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ht.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 Qt(t){return C(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=ht.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 ys=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function ks(t){return Qt(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 _s(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Qt((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:ys(t?.chats),senders:ys(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 Ss(t){let e=String(t?.id??"");return Qt(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 Es(t){let e=String(t?.id??"");return Qt(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}"`})}vt();var me={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 Ts(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ue({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.`})+Ot([{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 I({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+op()+Jr,css:ip,scripts:`${e}<script>${Vr}
1670
+ ${Yr}
1671
+ ${rp}
1672
+ ${lp}</script>`})}var rp=`
1673
1673
  (function(){
1674
1674
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1675
1675
  async function voiceMissing() {
@@ -1763,8 +1763,8 @@ ${Uc}</script>`})}var Bc=`
1763
1763
  refresh();
1764
1764
  // Refresh again after the main admin script has had a chance to mutate config.
1765
1765
  document.addEventListener('ax-config-saved', refresh);
1766
- })();`;function qc(){let t=_r().business?`<button data-tab="business">Business</button>
1767
- `:"";return zc.replace("__BUSINESS_TABS__",t)}var zc=`
1766
+ })();`;function op(){let t=jr().business?`<button data-tab="business">Business</button>
1767
+ `:"";return sp.replace("__BUSINESS_TABS__",t)}var sp=`
1768
1768
  <div id="peer-banner" class="peer-banner">
1769
1769
  <span class="label">Managing</span>
1770
1770
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -1909,7 +1909,7 @@ ${Uc}</script>`})}var Bc=`
1909
1909
  <div id="global-msg" class="msg"></div>
1910
1910
 
1911
1911
  <section id="tab-agents" class="tab active">
1912
- ${K({icon:ue.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1912
+ ${K({icon:me.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1913
1913
  ${se({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
1914
1914
  <div id="agent-list" class="ax-stack"></div>
1915
1915
  <details class="add-form" style="margin-top:14px" id="wiki-curator-section">
@@ -1942,7 +1942,7 @@ ${Uc}</script>`})}var Bc=`
1942
1942
  </section>
1943
1943
 
1944
1944
  <section id="tab-channels" class="tab">
1945
- ${K({icon:ue.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1945
+ ${K({icon:me.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1946
1946
  ${se({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
1947
1947
 
1948
1948
  <details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
@@ -2028,10 +2028,10 @@ ${Uc}</script>`})}var Bc=`
2028
2028
  </div>
2029
2029
  </details>
2030
2030
 
2031
- <div id="ch-chatapps-label">${$t({label:"Chat apps"})}</div>
2031
+ <div id="ch-chatapps-label">${Nt({label:"Chat apps"})}</div>
2032
2032
  <div class="ax-connectors" id="ch-chatapps"></div>
2033
2033
 
2034
- <div id="ch-devtools-label">${$t({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
2034
+ <div id="ch-devtools-label">${Nt({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
2035
2035
  <div class="ax-connectors" id="ch-devtools"></div>
2036
2036
 
2037
2037
  <!-- Active-channel configuration panes. One shows at a time; clicking
@@ -2049,7 +2049,7 @@ ${Uc}</script>`})}var Bc=`
2049
2049
  </section>
2050
2050
 
2051
2051
  <section id="tab-crons" class="tab">
2052
- ${K({icon:ue.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
2052
+ ${K({icon:me.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
2053
2053
  ${se({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
2054
2054
  <div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
2055
2055
 
@@ -2171,7 +2171,7 @@ ${Uc}</script>`})}var Bc=`
2171
2171
  </section>
2172
2172
 
2173
2173
  <section id="tab-webhooks" class="tab">
2174
- ${K({icon:ue.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
2174
+ ${K({icon:me.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
2175
2175
  ${se({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
2176
2176
  <div id="webhook-list" class="ax-stack"></div>
2177
2177
  <div class="add-form">
@@ -2213,10 +2213,10 @@ ${Uc}</script>`})}var Bc=`
2213
2213
  </section>
2214
2214
 
2215
2215
  <section id="tab-mesh" class="tab">
2216
- ${K({icon:ue.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
2216
+ ${K({icon:me.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
2217
2217
  <div id="mesh-hero" class="ax-mesh-hero"></div>
2218
2218
  ${se({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
2219
- ${$t({label:"Connected peers"})}
2219
+ ${Nt({label:"Connected peers"})}
2220
2220
  <div id="mesh-peers" class="ax-stack"></div>
2221
2221
  <div class="add-form">
2222
2222
  <h3>Add a peer</h3>
@@ -2243,7 +2243,7 @@ ${Uc}</script>`})}var Bc=`
2243
2243
  </section>
2244
2244
 
2245
2245
  <section id="tab-business" class="tab">
2246
- ${K({icon:ue.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
2246
+ ${K({icon:me.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
2247
2247
  ${se({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
2248
2248
 
2249
2249
  <div class="ax-stack" style="margin-top:14px">
@@ -2331,7 +2331,7 @@ ${Uc}</script>`})}var Bc=`
2331
2331
  </section>
2332
2332
 
2333
2333
  <section id="tab-boards-cfg" class="tab">
2334
- ${K({icon:ue.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
2334
+ ${K({icon:me.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
2335
2335
  ${se({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
2336
2336
 
2337
2337
  <div class="ax-stack" style="margin-top:14px">
@@ -2356,7 +2356,7 @@ ${Uc}</script>`})}var Bc=`
2356
2356
  </section>
2357
2357
 
2358
2358
  <section id="tab-actions" class="tab">
2359
- ${K({icon:ue.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
2359
+ ${K({icon:me.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
2360
2360
  ${se({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
2361
2361
 
2362
2362
  <div class="ax-stack" style="margin-top:14px">
@@ -2412,7 +2412,7 @@ ${Uc}</script>`})}var Bc=`
2412
2412
  </section>
2413
2413
 
2414
2414
  <section id="tab-tokens" class="tab">
2415
- ${K({icon:ue.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
2415
+ ${K({icon:me.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
2416
2416
  ${se({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
2417
2417
  <div id="token-list" class="ax-stack"></div>
2418
2418
  <div class="add-form">
@@ -2432,7 +2432,7 @@ ${Uc}</script>`})}var Bc=`
2432
2432
  </section>
2433
2433
 
2434
2434
  <section id="tab-advanced" class="tab">
2435
- ${K({icon:ue.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
2435
+ ${K({icon:me.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
2436
2436
  ${se({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
2437
2437
 
2438
2438
  <div class="ax-jv-toolbar">
@@ -2459,7 +2459,7 @@ ${Uc}</script>`})}var Bc=`
2459
2459
  <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>
2460
2460
  </section>
2461
2461
  </main>
2462
- `,Fc=`
2462
+ `,ip=`
2463
2463
 
2464
2464
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
2465
2465
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -2667,7 +2667,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
2667
2667
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
2668
2668
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
2669
2669
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
2670
- `,Uc=`
2670
+ `,lp=`
2671
2671
  const $ = (id) => document.getElementById(id);
2672
2672
  let state = null;
2673
2673
 
@@ -5636,11 +5636,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
5636
5636
  })();
5637
5637
 
5638
5638
  refresh();
5639
- `;function xs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fs({peers:a,localToken:n}))}async function bs(t,e){let a=Fa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function vs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await ip(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Kc(t),r={"GET /api/admin/state":()=>Vc(),"POST /api/admin/agents":()=>ap(n),"PATCH /api/admin/agents":()=>np(n),"DELETE /api/admin/agents":()=>rp(n),"POST /api/admin/agents/access":()=>Yc(n),"POST /api/admin/channels/telegram":()=>op(n),"DELETE /api/admin/channels/telegram":()=>Ip(n),"POST /api/admin/channels/telegram/toggle":()=>Mp(n),"POST /api/admin/crons":()=>Lp(n),"DELETE /api/admin/crons":()=>Rp(n),"POST /api/admin/config/raw":()=>Pp(n),"GET /api/admin/tokens":()=>Qc(),"POST /api/admin/tokens":()=>Zc(n),"DELETE /api/admin/tokens":()=>ep(n),"POST /api/admin/agents/test":()=>tp(n),"POST /api/admin/agents/integrations":()=>mp(n),"DELETE /api/admin/agents/integrations":()=>fp(n),"PATCH /api/admin/agents/integrations":()=>hp(n),"PATCH /api/admin/channels/telegram":()=>sp(n),"POST /api/admin/channels/slack":()=>kp(n),"POST /api/admin/channels/slack/toggle":()=>_p(n),"POST /api/admin/channels/discord":()=>Sp(n),"POST /api/admin/channels/discord/toggle":()=>Ep(n),"POST /api/admin/channels/gitlab":()=>Tp(n),"POST /api/admin/channels/gitlab/toggle":()=>Ap(n),"POST /api/admin/channels/request-status":()=>eo(n),"GET /api/admin/channels/whatsapp/state":()=>We("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>We("/webrtc/history"),"POST /api/admin/actions":()=>Gp(n),"DELETE /api/admin/actions":()=>Xp(n),"POST /api/admin/actions/run":()=>Kp(n),"GET /api/admin/channels/whatsapp/chats":()=>We("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>We("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>he("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Cp(n),"POST /api/admin/webhooks":()=>gp(n),"PATCH /api/admin/webhooks":()=>xp(n),"DELETE /api/admin/webhooks":()=>wp(n),"POST /api/admin/whatsapp-triage":()=>cs(n),"POST /api/admin/whatsapp-triage/rules":()=>ps(n),"PATCH /api/admin/whatsapp-triage/rules":()=>us(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ms(n),"POST /api/admin/mesh/peers":()=>bp(n),"DELETE /api/admin/mesh/peers":()=>vp(n),"POST /api/admin/mesh/toggle":()=>yp(n),"GET /api/admin/files":()=>lp(t),"GET /api/admin/files/read":()=>dp(t),"PUT /api/admin/files":()=>cp(n),"POST /api/admin/files/skill":()=>pp(n),"DELETE /api/admin/files/skill":()=>up(n),"POST /api/admin/business/orgchart":()=>$p(n),"DELETE /api/admin/business/orgchart":()=>jp(n),"POST /api/admin/business/project":()=>Op(n),"DELETE /api/admin/business/project":()=>Hp(n),"POST /api/admin/business/client":()=>Np(n),"DELETE /api/admin/business/client":()=>Dp(n),"POST /api/admin/business/contact":()=>Bp(n),"DELETE /api/admin/business/contact":()=>qp(n),"POST /api/admin/boards":()=>zp(n),"DELETE /api/admin/boards":()=>Fp(n),"POST /api/admin/boards/columns":()=>Up(n),"DELETE /api/admin/boards/columns":()=>Wp(n),"POST /api/admin/notifications":()=>Yp(n),"POST /api/admin/wiki/curator":()=>Vp(n),"POST /api/admin/screen":()=>Zp(n),"POST /api/admin/wiki-notes":()=>Qp(n),"GET /api/admin/wiki-notes/list":()=>We("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>eu(n),"POST /api/admin/mesh/health":()=>Jp(n),"GET /api/admin/projects":()=>We("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>he("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>he("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>he("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>he("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>he("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>he("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>he("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>he("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){qa(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();qa(e,200,i)}catch(n){qa(e,400,{error:n.message||"admin op failed"})}}function qa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Kc(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 Jc(t){let e=Ge(process.cwd(),t);if(!Vt(e))return[];let a=[];for(let n of Xc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(hs(Ge(e,n.name),"utf-8")))}catch{}return a}function Fa(){let t=Ge(process.cwd(),"agentx.json");return Vt(t)?JSON.parse(hs(t,"utf-8")):null}function Vc(){let t=Fa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([h,u])=>({id:h,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",wikiAbsorb:u.wiki?.absorb?.enabled!==!1,integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(f=>{let b=f.credentials||{},v={};for(let[E,x]of Object.entries(b))typeof x=="string"&&/^[A-Z][A-Z0-9_]*$/.test(x)?v[E]=process.env[x]?"set":"unset":typeof x=="string"&&(v[E]="literal");return{kind:f.kind,label:f.label,enabled:f.enabled!==!1,credentials:b,credStatus:v,metadata:f.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([h,u])=>({id:h,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([h,u])=>({id:h,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(h=>({id:h.id,source:h.source,agentId:h.agentId,secretEnv:h.secretEnv||"",description:h.description||"",enabled:h.enabled!==!1,triggers:h.triggers&&typeof h.triggers=="object"?h.triggers:{},defaultWorkflow:h.defaultWorkflow||""})):[],c={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(h=>({url:h.url,name:h.name,hasToken:!!h.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},g={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:{}},_=t.notifications||{},y={longTaskThreshold:_.longTaskThreshold??30,destination:_.destination||null,on:{taskComplete:_.on?.taskComplete!==!1,taskError:_.on?.taskError!==!1,taskQueued:!!_.on?.taskQueued},local:nr(_.local),ntfy:ro(t.channels?.ntfy)},S=[];try{S=Jc(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,f)=>u.id.localeCompare(f.id))}catch{}let T=(Array.isArray(t.boards)?t.boards:[]).map(h=>({id:h.id,name:h.name,source:h.source||{type:"gitlab",projects:[]},primaryToolLabel:h.primaryToolLabel||"",timeRangeDays:h.timeRangeDays??30,closedWindowDays:h.closedWindowDays??30,columns:Array.isArray(h.columns)?h.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Zr(t),whatsappTriage:ds(t),crons:l,webhooks:d,mesh:c,daemonUrl:p,nodeName:t.node?.name,business:g,boards:T,notifications:y,screen:$r(t.screen),wikiNotes:ao(t.wikiNotes),actions:S,wikiCurator:ks(t)}}function Yc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function Qc(){return new G().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 Zc(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 G().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function ep(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new G().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function tp(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 c=X();r=c.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=c.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function ap(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=ws(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=Ge(process.cwd(),"agents",e),{summary:l}=C(c=>{if(c.agents=c.agents||{},c.agents[e])throw new Error(`Agent "${e}" already exists.`);let p={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(p.model=o),s&&(p.systemPrompt=s.slice(0,400)),c.agents[e]=p,`added agent "${e}"`}),d=Ge(i,"CLAUDE.md");if(!Vt(d))try{Wc(i,{recursive:!0}),gs(d,`# ${a}
5639
+ `;function Is(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ts({peers:a,localToken:n}))}async function Ms(t,e){let a=Ka();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Rs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ep(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await up(t),r={"GET /api/admin/state":()=>fp(),"POST /api/admin/agents":()=>yp(n),"PATCH /api/admin/agents":()=>wp(n),"DELETE /api/admin/agents":()=>kp(n),"POST /api/admin/agents/access":()=>hp(n),"POST /api/admin/channels/telegram":()=>_p(n),"DELETE /api/admin/channels/telegram":()=>Xp(n),"POST /api/admin/channels/telegram/toggle":()=>Kp(n),"POST /api/admin/crons":()=>Jp(n),"DELETE /api/admin/crons":()=>Vp(n),"POST /api/admin/config/raw":()=>Yp(n),"GET /api/admin/tokens":()=>gp(),"POST /api/admin/tokens":()=>xp(n),"DELETE /api/admin/tokens":()=>bp(n),"POST /api/admin/agents/test":()=>vp(n),"POST /api/admin/agents/integrations":()=>Rp(n),"DELETE /api/admin/agents/integrations":()=>Lp(n),"PATCH /api/admin/agents/integrations":()=>Pp(n),"PATCH /api/admin/channels/telegram":()=>Sp(n),"POST /api/admin/channels/slack":()=>Bp(n),"POST /api/admin/channels/slack/toggle":()=>qp(n),"POST /api/admin/channels/discord":()=>zp(n),"POST /api/admin/channels/discord/toggle":()=>Fp(n),"POST /api/admin/channels/gitlab":()=>Up(n),"POST /api/admin/channels/gitlab/toggle":()=>Wp(n),"POST /api/admin/channels/request-status":()=>mo(n),"GET /api/admin/channels/whatsapp/state":()=>Ke("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Ke("/webrtc/history"),"POST /api/admin/actions":()=>cu(n),"DELETE /api/admin/actions":()=>pu(n),"POST /api/admin/actions/run":()=>uu(n),"GET /api/admin/channels/whatsapp/chats":()=>Ke("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Ke("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ge("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Gp(n),"POST /api/admin/webhooks":()=>$p(n),"PATCH /api/admin/webhooks":()=>jp(n),"DELETE /api/admin/webhooks":()=>Hp(n),"POST /api/admin/whatsapp-triage":()=>ks(n),"POST /api/admin/whatsapp-triage/rules":()=>_s(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Ss(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Es(n),"POST /api/admin/mesh/peers":()=>Op(n),"DELETE /api/admin/mesh/peers":()=>Np(n),"POST /api/admin/mesh/toggle":()=>Dp(n),"GET /api/admin/files":()=>Tp(t),"GET /api/admin/files/read":()=>Ap(t),"PUT /api/admin/files":()=>Cp(n),"POST /api/admin/files/skill":()=>Ip(n),"DELETE /api/admin/files/skill":()=>Mp(n),"POST /api/admin/business/orgchart":()=>Qp(n),"DELETE /api/admin/business/orgchart":()=>Zp(n),"POST /api/admin/business/project":()=>eu(n),"DELETE /api/admin/business/project":()=>nu(n),"POST /api/admin/business/client":()=>tu(n),"DELETE /api/admin/business/client":()=>au(n),"POST /api/admin/business/contact":()=>ru(n),"DELETE /api/admin/business/contact":()=>ou(n),"POST /api/admin/boards":()=>su(n),"DELETE /api/admin/boards":()=>iu(n),"POST /api/admin/boards/columns":()=>lu(n),"DELETE /api/admin/boards/columns":()=>du(n),"POST /api/admin/notifications":()=>hu(n),"POST /api/admin/wiki/curator":()=>fu(n),"POST /api/admin/screen":()=>xu(n),"POST /api/admin/wiki-notes":()=>gu(n),"GET /api/admin/wiki-notes/list":()=>Ke("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>bu(n),"POST /api/admin/mesh/health":()=>mu(n),"GET /api/admin/projects":()=>Ke("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ge("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ge("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ge("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ge("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ge("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ge("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ge("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ge("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Ga(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Ga(e,200,i)}catch(n){Ga(e,400,{error:n.message||"admin op failed"})}}function Ga(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function up(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 mp(t){let e=Je(process.cwd(),t);if(!Zt(e))return[];let a=[];for(let n of pp(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(As(Je(e,n.name),"utf-8")))}catch{}return a}function Ka(){let t=Je(process.cwd(),"agentx.json");return Zt(t)?JSON.parse(As(t,"utf-8")):null}function fp(){let t=Ka();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([h,u])=>({id:h,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",wikiAbsorb:u.wiki?.absorb?.enabled!==!1,integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(f=>{let v=f.credentials||{},y={};for(let[E,x]of Object.entries(v))typeof x=="string"&&/^[A-Z][A-Z0-9_]*$/.test(x)?y[E]=process.env[x]?"set":"unset":typeof x=="string"&&(y[E]="literal");return{kind:f.kind,label:f.label,enabled:f.enabled!==!1,credentials:v,credStatus:y,metadata:f.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([h,u])=>({id:h,botUsername:u.botUsername||"",agentBinding:u.agentBinding||"",botTokenRef:u.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([h,u])=>({id:h,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(h=>({id:h.id,source:h.source,agentId:h.agentId,secretEnv:h.secretEnv||"",description:h.description||"",enabled:h.enabled!==!1,triggers:h.triggers&&typeof h.triggers=="object"?h.triggers:{},defaultWorkflow:h.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(h=>({url:h.url,name:h.name,hasToken:!!h.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},c=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},g={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:{}},k=t.notifications||{},b={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:ur(k.local),ntfy:xo(t.channels?.ntfy)},S=[];try{S=mp(".agentx/actions").filter(u=>u&&typeof u=="object"&&u.id).map(u=>({id:u.id,title:u.title,kind:u.kind,description:u.description||"",inputs:Array.isArray(u.inputs)?u.inputs:[],timeoutMs:u.timeoutMs??3e4,command:u.kind==="shell"?u.command:void 0,url:u.kind==="http"?u.url:void 0,method:u.kind==="http"?u.method:void 0})).sort((u,f)=>u.id.localeCompare(f.id))}catch{}let T=(Array.isArray(t.boards)?t.boards:[]).map(h=>({id:h.id,name:h.name,source:h.source||{type:"gitlab",projects:[]},primaryToolLabel:h.primaryToolLabel||"",timeRangeDays:h.timeRangeDays??30,closedWindowDays:h.closedWindowDays??30,columns:Array.isArray(h.columns)?h.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:uo(t),whatsappTriage:ws(t),crons:l,webhooks:d,mesh:p,daemonUrl:c,nodeName:t.node?.name,business:g,boards:T,notifications:b,screen:Gr(t.screen),wikiNotes:ho(t.wikiNotes),actions:S,wikiCurator:$s(t)}}function hp(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function gp(){return new G().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 xp(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 G().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function bp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new G().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function vp(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=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function yp(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=Ps(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=Je(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let c={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(c.model=o),s&&(c.systemPrompt=s.slice(0,400)),p.agents[e]=c,`added agent "${e}"`}),d=Je(i,"CLAUDE.md");if(!Zt(d))try{dp(i,{recursive:!0}),Cs(d,`# ${a}
5640
5640
 
5641
5641
  ${s||"You are "+a+"."}
5642
- `)}catch{}return{summary:l}}function np(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=ws(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),typeof a.wikiAbsorb=="boolean"&&Ot(o,a.wikiAbsorb),`updated agent "${e}"`});return{summary:n}}function rp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function op(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=C(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function sp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function We(t){let{url:e,headers:a}=Ua(),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 he(t,e){let{url:a,headers:n}=Ua(),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 ip(t,e){try{let{url:a,headers:n}=Ua(),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 Ua(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function at(t){let a=Fa()?.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 za(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function lp(t){let e=za(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Be(at(e));return{agentId:e,...a}}function dp(t){let e=za(t,"agent").trim(),a=za(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ct(at(e),a)}function cp(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=It(at(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function pp(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=Mt(at(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function up(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=Lt(at(e),a);return{summary:`removed skill "${a}"`,...n}}function mp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function fp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function hp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(c=>c.kind===a&&c.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var ys=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function gp(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(!ys.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(p=>p.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(c=>c.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function xp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&ys.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 bp(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=C(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function vp(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function yp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function wp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function kp(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=C(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function _p(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function Sp(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=C(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Ep(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Tp(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=C(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function Ap(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function Cp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-AW4F5ZKS.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 Ip(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function Mp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function Lp(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=C(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function Rp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=C(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function Pp(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=Ge(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Vt(n))try{Gc(n,r)}catch{}gs(n,JSON.stringify(a,null,2)+`
5643
- `,"utf-8");try{let s=X().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 ws(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function $p(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function jp(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=C(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function Op(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=C(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function Np(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=C(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function Dp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function Hp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=C(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function Bp(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=C(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function qp(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=C(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function zp(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(p=>p.id===e),c={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(c.primaryToolLabel=r),d>=0){let p=l.boards[d];return l.boards[d]={...p,...c,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(c),`board "${e}" added`});return{summary:i}}async function Fp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=C(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Up(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(p=>p.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let c=l.columns.findIndex(p=>p.id===a);return c>=0?(l.columns[c]={...l.columns[c],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Wp(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=C(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Gp(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 Xp(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 Kp(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 Jp(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=C(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}function ks(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function Vp(t){let{summary:e}=C(a=>{if(a.wiki=a.wiki||{},a.wiki.curator=a.wiki.curator||{},t&&"enabled"in t&&(a.wiki.curator.enabled=!!t.enabled),t&&"agent"in t){let r=String(t.agent||"").trim();if(!r)delete a.wiki.curator.agent;else if(a.agents?.[r])a.wiki.curator.agent=r;else throw new Error(`no agent "${r}"`)}let n=ks(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function Yp(t){let{summary:e}=C(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=rr(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=oo(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 Qp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let e={};"enabled"in t&&(e.enabled=!!t.enabled),"inbox"in t&&(e.inbox=String(t.inbox??"")),"crons"in t&&(e.crons=Array.isArray(t.crons)?t.crons.map(String):String(t.crons??"").split(",")),"absorbAgent"in t&&(e.absorbAgent=String(t.absorbAgent??"")),"maxNotesPerRun"in t&&(e.maxNotesPerRun=Number(t.maxNotesPerRun)),"maxDeferrals"in t&&(e.maxDeferrals=Number(t.maxDeferrals));let{summary:a}=C(n=>no(n,e));return{summary:a}}async function Zp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=jr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function eu(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ft();import{resolve as nu}from"path";function _s(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
5642
+ `)}catch{}return{summary:l}}function wp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=C(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=Ps(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),typeof a.wikiAbsorb=="boolean"&&Ht(o,a.wikiAbsorb),`updated agent "${e}"`});return{summary:n}}function kp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function _p(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=C(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Sp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Ke(t){let{url:e,headers:a}=Ja(),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 ge(t,e){let{url:a,headers:n}=Ja(),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 Ep(t,e){try{let{url:a,headers:n}=Ja(),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 Ja(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ot(t){let a=Ka()?.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 Xa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Tp(t){let e=Xa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Fe(ot(e));return{agentId:e,...a}}function Ap(t){let e=Xa(t,"agent").trim(),a=Xa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Rt(ot(e),a)}function Cp(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=Lt(ot(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Ip(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=Pt(ot(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Mp(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=$t(ot(e),a);return{summary:`removed skill "${a}"`,...n}}function Rp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Lp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Pp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Ls=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function $p(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(!Ls.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(c=>c.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function jp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=C(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Ls.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 Op(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=C(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function Np(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function Dp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function Hp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function Bp(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=C(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function qp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function zp(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=C(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Fp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Up(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=C(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function Wp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function Gp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-7NK2FH5V.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 Xp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function Kp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function Jp(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=C(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function Vp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=C(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function Yp(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=Je(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Zt(n))try{cp(n,r)}catch{}Cs(n,JSON.stringify(a,null,2)+`
5643
+ `,"utf-8");try{let s=X().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 Ps(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Qp(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function Zp(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=C(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function eu(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=C(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function tu(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=C(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function au(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=C(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function nu(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=C(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function ru(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=C(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function ou(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=C(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function su(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(c=>c.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let c=l.boards[d];return l.boards[d]={...c,...p,columns:c.columns,labels:c.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function iu(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=C(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function lu(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(c=>c.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let p=l.columns.findIndex(c=>c.id===a);return p>=0?(l.columns[p]={...l.columns[p],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function du(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=C(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function cu(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 pu(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 uu(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 mu(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=C(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}function $s(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function fu(t){let{summary:e}=C(a=>{if(a.wiki=a.wiki||{},a.wiki.curator=a.wiki.curator||{},t&&"enabled"in t&&(a.wiki.curator.enabled=!!t.enabled),t&&"agent"in t){let r=String(t.agent||"").trim();if(!r)delete a.wiki.curator.agent;else if(a.agents?.[r])a.wiki.curator.agent=r;else throw new Error(`no agent "${r}"`)}let n=$s(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function hu(t){let{summary:e}=C(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=mr(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=bo(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 gu(t){if(!t||typeof t!="object")throw new Error("nothing to update");let e={};"enabled"in t&&(e.enabled=!!t.enabled),"inbox"in t&&(e.inbox=String(t.inbox??"")),"crons"in t&&(e.crons=Array.isArray(t.crons)?t.crons.map(String):String(t.crons??"").split(",")),"absorbAgent"in t&&(e.absorbAgent=String(t.absorbAgent??"")),"maxNotesPerRun"in t&&(e.maxNotesPerRun=Number(t.maxNotesPerRun)),"maxDeferrals"in t&&(e.maxDeferrals=Number(t.maxDeferrals));let{summary:a}=C(n=>go(n,e));return{summary:a}}async function xu(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Xr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function bu(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}vt();import{resolve as wu}from"path";function js(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
5644
5644
 
5645
5645
  <div id="disabled-banner" class="banner warn" style="display:none">
5646
5646
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -5695,7 +5695,7 @@ ${s||"You are "+a+"."}
5695
5695
  <h2>Recent classifications</h2>
5696
5696
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
5697
5697
  <div id="recent"></div>
5698
- </section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:tu,scripts:`${e}<script>${au}</script>`})}var tu=`
5698
+ </section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vu,scripts:`${e}<script>${yu}</script>`})}var vu=`
5699
5699
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
5700
5700
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
5701
5701
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -5799,7 +5799,7 @@ details {
5799
5799
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
5800
5800
  }
5801
5801
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
5802
- details[open] summary { margin-bottom: 8px; }`,au=`
5802
+ details[open] summary { margin-bottom: 8px; }`,yu=`
5803
5803
  const $ = (id) => document.getElementById(id);
5804
5804
  const state = { schema: null, nodes: [], pending: [], recent: [] };
5805
5805
 
@@ -6019,7 +6019,7 @@ $('btn-save-schema').addEventListener('click', async () => {
6019
6019
  $('btn-reload-schema').addEventListener('click', refresh);
6020
6020
 
6021
6021
  refresh();
6022
- `;function Es(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_s({peers:a,localToken:n}))}async function Ts(t,e,a){try{let n=t.method==="GET"?void 0:await uu(t),r=ru(),o={"GET /api/admin/graph/state":()=>ou(r),"POST /api/admin/graph/classifications/approve":()=>su(r,n),"POST /api/admin/graph/classifications/reject":()=>iu(r,n),"POST /api/admin/graph/nodes":()=>lu(r,n),"PATCH /api/admin/graph/nodes":()=>du(r,n),"DELETE /api/admin/graph/nodes":()=>cu(r,n),"PUT /api/admin/graph/schema":()=>pu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Wa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Wa(e,200,l)}catch(n){Wa(e,400,{error:n?.message||"graph op failed"})}}function ru(){let t=X(),e=nu(process.cwd(),t.graph.baseDir);return new zn({baseDir:e})}function ou(t){let e=X(),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 su(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=As(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=Ga(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function iu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=As(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function As(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 lu(t,e){let a=Ss(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Ss(String(e.parentId)):null,o=Ga({[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 du(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ga({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function cu(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function pu(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 Ga(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 Ss(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Wa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function uu(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 Cs=`
6022
+ `;function Ns(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(js({peers:a,localToken:n}))}async function Ds(t,e,a){try{let n=t.method==="GET"?void 0:await Mu(t),r=ku(),o={"GET /api/admin/graph/state":()=>_u(r),"POST /api/admin/graph/classifications/approve":()=>Su(r,n),"POST /api/admin/graph/classifications/reject":()=>Eu(r,n),"POST /api/admin/graph/nodes":()=>Tu(r,n),"PATCH /api/admin/graph/nodes":()=>Au(r,n),"DELETE /api/admin/graph/nodes":()=>Cu(r,n),"PUT /api/admin/graph/schema":()=>Iu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Va(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Va(e,200,l)}catch(n){Va(e,400,{error:n?.message||"graph op failed"})}}function ku(){let t=X(),e=wu(process.cwd(),t.graph.baseDir);return new Yn({baseDir:e})}function _u(t){let e=X(),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 Su(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Hs(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=Ya(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Eu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Hs(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Hs(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 Tu(t,e){let a=Os(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Os(String(e.parentId)):null,o=Ya({[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 Au(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ya({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Cu(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Iu(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 Ya(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 Os(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Va(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Mu(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 Bs=`
6023
6023
  <section class="apv__req" id="req-section" aria-labelledby="req-h">
6024
6024
  <h2 id="req-h">Open requests <span id="req-n"></span></h2>
6025
6025
  <p class="apv__lead">What you asked agents for that is not finished, oldest first. Reply, hand it to an agent, close it as done, or drop it. Nothing leaves this list by getting old.</p>
@@ -6041,7 +6041,7 @@ refresh();
6041
6041
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6042
6042
  </form>
6043
6043
  </details>
6044
- </section>`,Is=`
6044
+ </section>`,qs=`
6045
6045
  .apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
6046
6046
  .apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
6047
6047
  .apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
@@ -6069,7 +6069,7 @@ refresh();
6069
6069
  .apv__plan .is-done { color: var(--ax-ok, inherit); }
6070
6070
  .apv__plan .is-blocked { color: var(--ax-err); }
6071
6071
  .apv__plan small { display: block; color: var(--ax-muted); }
6072
- `,Ms=`
6072
+ `,zs=`
6073
6073
  (function(){
6074
6074
  var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
6075
6075
  function $(id){ return document.getElementById(id); }
@@ -6234,7 +6234,7 @@ function busy(){
6234
6234
  }
6235
6235
  setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
6236
6236
  })();
6237
- `;function Ls(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6237
+ `;function Fs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6238
6238
  <header class="apv__head">
6239
6239
  <div>
6240
6240
  <h1>Approvals</h1>
@@ -6256,7 +6256,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
6256
6256
  <ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
6257
6257
  <p id="apv-snoozed" class="apv__foot"></p>
6258
6258
 
6259
- ${Cs}
6259
+ ${Bs}
6260
6260
 
6261
6261
  <details class="apv__settings" id="apv-settings">
6262
6262
  <summary>Settings: expiry, later, daily digest</summary>
@@ -6271,7 +6271,7 @@ ${Cs}
6271
6271
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6272
6272
  </form>
6273
6273
  </details>
6274
- </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:mu+Is,scripts:`${e}<script>${fu}</script><script>${Ms}</script>`})}var mu=`
6274
+ </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ru+qs,scripts:`${e}<script>${Lu}</script><script>${zs}</script>`})}var Ru=`
6275
6275
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
6276
6276
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
6277
6277
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -6328,7 +6328,7 @@ ${Cs}
6328
6328
  @media (max-width: 560px) {
6329
6329
  .apv__acts .ax-btn { flex: 1 1 0; }
6330
6330
  }
6331
- `,fu=`
6331
+ `,Lu=`
6332
6332
  (function(){
6333
6333
  var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
6334
6334
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
@@ -6552,7 +6552,7 @@ $('apv-form').addEventListener('submit', async function(ev){
6552
6552
  load();
6553
6553
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within, .apv__item[data-touched]')) load(); }, 60000);
6554
6554
  })();
6555
- `;import{existsSync as hu,readFileSync as gu}from"fs";var Me="/api/admin/approvals/requests";function Rs(t){let e=Kn(t);if(!hu(e))return[];try{let a=JSON.parse(gu(e,"utf-8"))?.agents??{};return Object.entries(a).map(([n,r])=>({id:n,name:typeof r?.name=="string"&&r.name?r.name:n}))}catch{return[]}}var Yt=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Ps(t,e,a,n){try{return await xu(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function xu(t,e,a,n){if(t==="GET"&&e===Me){let o=St(n);return{status:200,body:{items:o?o.listOpen().map(s=>gr(s,o,mr(n))):[],agents:Rs(n.configPath),settings:_t(n.configPath)}}}let r=e===`${Me}/reply`?"reply":e===`${Me}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=St(n),d=l?.get(o);if(!l||!d||d.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=r==="reply"?d.agentId:typeof a.agentId=="string"?a.agentId:"",p=Rs(n.configPath).find(g=>g.id===c);if(r==="handoff"&&!p)return{status:400,body:{error:`"${c}" is not an agent on this node`}};if(!_t(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,c,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=p?.name??c;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Me}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=St(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",d,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Me}/settings`){let o={},s=d=>{let c=a[d];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${d} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=Yt(a.from),o.channels=Yt(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i={};if(typeof a.plansEnabled=="boolean"&&(i.enabled=a.plansEnabled),i.stallMinutes=s("stallMinutes"),a.maxNudges!==void 0){if(typeof a.maxNudges!="number"||!Number.isInteger(a.maxNudges)||a.maxNudges<0)throw new Error("maxNudges must be a whole number, 0 or more");i.maxNudges=a.maxNudges}i.approveKinds=Yt(a.approveKinds),i.disabledAgents=Yt(a.plansOffFor),Object.values(i).some(d=>d!==void 0)&&(o.plans=i);let l=await ur(o,{configPath:n.configPath,reload:n.reload});return l.success?{status:200,body:{ok:!0,settings:_t(n.configPath)}}:{status:400,body:{error:l.error}}}return{status:404,body:{error:"Not found"}}}var bu=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Qt(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 vu(t){let e=t.choice;return{...typeof e=="number"||typeof e=="string"&&e.trim()?{choice:typeof e=="string"?e.trim():e}:{},...typeof t.text=="string"&&t.text.trim()?{text:t.text}:{}}}function $s(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Ls({peers:e,localToken:a}))}async function js(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 te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Me)){let i=await Ps(o,a,o==="POST"?await Qt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=Et(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:Ae(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Qt(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!bu.includes(d))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let c=Ae(s.configPath),p=await Tt(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:c.laterHours,by:"operator (dashboard)",...vu(i)});return p.ok?(te(e,200,{ok:!0,message:p.message}),!0):(te(e,409,{error:p.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Qt(t),l=xr(s,typeof i.key=="string"?i.key:"",!!Ae(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Qt(t),l={},d=p=>{let m=i[p];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${p} must be a positive number`);return m}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let p=i.destination.trim();if(!p)l.destination=null;else{let m=Wr(p);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let c=await Gr(l,{configPath:s.configPath,reload:s.reload});return c.success?(te(e,200,{ok:!0,settings:Ae(s.configPath)}),!0):(te(e,400,{error:c.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}ya();function Os(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=pe({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates, your clients and guests. Open a person to see the machines they paired and what they asked for."})+`
6555
+ `;import{existsSync as Pu,readFileSync as $u}from"fs";var xe="/api/admin/approvals/requests";function Us(t){let e=nr(t);if(!Pu(e))return[];try{let a=JSON.parse($u(e,"utf-8"))?.agents??{};return Object.entries(a).map(([n,r])=>({id:n,name:typeof r?.name=="string"&&r.name?r.name:n}))}catch{return[]}}var ea=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function ta(t,e,a,n){try{return await ju(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function ju(t,e,a,n){if(t==="GET"&&e===xe){let o=ze(n);return{status:200,body:{items:o?o.listOpen().map(s=>Cr(s,o,Sr(n))):[],agents:Us(n.configPath),settings:At(n.configPath)}}}let r=e===`${xe}/reply`?"reply":e===`${xe}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=ze(n),d=l?.get(o);if(!l||!d||d.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?d.agentId:typeof a.agentId=="string"?a.agentId:"",c=Us(n.configPath).find(g=>g.id===p);if(r==="handoff"&&!c)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!At(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,p,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=c?.name??p;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${xe}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=ze(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",d,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${xe}/settings`){let o={},s=d=>{let p=a[d];if(p!==void 0){if(typeof p!="number"||!(p>0))throw new Error(`${d} must be a positive number`);return p}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=ea(a.from),o.channels=ea(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i={};if(typeof a.plansEnabled=="boolean"&&(i.enabled=a.plansEnabled),i.stallMinutes=s("stallMinutes"),a.maxNudges!==void 0){if(typeof a.maxNudges!="number"||!Number.isInteger(a.maxNudges)||a.maxNudges<0)throw new Error("maxNudges must be a whole number, 0 or more");i.maxNudges=a.maxNudges}i.approveKinds=ea(a.approveKinds),i.disabledAgents=ea(a.plansOffFor),Object.values(i).some(d=>d!==void 0)&&(o.plans=i);let l=await _r(o,{configPath:n.configPath,reload:n.reload});return l.success?{status:200,body:{ok:!0,settings:At(n.configPath)}}:{status:400,body:{error:l.error}}}return{status:404,body:{error:"Not found"}}}var Ou=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function aa(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 Nu(t){let e=t.choice;return{...typeof e=="number"||typeof e=="string"&&e.trim()?{choice:typeof e=="string"?e.trim():e}:{},...typeof t.text=="string"&&t.text.trim()?{text:t.text}:{}}}function Ws(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Fs({peers:e,localToken:a}))}async function Gs(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 te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(xe)){let i=await ta(o,a,o==="POST"?await aa(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=Ct(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:Ie(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await aa(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!Ou.includes(d))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Ie(s.configPath),c=await It(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)",...Nu(i)});return c.ok?(te(e,200,{ok:!0,message:c.message}),!0):(te(e,409,{error:c.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await aa(t),l=Ir(s,typeof i.key=="string"?i.key:"",!!Ie(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await aa(t),l={},d=c=>{let m=i[c];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${c} must be a positive number`);return m}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let c=i.destination.trim();if(!c)l.destination=null;else{let m=no(c);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await ro(l,{configPath:s.configPath,reload:s.reload});return p.success?(te(e,200,{ok:!0,settings:Ie(s.configPath)}),!0):(te(e,400,{error:p.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}Ea();function Xs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ue({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates, your clients and guests. Open a person to see the machines they paired and what they asked for."})+`
6556
6556
  <div class="pp">
6557
6557
  <div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
6558
6558
  <section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
@@ -6565,7 +6565,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6565
6565
  </ol>
6566
6566
  </section>
6567
6567
  <ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
6568
- </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:yu,scripts:`${e}<script>${wu}</script>`})}var yu=`
6568
+ </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Du,scripts:`${e}<script>${Hu}</script>`})}var Du=`
6569
6569
  .pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
6570
6570
  .pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
6571
6571
  .pp-msg.is-bad { color: var(--ax-red-ink); }
@@ -6606,7 +6606,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6606
6606
  .pp-text { overflow-wrap: anywhere; }
6607
6607
  .pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
6608
6608
  @media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
6609
- `,wu=`
6609
+ `,Hu=`
6610
6610
  (function () {
6611
6611
  var list = document.getElementById('pp-list');
6612
6612
  var msg = document.getElementById('pp-msg');
@@ -6744,7 +6744,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6744
6744
  load();
6745
6745
  setInterval(load, 30000);
6746
6746
  })();
6747
- `;var Xa="/api/admin/people";function ku(t,e){let a=Vr(t,e);return a?{...e,answer:a}:e}function _u(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function ge(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function Su(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&_u(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:mt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Eu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Ns(t,e,a,n){if(a!=="/people"&&a!==Xa&&!a.startsWith(`${Xa}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(ge(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Os({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return ge(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=d=>n.members.devices(d).map(c=>ku(n.root,c)),s=()=>Su(n.people(),o());if(r==="GET"&&a===Xa){let d=s();return ge(e,200,{people:d,paired:d.reduce((c,p)=>c+p.machines.active+p.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let d=s().find(g=>g.id===i[1]);if(!d)return ge(e,404,{error:`no person "${i[1]}"`}),!0;let c=n.db(),p=[],m=[];try{c&&(p=Xr(c,d.id))}catch{}try{c&&(m=jt(c,d.id,20))}catch{}return ge(e,200,{person:d,devices:o(d.id).sort(Eu),requests:p,runs:m,database:!!c}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,d,c]=l,p=n.members.byToken(c);if(!p||p.personId!==d)return ge(e,404,{error:"no such machine for this person"}),!0;if(p.state==="removed")return ge(e,409,{error:"this machine's access has already ended"}),!0;let m=Qr({tokens:n.tokens??new G,members:n.members,now:n.now},c,"removed by the owner (dashboard)");return ge(e,200,{ok:!0,device:m}),!0}return ge(e,404,{error:"not found"}),!0}import{resolve as Mu}from"path";import{existsSync as Lu}from"fs";import Ru from"better-sqlite3";var Ds=new WeakSet;function Tu(t,e,a={}){if(Ds.has(t))return;Ds.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let d=i[l].bind(i);i[l]=(...c)=>{let p=r();try{return d(...c)}finally{let m=r()-p;m>=n&&e({sql:s,ms:m})}}}return i}}function Au(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ke(t,e){Tu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Au(a)}`))}function Hs(t={}){let e=`<div class="ax-obs">
6747
+ `;var Qa="/api/admin/people";function Bu(t,e){let a=lo(t,e);return a?{...e,answer:a}:e}function qu(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function zu(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&qu(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:bt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Fu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Ks(t,e,a,n){if(a!=="/people"&&a!==Qa&&!a.startsWith(`${Qa}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(be(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Xs({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return be(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=d=>n.members.devices(d).map(p=>Bu(n.root,p)),s=()=>zu(n.people(),o());if(r==="GET"&&a===Qa){let d=s();return be(e,200,{people:d,paired:d.reduce((p,c)=>p+c.machines.active+c.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let d=s().find(g=>g.id===i[1]);if(!d)return be(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),c=[],m=[];try{p&&(c=oo(p,d.id))}catch{}try{p&&(m=Dt(p,d.id,20))}catch{}return be(e,200,{person:d,devices:o(d.id).sort(Fu),requests:c,runs:m,database:!!p}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,d,p]=l,c=n.members.byToken(p);if(!c||c.personId!==d)return be(e,404,{error:"no such machine for this person"}),!0;if(c.state==="removed")return be(e,409,{error:"this machine's access has already ended"}),!0;let m=po({tokens:n.tokens??new G,members:n.members,now:n.now},p,"removed by the owner (dashboard)");return be(e,200,{ok:!0,device:m}),!0}return be(e,404,{error:"not found"}),!0}import{resolve as Ku}from"path";import{existsSync as Ju}from"fs";import Vu from"better-sqlite3";var Js=new WeakSet;function Uu(t,e,a={}){if(Js.has(t))return;Js.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let d=i[l].bind(i);i[l]=(...p)=>{let c=r();try{return d(...p)}finally{let m=r()-c;m>=n&&e({sql:s,ms:m})}}}return i}}function Wu(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function Se(t,e){Uu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Wu(a)}`))}function Vs(t={}){let e=`<div class="ax-obs">
6748
6748
  <header class="ax-obs__head">
6749
6749
  <h1>Health</h1>
6750
6750
  <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>
@@ -6866,7 +6866,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6866
6866
  </div>
6867
6867
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
6868
6868
  </section>
6869
- </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Cu,scripts:`<script>${Iu}</script>`})}var Cu=`
6869
+ </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Gu,scripts:`<script>${Xu}</script>`})}var Gu=`
6870
6870
  .ax-obs { padding: 16px 24px; }
6871
6871
  .ax-obs__head { margin-bottom: 16px; }
6872
6872
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -6983,7 +6983,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6983
6983
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
6984
6984
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
6985
6985
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
6986
- `,Iu=`
6986
+ `,Xu=`
6987
6987
  (function(){
6988
6988
  var panes = document.querySelectorAll('.ax-obs__pane');
6989
6989
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -7367,23 +7367,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7367
7367
 
7368
7368
  load(current);
7369
7369
  })();
7370
- `;var zs={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 Fs(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ka(t){let e=zs[Fs(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 Pu(){let t=Mu(process.cwd(),".agentx/db.sqlite");if(!Lu(t))return null;try{let e=new Ru(t,{readonly:!0,fileMustExist:!0});return ke(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Us(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hs({peers:a}))}function $u(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 xe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Ws(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Pu();if(!r)return xe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=$u(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7370
+ `;var Zs={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 ei(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Za(t){let e=Zs[ei(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 Yu(){let t=Ku(process.cwd(),".agentx/db.sqlite");if(!Ju(t))return null;try{let e=new Vu(t,{readonly:!0,fileMustExist:!0});return Se(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function ti(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vs({peers:a}))}function Qu(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 ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function ai(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Yu();if(!r)return ve(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Qu(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7371
7371
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
7372
7372
  FROM route_traces
7373
7373
  ${i.length?"WHERE "+i.join(" AND "):""}
7374
7374
  ORDER BY at DESC LIMIT @limit
7375
- `,c=r.db.prepare(d).all(l);return xe(e,200,{rows:c}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7375
+ `,p=r.db.prepare(d).all(l);return ve(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7376
7376
  SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
7377
7377
  FROM rotations
7378
7378
  ${i.length?"WHERE "+i.join(" AND "):""}
7379
7379
  ORDER BY rotated_at DESC LIMIT @limit
7380
- `,c=r.db.prepare(d).all(l);return xe(e,200,{rows:c}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7380
+ `,p=r.db.prepare(d).all(l);return ve(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7381
7381
  SELECT started_at, agent_id, channel, message_preview, error
7382
7382
  FROM task_history
7383
7383
  WHERE ${i.join(" AND ")}
7384
7384
  ORDER BY started_at DESC LIMIT @limit
7385
- `,p=r.db.prepare(d).all(l).map(m=>({...m,plain:Gs(m.error)}));return xe(e,200,{rows:p}),!0}if(n==="summary"||n==="overview")return xe(e,200,ju(r.db)),!0;if(n==="activity")return xe(e,200,Ou(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Bs(i.searchParams.get("range"));return xe(e,200,qs(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Bs(i.searchParams.get("range")),d=qs(r.db,l),c=Nu(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(c),!0}return xe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return xe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Gs(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(`
7386
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function ju(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,c=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),p=x=>c.length?c[Math.min(c.length-1,Math.floor(c.length*x))].duration_ms:0,m=p(.5),g=p(.95),y=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((x,A)=>x+Ka(A),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((x,A)=>x+Ka(A),0),T=t.prepare(`
7385
+ `,c=r.db.prepare(d).all(l).map(m=>({...m,plain:ni(m.error)}));return ve(e,200,{rows:c}),!0}if(n==="summary"||n==="overview")return ve(e,200,Zu(r.db)),!0;if(n==="activity")return ve(e,200,em(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Ys(i.searchParams.get("range"));return ve(e,200,Qs(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Ys(i.searchParams.get("range")),d=Qs(r.db,l),p=tm(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return ve(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function ni(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(`
7386
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Zu(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),c=x=>p.length?p[Math.min(p.length-1,Math.floor(p.length*x))].duration_ms:0,m=c(.5),g=c(.95),b=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((x,A)=>x+Za(A),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((x,A)=>x+Za(A),0),T=t.prepare(`
7387
7387
  SELECT agent_id,
7388
7388
  COUNT(*) AS tasks,
7389
7389
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -7401,12 +7401,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7401
7401
  WHERE started_at >= ?
7402
7402
  GROUP BY channel
7403
7403
  ORDER BY tasks DESC
7404
- `).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(x=>x.agent_id),f=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(x=>x.agent_id)),b=u.filter(x=>!f.has(x)),E=t.prepare(`
7404
+ `).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(x=>x.agent_id),f=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(x=>x.agent_id)),v=u.filter(x=>!f.has(x)),E=t.prepare(`
7405
7405
  SELECT started_at, agent_id, channel, message_preview, error
7406
7406
  FROM task_history
7407
7407
  WHERE status='error' AND started_at >= ?
7408
7408
  ORDER BY started_at DESC LIMIT 5
7409
- `).all(o).map(x=>({...x,plain:Gs(x.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:m,p95DurationMs:g,spendToday:y,spendDelta:y-S,idleAgentCount:b.length},perAgent:T,perChannel:h,idleAgents:b,recentErrors:E}}function Ou(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(`
7409
+ `).all(o).map(x=>({...x,plain:ni(x.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:m,p95DurationMs:g,spendToday:b,spendDelta:b-S,idleAgentCount:v.length},perAgent:T,perChannel:h,idleAgents:v,recentErrors:E}}function em(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(`
7410
7410
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
7411
7411
  COUNT(*) AS tasks,
7412
7412
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -7433,7 +7433,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7433
7433
  WHERE started_at >= @since
7434
7434
  GROUP BY agent_id
7435
7435
  ORDER BY tasks_24h DESC, tasks_7d DESC
7436
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Bs(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 qs(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7436
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Ys(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 Qs(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7437
7437
  SELECT day, agent_id, model,
7438
7438
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
7439
7439
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -7441,37 +7441,37 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7441
7441
  FROM usage_daily
7442
7442
  ${a}
7443
7443
  ORDER BY day
7444
- `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,c=0,p=0,m=0,g=0,_=0,y=0,S=0,T={},h={};for(let k of n){let L=Ka(k),j=Fs(k.model),$=zs[j],O=(k.tier2_input_tokens||0)/1e6*$.input*.5+(k.tier2_output_tokens||0)/1e6*$.output*.5+(k.tier2_cache_read_tokens||0)/1e6*$.cacheRead*.5+(k.tier2_cache_create_tokens||0)/1e6*$.cacheCreate*.5,W=(k.input_tokens||0)+(k.tier2_input_tokens||0),de=(k.output_tokens||0)+(k.tier2_output_tokens||0),Q=(k.cache_read_tokens||0)+(k.tier2_cache_read_tokens||0),oe=(k.cache_create_tokens||0)+(k.tier2_cache_create_tokens||0);p+=L,k.day>=s&&(c+=L,_+=k.tasks||0),k.day>=i&&k.day<s&&(S+=L,y+=k.tasks||0),k.day===r&&(l+=L),k.day===o&&(d+=L),k.day===r&&(m+=O),k.day>=s&&(g+=O);let Z=T[k.day]||(T[k.day]={date:k.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=k.tasks||0,Z.input+=W,Z.output+=de,Z.cacheRead+=Q,Z.cacheCreate+=oe,Z.cost+=L,Z.tier2+=O;let F=Z.agents[k.agent_id]||(Z.agents[k.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:k.model});F.tasks+=k.tasks||0,F.cost+=L,F.tier2+=O,F.input+=W,F.output+=de,F.cacheRead+=Q,F.cacheCreate+=oe,k.model&&(F.model=k.model);let N=h[k.agent_id]||(h[k.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:k.model});N.tasks+=k.tasks||0,N.cost+=L,N.tier2+=O,N.input+=W,N.output+=de,N.cacheRead+=Q,N.cacheCreate+=oe,k.model&&(N.model=k.model)}let u=Object.values(T).sort((k,L)=>k.date<L.date?-1:1),f=0,b=0,v=0,E=0,x=0,A=0;for(let k of u)f+=k.tasks,b+=k.input,v+=k.output,E+=k.cacheRead,x+=k.cacheCreate,A+=k.cost;let R=Object.entries(h).map(([k,L])=>({agent_id:k,...L,tokens:L.input+L.output+L.cacheRead+L.cacheCreate})).sort((k,L)=>L.cost-k.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:c,spend30d:p,tier2Today:m,tier2_7d:g,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:f,tokensRange:b+v+E+x,cacheHitRange:E+b>0?E/(E+b):0,costPerTaskRange:f>0?A/f:0,spendDeltaWoW:S>0?(c-S)/S:0,tasksDeltaWoW:y>0?(_-y)/y:0},days:u,perAgent:R}}function Nu(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+`
7444
+ `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,c=0,m=0,g=0,k=0,b=0,S=0,T={},h={};for(let _ of n){let R=Za(_),j=ei(_.model),$=Zs[j],O=(_.tier2_input_tokens||0)/1e6*$.input*.5+(_.tier2_output_tokens||0)/1e6*$.output*.5+(_.tier2_cache_read_tokens||0)/1e6*$.cacheRead*.5+(_.tier2_cache_create_tokens||0)/1e6*$.cacheCreate*.5,W=(_.input_tokens||0)+(_.tier2_input_tokens||0),ce=(_.output_tokens||0)+(_.tier2_output_tokens||0),Q=(_.cache_read_tokens||0)+(_.tier2_cache_read_tokens||0),oe=(_.cache_create_tokens||0)+(_.tier2_cache_create_tokens||0);c+=R,_.day>=s&&(p+=R,k+=_.tasks||0),_.day>=i&&_.day<s&&(S+=R,b+=_.tasks||0),_.day===r&&(l+=R),_.day===o&&(d+=R),_.day===r&&(m+=O),_.day>=s&&(g+=O);let Z=T[_.day]||(T[_.day]={date:_.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=_.tasks||0,Z.input+=W,Z.output+=ce,Z.cacheRead+=Q,Z.cacheCreate+=oe,Z.cost+=R,Z.tier2+=O;let F=Z.agents[_.agent_id]||(Z.agents[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});F.tasks+=_.tasks||0,F.cost+=R,F.tier2+=O,F.input+=W,F.output+=ce,F.cacheRead+=Q,F.cacheCreate+=oe,_.model&&(F.model=_.model);let N=h[_.agent_id]||(h[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});N.tasks+=_.tasks||0,N.cost+=R,N.tier2+=O,N.input+=W,N.output+=ce,N.cacheRead+=Q,N.cacheCreate+=oe,_.model&&(N.model=_.model)}let u=Object.values(T).sort((_,R)=>_.date<R.date?-1:1),f=0,v=0,y=0,E=0,x=0,A=0;for(let _ of u)f+=_.tasks,v+=_.input,y+=_.output,E+=_.cacheRead,x+=_.cacheCreate,A+=_.cost;let L=Object.entries(h).map(([_,R])=>({agent_id:_,...R,tokens:R.input+R.output+R.cacheRead+R.cacheCreate})).sort((_,R)=>R.cost-_.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:c,tier2Today:m,tier2_7d:g,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:f,tokensRange:v+y+E+x,cacheHitRange:E+v>0?E/(E+v):0,costPerTaskRange:f>0?A/f:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:b>0?(k-b)/b:0},days:u,perAgent:L}}function tm(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+`
7445
7445
  `+a.join(`
7446
7446
  `)+`
7447
- `}import{resolve as Du}from"path";import{existsSync as Hu}from"fs";import Bu from"better-sqlite3";function qu(){let t=Du(process.cwd(),".agentx/intent/ledger.sqlite");if(!Hu(t))return null;try{let e=new Bu(t,{readonly:!0,fileMustExist:!0});return ke(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Xs>6e4&&(Xs=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Xs=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function zu(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 Ks(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=qu();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=zu(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),c=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let p=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),_=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,y=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${p}`).get({since:s}).n,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),h=r.db.prepare(`
7447
+ `}import{resolve as am}from"path";import{existsSync as nm}from"fs";import rm from"better-sqlite3";function om(){let t=am(process.cwd(),".agentx/intent/ledger.sqlite");if(!nm(t))return null;try{let e=new rm(t,{readonly:!0,fileMustExist:!0});return Se(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ri>6e4&&(ri=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var ri=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function sm(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 oi(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=om();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=sm(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let c=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${c} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,b=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${c}`).get({since:s}).n,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${c} GROUP BY source ORDER BY n DESC`).all({since:s}),h=r.db.prepare(`
7448
7448
  SELECT COUNT(*) AS n FROM intent_decisions d
7449
7449
  LEFT JOIN intent_resolutions r
7450
7450
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7451
7451
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
7452
- `).get().n;return Le(e,200,{since:s??null,eventsBySource:g,totalDecisions:_,decisionsByOutcome:y,totalDivergences:S,divergencesBySource:T,inFlight:h}),!0}if(n==="events"){let p=[],m={limit:c};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i),l&&(p.push("project = @project"),m.project=l);let g=`
7452
+ `).get().n;return Le(e,200,{since:s??null,eventsBySource:g,totalDecisions:k,decisionsByOutcome:b,totalDivergences:S,divergencesBySource:T,inFlight:h}),!0}if(n==="events"){let c=[],m={limit:p};s!==void 0&&(c.push("ts >= @since"),m.since=s),i&&(c.push("source = @source"),m.source=i),l&&(c.push("project = @project"),m.project=l);let g=`
7453
7453
  SELECT id, ts, source, source_event_id, project, subject, intent
7454
7454
  FROM intent_events
7455
- ${p.length?"WHERE "+p.join(" AND "):""}
7455
+ ${c.length?"WHERE "+c.join(" AND "):""}
7456
7456
  ORDER BY ts DESC LIMIT @limit
7457
- `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="divergences"){let p=[],m={limit:c};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i);let g=`
7457
+ `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="divergences"){let c=[],m={limit:p};s!==void 0&&(c.push("ts >= @since"),m.since=s),i&&(c.push("source = @source"),m.source=i);let g=`
7458
7458
  SELECT ts, source, decided_by,
7459
7459
  legacy_agent_id, legacy_outcome, legacy_reason,
7460
7460
  ledger_agent_id, ledger_outcome, ledger_reason,
7461
7461
  event_id
7462
7462
  FROM intent_divergences
7463
- ${p.length?"WHERE "+p.join(" AND "):""}
7463
+ ${c.length?"WHERE "+c.join(" AND "):""}
7464
7464
  ORDER BY ts DESC LIMIT @limit
7465
- `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="active"){let p=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:c};i&&(p.push("e.source = @source"),m.source=i);let g=`
7465
+ `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="active"){let c=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:p};i&&(c.push("e.source = @source"),m.source=i);let g=`
7466
7466
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
7467
7467
  d.decided_by, d.decided_at, d.agent_id, d.reason
7468
7468
  FROM intent_decisions d
7469
7469
  JOIN intent_events e ON e.id = d.event_id
7470
7470
  LEFT JOIN intent_resolutions r
7471
7471
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7472
- WHERE ${p.join(" AND ")}
7472
+ WHERE ${c.join(" AND ")}
7473
7473
  ORDER BY d.decided_at DESC LIMIT @limit
7474
- `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}return Le(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Le(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Js(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7474
+ `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}return Le(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Le(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function si(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7475
7475
  <header class="ax-led__head">
7476
7476
  <h1>Intent ledger</h1>
7477
7477
  <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>
@@ -7676,7 +7676,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7676
7676
  }
7677
7677
  load();
7678
7678
  })();
7679
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Vs(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7679
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function ii(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7680
7680
  <header class="ax-cost__head">
7681
7681
  <div>
7682
7682
  <h1>Cost</h1>
@@ -8249,7 +8249,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8249
8249
  load();
8250
8250
  setInterval(load, 30000);
8251
8251
  })();
8252
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Ys(t={}){let e=`<div class="ax-pj__root">
8252
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function li(t={}){let e=`<div class="ax-pj__root">
8253
8253
  <aside class="ax-pj__list">
8254
8254
  <header>
8255
8255
  <h2>Projects</h2>
@@ -8276,7 +8276,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8276
8276
  </header>
8277
8277
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
8278
8278
  </section>
8279
- </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Fu,scripts:`<script>${Uu}</script>`})}var Fu=`
8279
+ </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:im,scripts:`<script>${lm}</script>`})}var im=`
8280
8280
  .ax-pj__root {
8281
8281
  display: grid;
8282
8282
  grid-template-columns: 360px 1fr;
@@ -8463,7 +8463,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8463
8463
  }
8464
8464
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
8465
8465
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
8466
- `,Uu=`
8466
+ `,lm=`
8467
8467
  (function(){
8468
8468
  const $ = (sel) => document.querySelector(sel);
8469
8469
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -9113,31 +9113,31 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
9113
9113
  load();
9114
9114
  });
9115
9115
  })();
9116
- `;import{resolve as Za,join as sm}from"path";import{existsSync as en,readdirSync as im,readFileSync as lm}from"fs";import dm from"better-sqlite3";var Zs=String.raw`[\w.-]+(?:/[\w.-]+)+`,Wu=new RegExp(`^(?:chat:)?(${Zs}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Gu=new RegExp(`^\\[(?:GitLab|GitHub) (${Zs}) `);function Qs(t){if(!t)return null;let e=t.match(Wu);return e?e[1]:null}function Ja(t){if(!t)return null;let e=t.trimStart().match(Gu);return e?e[1]:null}function Zt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Qs(typeof n?.chatId=="string"?n.chatId:null)??Qs(e)??Ja(a)}function Xu(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function ea(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ku=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Ju=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Vu=t=>/^issue/i.test(t)?"issue":"mr";function Yu(t){let e=t.subject.match(Ku)??t.inputPreview.trimStart().match(Ju);return e?{kind:Vu(e[1]),n:Number(e[2])}:null}function Qu(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 ei(t){if(!Xu(t.projectId))return[];let e=Yu(t);return e?[e]:Qu(t.inputPreview)}var Zu=6e4,em=5*6e4,tm=40,ti=6,ai=new Map;function ni(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 ei(n)){let s=ea(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=tm)return[...e.values()]}}return[...e.values()]}async function ri(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ea(s.project,s.ref),l=ai.get(i);l&&n-l.at<(s.github?em:Zu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ti)await Promise.all(o.slice(s,s+ti).map(async i=>{let l=ea(i.project,i.ref),d=null;try{d=i.github?await nm(i,e,a):await am(i,e,a)}catch{}ai.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function oi(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 am(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 oi(`${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 nm(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 oi(`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}$n();var Va=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function si(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=pt(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=Va(o.from,80);if(s){a.callback={from:s,status:Va(o.status,20)??"done"};let i=Va(o.peer,80);i&&(a.callback.peer=i)}}return a}$n();ya();var ii={kind:"agentx",id:"agentx",name:"AgentX"},Ya={kind:"person",id:"unknown",name:"Unknown"},rm=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),li=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Re=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function om(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Re(o?.id)??(e==="whatsapp"?Re(n?.from):void 0),i=Re(o?.username)??Re(o?.login);return s||i?{id:s,username:i,name:Re(o?.name)}:null}function di(t){let e=s=>({kind:"person",id:`person:${s}`,name:Hn(t.people,s)}),a=(s,i)=>i||rm.has(s)?ii:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Re(n.person)??qn(t.people,s)?.id;if(i)return e(i);let l=pt(s),d=l?.channel??t.channel;if(Pn(s)==="human")return li(s?.senderUsername)?a(d,!1):Ya;let c=!!Re(n.senderAgentId)||ga(l?l.sender:s?.sender);return d==="desktop"&&!c?Ya:a(d,c)}let r=om(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Bn(t.people,t.channel,r);return o?e(o.id):ga(r.name)?ii:Rn.has(t.channel)&&!li(r.username)?Ya:a(t.channel,!1)}function tn(){let t=Za(process.cwd(),".agentx/intent/ledger.sqlite");if(!en(t))return null;try{let e=new dm(t,{readonly:!0,fileMustExist:!0});return ke(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ci>6e4&&(ci=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ci=0;function be(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 cm(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 mi(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 pm(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 fi(t,e,a){return tr(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 um(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:J(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&&!Qa(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Qa(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:fm(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,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!Qa(i||l||"")){let c=typeof n.channel=="string"?n.channel:"",p=pi(c);return{id:d,name:l||i||d,avatar:J(l||i||d),kind:p}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:J(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(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:J(i),kind:pi(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:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(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:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(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:J(o),kind:"whatsapp"}}}return null}var mm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function fm(t,e){let a=mm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function pi(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Qa(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 J(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 hi(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}
9116
+ `;import{resolve as rn,join as Sm}from"path";import{existsSync as on,readdirSync as Em,readFileSync as Tm}from"fs";import Am from"better-sqlite3";var ci=String.raw`[\w.-]+(?:/[\w.-]+)+`,dm=new RegExp(`^(?:chat:)?(${ci}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),cm=new RegExp(`^\\[(?:GitLab|GitHub) (${ci}) `);function di(t){if(!t)return null;let e=t.match(dm);return e?e[1]:null}function en(t){if(!t)return null;let e=t.trimStart().match(cm);return e?e[1]:null}function na(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():di(typeof n?.chatId=="string"?n.chatId:null)??di(e)??en(a)}function pm(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function ra(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var um=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,mm=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,fm=t=>/^issue/i.test(t)?"issue":"mr";function hm(t){let e=t.subject.match(um)??t.inputPreview.trimStart().match(mm);return e?{kind:fm(e[1]),n:Number(e[2])}:null}function gm(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 pi(t){if(!pm(t.projectId))return[];let e=hm(t);return e?[e]:gm(t.inputPreview)}var xm=6e4,bm=5*6e4,vm=40,ui=6,mi=new Map;function fi(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 pi(n)){let s=ra(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=vm)return[...e.values()]}}return[...e.values()]}async function hi(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ra(s.project,s.ref),l=mi.get(i);l&&n-l.at<(s.github?bm:xm)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ui)await Promise.all(o.slice(s,s+ui).map(async i=>{let l=ra(i.project,i.ref),d=null;try{d=i.github?await wm(i,e,a):await ym(i,e,a)}catch{}mi.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function gi(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 ym(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 gi(`${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 wm(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 gi(`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}Fn();var tn=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function xi(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=gt(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=tn(o.from,80);if(s){a.callback={from:s,status:tn(o.status,20)??"done"};let i=tn(o.peer,80);i&&(a.callback.peer=i)}}return a}Fn();Ea();var bi={kind:"agentx",id:"agentx",name:"AgentX"},an={kind:"person",id:"unknown",name:"Unknown"},km=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),vi=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Pe=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function _m(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Pe(o?.id)??(e==="whatsapp"?Pe(n?.from):void 0),i=Pe(o?.username)??Pe(o?.login);return s||i?{id:s,username:i,name:Pe(o?.name)}:null}function yi(t){let e=s=>({kind:"person",id:`person:${s}`,name:Kn(t.people,s)}),a=(s,i)=>i||km.has(s)?bi:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Pe(n.person)??Vn(t.people,s)?.id;if(i)return e(i);let l=gt(s),d=l?.channel??t.channel;if(zn(s)==="human")return vi(s?.senderUsername)?a(d,!1):an;let p=!!Pe(n.senderAgentId)||wa(l?l.sender:s?.sender);return d==="desktop"&&!p?an:a(d,p)}let r=_m(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Jn(t.people,t.channel,r);return o?e(o.id):wa(r.name)?bi:qn.has(t.channel)&&!vi(r.username)?an:a(t.channel,!1)}function sn(){let t=rn(process.cwd(),".agentx/intent/ledger.sqlite");if(!on(t))return null;try{let e=new Am(t,{readonly:!0,fileMustExist:!0});return Se(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-wi>6e4&&(wi=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var wi=0;function ye(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var $e={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Cm(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in $e)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in $e)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in $e)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in $e)return s}return"workflow"}return t}function Si(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 Im(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 Ei(t,e,a){return cr(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 Mm(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:J(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&&!nn(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!nn(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Lm(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,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!nn(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",c=ki(p);return{id:d,name:l||i||d,avatar:J(l||i||d),kind:c}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:J(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(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:J(i),kind:ki(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:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(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:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(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:J(o),kind:"whatsapp"}}}return null}var Rm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Lm(t,e){let a=Rm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ki(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function nn(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 J(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 Ti(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}
9117
9117
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
9118
- ${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 hm(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 gi(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
9118
+ ${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 Pm(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 Ai(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
9119
9119
  SELECT id, ts, source, project, subject, intent, raw_json
9120
9120
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
9121
- `).all(r),s=new Map,i=new Map;if(o.length>0){let x=o.map(j=>j.id),A=x.map((j,$)=>`@id${$}`).join(","),R=Object.fromEntries(x.map((j,$)=>[`id${$}`,j])),k=t.prepare(`
9121
+ `).all(r),s=new Map,i=new Map;if(o.length>0){let x=o.map(j=>j.id),A=x.map((j,$)=>`@id${$}`).join(","),L=Object.fromEntries(x.map((j,$)=>[`id${$}`,j])),_=t.prepare(`
9122
9122
  SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
9123
9123
  FROM intent_decisions WHERE event_id IN (${A}) ORDER BY decided_at ASC
9124
- `).all(R);for(let j of k)s.has(j.event_id)||s.set(j.event_id,[]),s.get(j.event_id).push(j);let L=t.prepare(`
9124
+ `).all(L);for(let j of _)s.has(j.event_id)||s.set(j.event_id,[]),s.get(j.event_id).push(j);let R=t.prepare(`
9125
9125
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
9126
9126
  FROM intent_resolutions WHERE decision_event_id IN (${A})
9127
- `).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,d=new Map,c=new Map,p=new Map,m=[],g=e?.business?.projects??[],_=e?.business?.contactMap??[],y=_a(e?.business??{}),S=e?.people??[];for(let x of o){let A=null;try{A=JSON.parse(x.raw_json)}catch{}let R=fi(x.source,A,_),k=hi(x.source,A),L=si(A),j=x.project??Zt(A,x.subject,k),$=null,O=null;R?($=R.client,O=R.project||`${R.client}/_chat`):j&&($=bt(j,g),O=j);let W=cm(x.source,x.intent||"",A),de=Pe[W]||{label:W,color:"#6b7280"};c.has(W)||c.set(W,{id:W,label:de.label,color:de.color});let Q=di({source:x.source,channel:W,raw:A,people:S,channelLabel:N=>Pe[N]?.label??N}),oe="__system",Z,F=um(x.source,x.intent||"",A);if(F){oe=F.id,Z=F.kind;let N=R?.displayName||F.name;(!p.has(F.id)||R?.displayName)&&p.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else p.has("__system")||p.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(x.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let Yd=`${x.id}|${N.decided_by}`,dt=i.get(Yd),Cn=N.decided_at,In=dt?.resolved_at??null,fa=In===null,Qd=dt?.duration_ms??(fa?n-Cn:0),Zd=fa?"active":dt?.status==="error"||dt?.status==="fail"?"error":"completed",ee,Qe;if($)ee=$,Qe=O;else{let ha=y.get(N.agent_id);ha?(ee=ha,Qe=`${ha}/_${x.source}`):(ee="unmapped",Qe=`unmapped/_${x.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:mi(ee),projects:[]}),d.has(ee)||d.set(ee,new Set),d.get(ee).add(Qe),m.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:Qe,channelId:W,initiatorId:oe,initiatorKind:Z,subject:hm(x.subject),intent:x.intent||"",startedAt:Cn,resolvedAt:In,duration:Qd,active:fa,outcome:Zd,tokens:0,inputPreview:k,system:pm(N.agent_id,e),...L,starter:Q})}}let T=[...l.values()].map(x=>({...x,projects:[...d.get(x.id)||[]].sort()})).sort((x,A)=>x.id.localeCompare(A.id)),h=[],u=new Set;if(e){let x=e.business??{},A=R=>{let k=x.orgChart?.[R]?.role,L=k?x.roles?.[k]?.title:void 0;return typeof L=="string"&&L.trim()?L.trim():void 0};for(let[R,k]of Object.entries(e.agents||{})){let L={id:R,name:k.name||R,tier:k.tier==="claude-code"?"lead":"worker",model:k.model||"",role:k.systemPrompt?k.systemPrompt.split(/[.\n]/)[0].slice(0,60):k.tier||"",title:A(R)};h.push(L),u.add(R)}}for(let x of m)u.has(x.agentId)||(h.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),u.add(x.agentId));h.sort((x,A)=>x.id.localeCompare(A.id));let f=[],b=new Set;for(let[x,A]of Object.entries(Pe))f.push({id:x,label:A.label,color:A.color}),b.add(x);for(let x of c.values())b.has(x.id)||f.push(x);let v=[...p.values()];v.find(x=>x.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let E=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:T,agents:h,channels:f,initiators:v,dispatches:m,forges:{gitlab:typeof E=="string"?E:void 0,github:"https://github.com"}}}function an(t){let e=tn();if(!e)return null;try{return gi(e.db,bi(),t)}finally{e.close()}}function xi(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:c}of t){l.gitlab??=c.forges?.gitlab,l.github??=c.forges?.github,c.now>s&&(s=c.now),c.windowH>i&&(i=c.windowH);for(let p of c.clients){let m=e.get(p.id);if(!m)e.set(p.id,{...p,projects:[...p.projects]});else{let g=Array.from(new Set([...m.projects,...p.projects])).sort();e.set(p.id,{...m,projects:g})}}for(let p of c.agents)a.has(p.id)||a.set(p.id,p);for(let p of c.channels)n.has(p.id)||n.set(p.id,p);for(let p of c.initiators)r.has(p.id)||r.set(p.id,p);for(let p of c.dispatches){let m=gm(p);if(m.clientId!==p.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:mi(m.clientId),projects:[]}),m.projectId!==p.projectId){let g=e.get(m.clientId);g.projects.includes(m.projectId)||e.set(m.clientId,{...g,projects:[...g.projects,m.projectId].sort()})}o.push({...m,nodeId:d,id:`${d}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,c)=>d.id.localeCompare(c.id)),agents:[...a.values()].sort((d,c)=>d.id.localeCompare(c.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,c)=>c.startedAt-d.startedAt)}}function gm(t){if(t.clientId!=="unmapped")return t;let e=Ja(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:bt(e,a)}}async function ta(t){let e=ve?.channels?.gitlab,a=await ri(ni(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 bi(){return ve&&{...ve,people:tt(ve.people)}}function vi(t){ve=t}async function yi(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=tn();if(!n)return be(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=wi(parseInt(r.searchParams.get("hours")||"6",10));be(e,200,await ta(gi(n.db,bi(),o)))}catch(r){be(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var xm=5e3;async function nn(t,e,a,n=an){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
9127
+ `).all(L);for(let j of R)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,d=new Map,p=new Map,c=new Map,m=[],g=e?.business?.projects??[],k=e?.business?.contactMap??[],b=Ca(e?.business??{}),S=e?.people??[];for(let x of o){let A=null;try{A=JSON.parse(x.raw_json)}catch{}let L=Ei(x.source,A,k),_=Ti(x.source,A),R=xi(A),j=x.project??na(A,x.subject,_),$=null,O=null;L?($=L.client,O=L.project||`${L.client}/_chat`):j&&($=_t(j,g),O=j);let W=Cm(x.source,x.intent||"",A),ce=$e[W]||{label:W,color:"#6b7280"};p.has(W)||p.set(W,{id:W,label:ce.label,color:ce.color});let Q=yi({source:x.source,channel:W,raw:A,people:S,channelLabel:N=>$e[N]?.label??N}),oe="__system",Z,F=Mm(x.source,x.intent||"",A);if(F){oe=F.id,Z=F.kind;let N=L?.displayName||F.name;(!c.has(F.id)||L?.displayName)&&c.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else c.has("__system")||c.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(x.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let hc=`${x.id}|${N.decided_by}`,ft=i.get(hc),Nn=N.decided_at,Dn=ft?.resolved_at??null,va=Dn===null,gc=ft?.duration_ms??(va?n-Nn:0),xc=va?"active":ft?.status==="error"||ft?.status==="fail"?"error":"completed",ee,tt;if($)ee=$,tt=O;else{let ya=b.get(N.agent_id);ya?(ee=ya,tt=`${ya}/_${x.source}`):(ee="unmapped",tt=`unmapped/_${x.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:Si(ee),projects:[]}),d.has(ee)||d.set(ee,new Set),d.get(ee).add(tt),m.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:tt,channelId:W,initiatorId:oe,initiatorKind:Z,subject:Pm(x.subject),intent:x.intent||"",startedAt:Nn,resolvedAt:Dn,duration:gc,active:va,outcome:xc,tokens:0,inputPreview:_,system:Im(N.agent_id,e),...R,starter:Q})}}let T=[...l.values()].map(x=>({...x,projects:[...d.get(x.id)||[]].sort()})).sort((x,A)=>x.id.localeCompare(A.id)),h=[],u=new Set;if(e){let x=e.business??{},A=L=>{let _=x.orgChart?.[L]?.role,R=_?x.roles?.[_]?.title:void 0;return typeof R=="string"&&R.trim()?R.trim():void 0};for(let[L,_]of Object.entries(e.agents||{})){let R={id:L,name:_.name||L,tier:_.tier==="claude-code"?"lead":"worker",model:_.model||"",role:_.systemPrompt?_.systemPrompt.split(/[.\n]/)[0].slice(0,60):_.tier||"",title:A(L)};h.push(R),u.add(L)}}for(let x of m)u.has(x.agentId)||(h.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),u.add(x.agentId));h.sort((x,A)=>x.id.localeCompare(A.id));let f=[],v=new Set;for(let[x,A]of Object.entries($e))f.push({id:x,label:A.label,color:A.color}),v.add(x);for(let x of p.values())v.has(x.id)||f.push(x);let y=[...c.values()];y.find(x=>x.id==="__system")||y.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let E=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:T,agents:h,channels:f,initiators:y,dispatches:m,forges:{gitlab:typeof E=="string"?E:void 0,github:"https://github.com"}}}function ln(t){let e=sn();if(!e)return null;try{return Ai(e.db,Ii(),t)}finally{e.close()}}function Ci(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let c of p.clients){let m=e.get(c.id);if(!m)e.set(c.id,{...c,projects:[...c.projects]});else{let g=Array.from(new Set([...m.projects,...c.projects])).sort();e.set(c.id,{...m,projects:g})}}for(let c of p.agents)a.has(c.id)||a.set(c.id,c);for(let c of p.channels)n.has(c.id)||n.set(c.id,c);for(let c of p.initiators)r.has(c.id)||r.set(c.id,c);for(let c of p.dispatches){let m=$m(c);if(m.clientId!==c.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Si(m.clientId),projects:[]}),m.projectId!==c.projectId){let g=e.get(m.clientId);g.projects.includes(m.projectId)||e.set(m.clientId,{...g,projects:[...g.projects,m.projectId].sort()})}o.push({...m,nodeId:d,id:`${d}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,p)=>d.id.localeCompare(p.id)),agents:[...a.values()].sort((d,p)=>d.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,p)=>p.startedAt-d.startedAt)}}function $m(t){if(t.clientId!=="unmapped")return t;let e=en(t.inputPreview);if(!e)return t;let a=we?.business?.projects??[];return{...t,projectId:e,clientId:_t(e,a)}}async function oa(t){let e=we?.channels?.gitlab,a=await hi(fi(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 we=null;function Ii(){return we&&{...we,people:rt(we.people)}}function Mi(t){we=t}async function Ri(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=sn();if(!n)return ye(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Li(parseInt(r.searchParams.get("hours")||"6",10));ye(e,200,await oa(Ai(n.db,Ii(),o)))}catch(r){ye(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var jm=5e3;async function dn(t,e,a,n=ln){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
9128
9128
 
9129
- `);let r=new URL(t.url||"/","http://_"),o=wi(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
9129
+ `);let r=new URL(t.url||"/","http://_"),o=Li(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
9130
9130
 
9131
- `)}catch{i()}},25e3);try{for(;!s;){try{let c=await n(o),p=c&&await ta(c);if(s)break;p?(e.write(`event: snapshot
9132
- `),e.write(`data: ${JSON.stringify(p)}
9131
+ `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),c=p&&await oa(p);if(s)break;c?(e.write(`event: snapshot
9132
+ `),e.write(`data: ${JSON.stringify(c)}
9133
9133
 
9134
9134
  `)):e.write(`event: error
9135
9135
  data: ${JSON.stringify({error:"ledger not available"})}
9136
9136
 
9137
- `)}catch(c){e.write(`event: error
9138
- data: ${JSON.stringify({error:c?.message??String(c)})}
9137
+ `)}catch(p){e.write(`event: error
9138
+ data: ${JSON.stringify({error:p?.message??String(p)})}
9139
9139
 
9140
- `)}let d=Date.now();for(;!s&&Date.now()-d<xm;)await new Promise(c=>setTimeout(c,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function wi(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function bm(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Za(process.cwd(),".agentx/task-history",t,n);if(!en(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Za(process.cwd(),".agentx/task-history",t,o);return en(s)?ui(s,e,a):null}return ui(r,e,a)}function ui(t,e,a){let n=null,r=1/0;for(let o of im(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(lm(sm(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let c=Date.parse(i);if(!Number.isFinite(c))continue;l=c}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function ki(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 be(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=tn();if(!l)return be(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return be(e,404,{error:"event not found"}),!0;let c=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(!c)return be(e,404,{error:"decision not found"}),!0;let p=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(d.raw_json)}catch{}let g=hi(d.source,m),_=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)||g,y=null,S=null;if(c.agent_id){let v=bm(c.agent_id,c.decided_at);if(v){typeof v.responseText=="string"&&(y=v.responseText);let E=v.transcript;Array.isArray(E)&&(S=E.length)}}let T=ve?.business?.projects??[],h=ve?.business?.contactMap??[],u=_a(ve?.business??{}),f={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},b=fi(d.source,m,h);if(b)f={client:b.client,project:b.project||`${b.client}/_chat`,via:`contactMap (channel=${b.channel??"*"}${b.username?` username=${b.username}`:""}${b.chatId?` chatId=${b.chatId}`:""})`};else if(d.project||Zt(m,d.subject,g)){let v=d.project||Zt(m,d.subject,g);f={client:bt(v,T),project:v,via:d.project?`project namespace prefix (${v})`:`forge path in chat id / message (${v})`}}else if(c.agent_id){let v=u.get(c.agent_id);v&&(f={client:v,project:`${v}/_${d.source}`,via:`orgChart fallback (agent ${c.agent_id} reports up to a PM whose project belongs to ${v})`})}be(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:c.decided_by,agentId:c.agent_id,outcome:c.outcome,reason:c.reason,startedAt:c.decided_at,resolvedAt:p?.resolved_at??null,durationMs:p?.duration_ms??null,input:_,response:y,transcriptLen:S,resolutionStatus:p?.status??null,resultSummary:p?.result_summary??null,attribution:f})}catch(d){be(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as km,readFileSync as _m}from"fs";import{resolve as Si}from"path";ft();function _i(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=vm.replace(/__AGENT_ID__/g,H(e));return I({title:`AgentX \xB7 ${H(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${H(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:ym,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>${wm}</script>`})}var vm=`
9140
+ `)}let d=Date.now();for(;!s&&Date.now()-d<jm;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Li(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Om(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=rn(process.cwd(),".agentx/task-history",t,n);if(!on(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=rn(process.cwd(),".agentx/task-history",t,o);return on(s)?_i(s,e,a):null}return _i(r,e,a)}function _i(t,e,a){let n=null,r=1/0;for(let o of Em(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Tm(Sm(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function Pi(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 ye(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=sn();if(!l)return ye(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return ye(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 ye(e,404,{error:"decision not found"}),!0;let c=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(d.raw_json)}catch{}let g=Ti(d.source,m),k=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)||g,b=null,S=null;if(p.agent_id){let y=Om(p.agent_id,p.decided_at);if(y){typeof y.responseText=="string"&&(b=y.responseText);let E=y.transcript;Array.isArray(E)&&(S=E.length)}}let T=we?.business?.projects??[],h=we?.business?.contactMap??[],u=Ca(we?.business??{}),f={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},v=Ei(d.source,m,h);if(v)f={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(d.project||na(m,d.subject,g)){let y=d.project||na(m,d.subject,g);f={client:_t(y,T),project:y,via:d.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(p.agent_id){let y=u.get(p.agent_id);y&&(f={client:y,project:`${y}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${y})`})}ye(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:c?.resolved_at??null,durationMs:c?.duration_ms??null,input:k,response:b,transcriptLen:S,resolutionStatus:c?.status??null,resultSummary:c?.result_summary??null,attribution:f})}catch(d){ye(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Bm,readFileSync as qm}from"fs";import{resolve as ji}from"path";vt();function $i(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=Nm.replace(/__AGENT_ID__/g,H(e));return I({title:`AgentX \xB7 ${H(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${H(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Dm,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>${Hm}</script>`})}var Nm=`
9141
9141
  <!-- Breadcrumb -->
9142
9142
  <div class="ax-crumb">
9143
9143
  <a href="/admin">Settings</a>
@@ -9735,7 +9735,7 @@ data: ${JSON.stringify({error:c?.message??String(c)})}
9735
9735
  </div>
9736
9736
  </div>
9737
9737
  </div>
9738
- `,ym=`
9738
+ `,Dm=`
9739
9739
  /* Agent-specific layout + legacy styles for bits the migration left in
9740
9740
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
9741
9741
  * primitives live in components.css.ts. */
@@ -9854,7 +9854,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
9854
9854
 
9855
9855
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
9856
9856
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
9857
- `,wm=`
9857
+ `,Hm=`
9858
9858
  const $ = (id) => document.getElementById(id);
9859
9859
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
9860
9860
 
@@ -10713,15 +10713,15 @@ document.addEventListener('keydown', (e) => {
10713
10713
  /* ===== Boot ===== */
10714
10714
  initOptsToggles();
10715
10715
  loadAgent();
10716
- `;function Ei(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_i({agentId:a,peers:n,localToken:r}))}async function Ti(t,e,a){try{let n=t.method==="GET"?void 0:await Wm(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){aa(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,p={"GET ":()=>nt(i),"PATCH ":()=>Sm(i,n),"PATCH capability":()=>Am(i,n),"POST mcp":()=>Em(i,n),"DELETE mcp":()=>Tm(i,n),"GET identity":()=>Cm(i),"GET identity/file":()=>Im(i,String(o.path||"")),"PUT identity/file":()=>Mm(i,n),"GET skills":()=>Lm(i),"POST skills":()=>Rm(i,n),"DELETE skills":()=>Pm(i,n),"GET skills/tree":()=>$m(i,String(o.slug||"")),"GET skills/file":()=>jm(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Om(i,n),"GET skills/deps":()=>Nm(i,String(o.slug||"")),"POST skills/install":()=>Dm(i,n,t),"POST skills/deps":()=>Hm(i,n,t),"GET channels":()=>Bm(i),"GET activity":()=>qm(i,t),"GET handovers":()=>zm(i),"POST handovers":()=>Fm(i,n),"DELETE handovers":()=>Um(n)}[d];if(!p){aa(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let m=await p();aa(e,200,m)}catch(n){aa(e,400,{error:n?.message||"agent op failed"})}}function Ai(){let t=Si(process.cwd(),"agentx.json");return km(t)?JSON.parse(_m(t,"utf-8")):null}function V(t){let e=Ai();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 nt(t){let{def:e,cfg:a}=V(t),n=e.workspace?Be(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",wikiAbsorb:e.wiki?.absorb?.enabled!==!1,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 Sm(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},typeof e?.wikiAbsorb=="boolean"&&(Ot(r.agents[t],e.wikiAbsorb),a.wikiAbsorb=e.wikiAbsorb),`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function Em(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:nt(t)}}function Tm(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:nt(t)}}function Am(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function Cm(t){let{def:e}=V(t);return Be(e.workspace)}function Im(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Ct(a.workspace,e)}function Mm(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return It(n.workspace,a,String(e?.content??""))}function Lm(t){let{def:e}=V(t),a=Be(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Rm(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Mt(n.workspace,a,{title:e?.title,content:e?.content})}function Pm(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Lt(n.workspace,a)}function $m(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Lr(a.workspace,e),r=Rt(a.workspace,e);return{slug:e,tree:n,deps:r}}function jm(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Rr(n.workspace,e,a)}function Om(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return Pr(r.workspace,a,n,String(e?.content??""))}function Nm(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Rt(a.workspace,e)}async function Dm(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=Ci(e?.worker),{def:o}=V(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(`
10717
- `);return Ii(a,r,s,`install-${n}:${Date.now()}`)}async function Hm(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Ci(e?.worker),{def:o}=V(t),s=Rt(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=Si(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(`
10718
- `);return Ii(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Ci(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Ii(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),c;try{c=JSON.parse(d)}catch{c={content:d}}if(!l.ok)throw new Error(c?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:c?.taskId,content:c?.content,duration:c?.duration,error:c?.error}}function Bm(t){let e=Ai(),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 qm(t,e){try{let n=(X().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 rn(){return new Fn}function zm(t){let e=rn(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Fm(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=rn().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function Um(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:rn().remove(e,a,n)?"Released":"No active handover for that chat"}}function aa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Wm(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 $e={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 Mi=[{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 on(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify($e)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10716
+ `;function Oi(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($i({agentId:a,peers:n,localToken:r}))}async function Ni(t,e,a){try{let n=t.method==="GET"?void 0:await cf(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){sa(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,c={"GET ":()=>st(i),"PATCH ":()=>zm(i,n),"PATCH capability":()=>Wm(i,n),"POST mcp":()=>Fm(i,n),"DELETE mcp":()=>Um(i,n),"GET identity":()=>Gm(i),"GET identity/file":()=>Xm(i,String(o.path||"")),"PUT identity/file":()=>Km(i,n),"GET skills":()=>Jm(i),"POST skills":()=>Vm(i,n),"DELETE skills":()=>Ym(i,n),"GET skills/tree":()=>Qm(i,String(o.slug||"")),"GET skills/file":()=>Zm(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>ef(i,n),"GET skills/deps":()=>tf(i,String(o.slug||"")),"POST skills/install":()=>af(i,n,t),"POST skills/deps":()=>nf(i,n,t),"GET channels":()=>rf(i),"GET activity":()=>of(i,t),"GET handovers":()=>sf(i),"POST handovers":()=>lf(i,n),"DELETE handovers":()=>df(n)}[d];if(!c){sa(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let m=await c();sa(e,200,m)}catch(n){sa(e,400,{error:n?.message||"agent op failed"})}}function Di(){let t=ji(process.cwd(),"agentx.json");return Bm(t)?JSON.parse(qm(t,"utf-8")):null}function V(t){let e=Di();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 st(t){let{def:e,cfg:a}=V(t),n=e.workspace?Fe(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",wikiAbsorb:e.wiki?.absorb?.enabled!==!1,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 zm(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},typeof e?.wikiAbsorb=="boolean"&&(Ht(r.agents[t],e.wikiAbsorb),a.wikiAbsorb=e.wikiAbsorb),`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:st(t)}}function Fm(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:st(t)}}function Um(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:st(t)}}function Wm(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:st(t)}}function Gm(t){let{def:e}=V(t);return Fe(e.workspace)}function Xm(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Rt(a.workspace,e)}function Km(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return Lt(n.workspace,a,String(e?.content??""))}function Jm(t){let{def:e}=V(t),a=Fe(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Vm(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Pt(n.workspace,a,{title:e?.title,content:e?.content})}function Ym(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return $t(n.workspace,a)}function Qm(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Fr(a.workspace,e),r=jt(a.workspace,e);return{slug:e,tree:n,deps:r}}function Zm(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Ur(n.workspace,e,a)}function ef(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return Wr(r.workspace,a,n,String(e?.content??""))}function tf(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return jt(a.workspace,e)}async function af(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=Hi(e?.worker),{def:o}=V(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(`
10717
+ `);return Bi(a,r,s,`install-${n}:${Date.now()}`)}async function nf(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Hi(e?.worker),{def:o}=V(t),s=jt(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=ji(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(`
10718
+ `);return Bi(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Hi(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Bi(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),p;try{p=JSON.parse(d)}catch{p={content:d}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function rf(t){let e=Di(),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 of(t,e){try{let n=(X().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 cn(){return new Qn}function sf(t){let e=cn(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function lf(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=cn().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function df(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:cn().remove(e,a,n)?"Released":"No active handover for that chat"}}function sa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function cf(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 je={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 qi=[{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 pn(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(je)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10719
10719
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
10720
10720
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
10721
10721
  <section id="statstrip" class="ax-statstrip"></section>
10722
10722
  <main id="grid" class="ax-live__body"></main>
10723
10723
  </div>
10724
- `;return I({title:`${$e.brand} \xB7 ${$e.subtitle}`,activeTab:"live",subtitle:$e.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Gm,scripts:e+`<script>${Xm}</script>`,headExtras:`<script>
10724
+ `;return I({title:`${je.brand} \xB7 ${je.subtitle}`,activeTab:"live",subtitle:je.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:pf,scripts:e+`<script>${uf}</script>`,headExtras:`<script>
10725
10725
  // rightExtras for the topbar are injected at runtime \u2014 they reference
10726
10726
  // IDs (#ts, #conn-dot) that the script below addresses directly.
10727
10727
  document.addEventListener('DOMContentLoaded', () => {
@@ -10732,7 +10732,7 @@ loadAgent();
10732
10732
  extras.innerHTML = ${JSON.stringify(a)};
10733
10733
  right.insertBefore(extras, right.firstChild);
10734
10734
  });
10735
- </script>`})}var Gm=`
10735
+ </script>`})}var pf=`
10736
10736
  /* --- Page frame --- */
10737
10737
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
10738
10738
 
@@ -10953,7 +10953,7 @@ loadAgent();
10953
10953
  border-top-color: var(--ax-accent); border-radius: 50%;
10954
10954
  animation: ax-spin 800ms linear infinite; display: inline-block;
10955
10955
  }
10956
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,Xm=`
10956
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,uf=`
10957
10957
  'use strict';
10958
10958
 
10959
10959
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -11600,7 +11600,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11600
11600
  });
11601
11601
  }
11602
11602
 
11603
- `;var Li=`
11603
+ `;var zi=`
11604
11604
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
11605
11605
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
11606
11606
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -11774,7 +11774,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11774
11774
  .mx-summary{max-width:56vw}
11775
11775
  }
11776
11776
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
11777
- `;var Ri=`<script>
11777
+ `;var Fi=`<script>
11778
11778
  window.MX=(function(){
11779
11779
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
11780
11780
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -11883,7 +11883,7 @@ window.MX=(function(){
11883
11883
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
11884
11884
  setHealth:setHealth,get:get};
11885
11885
  })();
11886
- </script>`;var Pi=`<script>
11886
+ </script>`;var Ui=`<script>
11887
11887
  window.MXD=(function(){
11888
11888
  function el(id){return document.getElementById(id)}
11889
11889
  function tz(){return -new Date().getTimezoneOffset()}
@@ -12097,7 +12097,7 @@ window.MXD=(function(){
12097
12097
 
12098
12098
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
12099
12099
  })();
12100
- </script>`;var $i=`<script>
12100
+ </script>`;var Wi=`<script>
12101
12101
  (function(){
12102
12102
  var LANES=[
12103
12103
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -12413,7 +12413,7 @@ window.MXD=(function(){
12413
12413
  window.addEventListener('scroll',hideTip,{passive:true});
12414
12414
  load();
12415
12415
  })();
12416
- </script>`;var ji=`<script>
12416
+ </script>`;var Gi=`<script>
12417
12417
  (function(){
12418
12418
  var showAll=document.getElementById('mx-show-all'),expanded=false;
12419
12419
  var esc=MX.esc;
@@ -12591,7 +12591,7 @@ window.MXD=(function(){
12591
12591
  }
12592
12592
  load();setInterval(load,5000);
12593
12593
  })();
12594
- </script>`;var Oi=`
12594
+ </script>`;var Xi=`
12595
12595
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
12596
12596
  .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}
12597
12597
  .mx-rt-wrap > .mx-empty{border:0}
@@ -12632,7 +12632,7 @@ window.MXD=(function(){
12632
12632
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
12633
12633
  .mx-rt-name{max-width:100%}
12634
12634
  }
12635
- `,Ni=`<script>
12635
+ `,Ki=`<script>
12636
12636
  (function(){
12637
12637
  var root=document.getElementById('mx-routines');
12638
12638
  var bar=document.getElementById('mx-rt-filter');
@@ -12759,7 +12759,7 @@ window.MXD=(function(){
12759
12759
  syncBar();
12760
12760
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
12761
12761
  })();
12762
- </script>`;var Di=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Hi=`<script>
12762
+ </script>`;var Ji=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Vi=`<script>
12763
12763
  (function(){
12764
12764
  var root=document.getElementById('mx-feed');
12765
12765
  if(!root)return;
@@ -12834,12 +12834,12 @@ window.MXD=(function(){
12834
12834
  }
12835
12835
  load();setInterval(load,5000);
12836
12836
  })();
12837
- </script>`;var ae={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 ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Km=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Jm=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Vm=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Bi(t){let e=pe({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Pt([{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">
12837
+ </script>`;var ae={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 ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var mf=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],ff=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],hf=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Yi(t){let e=ue({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Ot([{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">
12838
12838
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
12839
- ${Jm.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("")}
12839
+ ${ff.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("")}
12840
12840
  </div>
12841
12841
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
12842
- ${Vm.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12842
+ ${hf.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12843
12843
  </div>
12844
12844
  </div>
12845
12845
  <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">
@@ -12892,7 +12892,7 @@ window.MXD=(function(){
12892
12892
  <section class="mx-section" aria-labelledby="mx-routines-title">
12893
12893
  ${ne(ae.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>')}
12894
12894
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
12895
- ${Km.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12895
+ ${mf.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12896
12896
  </div>
12897
12897
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
12898
12898
  </section>
@@ -12900,7 +12900,7 @@ window.MXD=(function(){
12900
12900
  <section class="mx-section" aria-labelledby="mx-feed-title">
12901
12901
  ${ne(ae.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>')}
12902
12902
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
12903
- ${Di.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12903
+ ${Ji.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12904
12904
  </div>
12905
12905
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
12906
12906
  </section>
@@ -12933,7 +12933,7 @@ window.MXD=(function(){
12933
12933
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
12934
12934
  </header>
12935
12935
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
12936
- </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Li+Oi,scripts:Ri+Ym+Pi+$i+Ni+ji+Hi})}var Ym=`<script>
12936
+ </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:zi+Xi,scripts:Fi+gf+Ui+Wi+Ki+Gi+Vi})}var gf=`<script>
12937
12937
  (function(){
12938
12938
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
12939
12939
  var range=document.getElementById('mx-range');
@@ -12961,10 +12961,10 @@ window.MXD=(function(){
12961
12961
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
12962
12962
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
12963
12963
  })();
12964
- </script>`;function qi(t){let e=pe({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
12964
+ </script>`;function Qi(t){let e=ue({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
12965
12965
  <div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
12966
12966
  <ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
12967
- <p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent &lt;id&gt;</code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return I({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:Qm,scripts:`<script>${Zm}</script>`})}var Qm=`
12967
+ <p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent &lt;id&gt;</code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return I({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:xf,scripts:`<script>${bf}</script>`})}var xf=`
12968
12968
  .gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
12969
12969
  .gm-empty { color: var(--ax-text-2); }
12970
12970
  .gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
@@ -12982,7 +12982,7 @@ window.MXD=(function(){
12982
12982
  .gm-msg { min-height: 1.4em; margin: 8px 0 0; }
12983
12983
  .gm-msg.is-bad { color: var(--ax-red-ink); }
12984
12984
  .gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
12985
- `,Zm=`
12985
+ `,bf=`
12986
12986
  (function () {
12987
12987
  var list = document.getElementById('gm-list');
12988
12988
  var msg = document.getElementById('gm-msg');
@@ -13029,7 +13029,7 @@ window.MXD=(function(){
13029
13029
  load();
13030
13030
  setInterval(load, 30000);
13031
13031
  })();
13032
- `;async function zi(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return ef(s,e.days)}function ef(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,c=0,p=0,m=0,g=0,_=0;for(let{node:S,data:T}of t)if(T){a.runs+=T.totals.runs,a.errors+=T.totals.errors,a.hours+=T.totals.hours,a.agents+=T.totals.agents,a.threads+=T.totals.threads;for(let h of T.days){let u=n.get(h.day)||{day:h.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let f of["cron","workflow","direct"])u[f][0]+=h[f]?.[0]||0,u[f][1]+=h[f]?.[1]||0;n.set(h.day,u)}for(let h of T.origins){let u=r.get(h.channel)||{channel:h.channel,runs:0,errors:0,hours:0};u.runs+=h.runs,u.errors+=h.errors,u.hours+=h.hours,r.set(h.channel,u)}for(let h of T.causes){let u=o.get(h.cause)||{cause:h.cause,count:0,agents:[],example:""};u.count+=h.count;for(let f of h.agents)u.agents.includes(f)||u.agents.push(f);u.example||(u.example=h.example),o.set(h.cause,u)}for(let h of T.rotations.byReason)s.set(h.reason,(s.get(h.reason)||0)+h.count);d+=T.rotations.total,c+=T.rotations.tokenSum||0,p+=T.rotations.tokenSamples||0,m=Math.max(m,T.rotations.maxTokens),g+=T.retention.traces,_+=T.retention.tracesWithSteps;for(let h of T.jobs)i.push({...h,node:S.name,nodeUrl:S.url});for(let h of T.threads)l.push({...h,node:S.name,nodeUrl:S.url})}let y=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:y.length?Math.min(...y):Date.now()-e*864e5,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,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,T)=>S.day.localeCompare(T.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,T)=>T.runs-S.runs),causes:[...o.values()].sort((S,T)=>T.count-S.count),jobs:i.sort((S,T)=>T.hours-S.hours),threads:l.sort((S,T)=>T.lastAt-T.firstAt-(S.lastAt-S.firstAt)||T.runs-S.runs),rotations:{total:d,byReason:[...s.entries()].map(([S,T])=>({reason:S,count:T})).sort((S,T)=>T.count-S.count),tokenSum:c,tokenSamples:p,maxTokens:m},retention:{traces:g,tracesWithSteps:_}}}async function Fi(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 Ui(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return tf(s,e.day)}function tf(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function Wi(t={}){let e=`
13032
+ `;async function Zi(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return vf(s,e.days)}function vf(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,p=0,c=0,m=0,g=0,k=0;for(let{node:S,data:T}of t)if(T){a.runs+=T.totals.runs,a.errors+=T.totals.errors,a.hours+=T.totals.hours,a.agents+=T.totals.agents,a.threads+=T.totals.threads;for(let h of T.days){let u=n.get(h.day)||{day:h.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let f of["cron","workflow","direct"])u[f][0]+=h[f]?.[0]||0,u[f][1]+=h[f]?.[1]||0;n.set(h.day,u)}for(let h of T.origins){let u=r.get(h.channel)||{channel:h.channel,runs:0,errors:0,hours:0};u.runs+=h.runs,u.errors+=h.errors,u.hours+=h.hours,r.set(h.channel,u)}for(let h of T.causes){let u=o.get(h.cause)||{cause:h.cause,count:0,agents:[],example:""};u.count+=h.count;for(let f of h.agents)u.agents.includes(f)||u.agents.push(f);u.example||(u.example=h.example),o.set(h.cause,u)}for(let h of T.rotations.byReason)s.set(h.reason,(s.get(h.reason)||0)+h.count);d+=T.rotations.total,p+=T.rotations.tokenSum||0,c+=T.rotations.tokenSamples||0,m=Math.max(m,T.rotations.maxTokens),g+=T.retention.traces,k+=T.retention.tracesWithSteps;for(let h of T.jobs)i.push({...h,node:S.name,nodeUrl:S.url});for(let h of T.threads)l.push({...h,node:S.name,nodeUrl:S.url})}let b=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:b.length?Math.min(...b):Date.now()-e*864e5,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,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,T)=>S.day.localeCompare(T.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,T)=>T.runs-S.runs),causes:[...o.values()].sort((S,T)=>T.count-S.count),jobs:i.sort((S,T)=>T.hours-S.hours),threads:l.sort((S,T)=>T.lastAt-T.firstAt-(S.lastAt-S.firstAt)||T.runs-S.runs),rotations:{total:d,byReason:[...s.entries()].map(([S,T])=>({reason:S,count:T})).sort((S,T)=>T.count-S.count),tokenSum:p,tokenSamples:c,maxTokens:m},retention:{traces:g,tracesWithSteps:k}}}async function el(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 tl(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return yf(s,e.day)}function yf(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function al(t={}){let e=`
13033
13033
  <select id="boardPicker" title="Switch board"></select>
13034
13034
  <div class="search">
13035
13035
  <span class="icon">\u2315</span>
@@ -13130,7 +13130,7 @@ window.MXD=(function(){
13130
13130
  </footer>
13131
13131
  </div>
13132
13132
  </div>
13133
- <script src="/sortable.min.js"></script>`;return I({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:af,scripts:`<script>${nf}</script>`,headExtras:`<script>
13133
+ <script src="/sortable.min.js"></script>`;return I({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:wf,scripts:`<script>${kf}</script>`,headExtras:`<script>
13134
13134
  // The boards page has its own connection dot + wants body height:100%
13135
13135
  // for the full-viewport kanban layout. Inject the dot into the topbar
13136
13136
  // and override body height at runtime so the shared shell doesn't
@@ -13146,7 +13146,7 @@ window.MXD=(function(){
13146
13146
  right.insertBefore(dot, right.firstChild);
13147
13147
  }
13148
13148
  });
13149
- </script>`})}var af=`
13149
+ </script>`})}var wf=`
13150
13150
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
13151
13151
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
13152
13152
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -13399,7 +13399,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
13399
13399
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
13400
13400
  .draft-box .draft-row .hint.err { color: var(--red); }
13401
13401
  .draft-box .draft-row .hint.ok { color: var(--green); }
13402
- `,nf=`
13402
+ `,kf=`
13403
13403
  'use strict';
13404
13404
  const state = {
13405
13405
  boards: [], current: null, items: {},
@@ -14452,9 +14452,9 @@ function appendEvents(events) {
14452
14452
  }
14453
14453
 
14454
14454
  loadBoards().catch(e => toast('Init failed: ' + e.message));
14455
- `;function Gi(t={}){let a=`<h1>Plain-English glossary</h1>
14455
+ `;function nl(t={}){let a=`<h1>Plain-English glossary</h1>
14456
14456
  <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>
14457
- ${Mi.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${H(n.alias)}</span>`:"";return`<article class="term"><h3>${H(n.term)}${r}</h3><p>${H(n.definition)}</p></article>`}).join("")}`;return I({title:`${$e.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:rf})}var rf=`
14457
+ ${qi.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${H(n.alias)}</span>`:"";return`<article class="term"><h3>${H(n.term)}${r}</h3><p>${H(n.definition)}</p></article>`}).join("")}`;return I({title:`${je.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:_f})}var _f=`
14458
14458
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
14459
14459
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
14460
14460
  .lead {
@@ -14484,7 +14484,7 @@ article.term .alias {
14484
14484
  }
14485
14485
  article.term p {
14486
14486
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
14487
- }`;function Xi(t={}){let e=`<div class="ax-wf__root">
14487
+ }`;function rl(t={}){let e=`<div class="ax-wf__root">
14488
14488
  <aside class="ax-wf__list">
14489
14489
  <header>
14490
14490
  <h2>Workflows</h2>
@@ -14582,7 +14582,7 @@ article.term p {
14582
14582
  </aside>
14583
14583
  </div>
14584
14584
 
14585
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return I({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:of,scripts:`<script>${z({workflowHealth:er})}${sf}</script>`})}var of=`
14585
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return I({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Sf,scripts:`<script>${z({workflowHealth:dr})}${Ef}</script>`})}var Sf=`
14586
14586
  .ax-wf__root {
14587
14587
  display: grid;
14588
14588
  grid-template-columns: 340px 1fr;
@@ -15000,7 +15000,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15000
15000
  font-size: 12px; z-index: 50;
15001
15001
  }
15002
15002
  .hint { color: var(--ax-muted); font-size: 11px; }
15003
- `,sf=`
15003
+ `,Ef=`
15004
15004
  (() => {
15005
15005
  const $ = (sel) => document.querySelector(sel)
15006
15006
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -15886,7 +15886,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15886
15886
  setInterval(refresh, 15000)
15887
15887
  })
15888
15888
  })();
15889
- `;function Ki(t={}){let e=`<div class="ax-proc__root">
15889
+ `;function ol(t={}){let e=`<div class="ax-proc__root">
15890
15890
  <header class="ax-proc__header">
15891
15891
  <h1>Procedures</h1>
15892
15892
  <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>
@@ -15930,7 +15930,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15930
15930
  <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>
15931
15931
  <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>
15932
15932
  </section>
15933
- </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:lf,scripts:`<script>${df}</script>`})}var lf=`
15933
+ </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Tf,scripts:`<script>${Af}</script>`})}var Tf=`
15934
15934
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
15935
15935
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
15936
15936
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -15956,7 +15956,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15956
15956
  .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); }
15957
15957
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
15958
15958
  .ax-proc__link:hover { text-decoration: underline; }
15959
- `,df=`
15959
+ `,Af=`
15960
15960
  (function(){
15961
15961
  function $(sel){ return document.querySelector(sel) }
15962
15962
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -16056,7 +16056,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16056
16056
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
16057
16057
  else bootAll()
16058
16058
  })();
16059
- `;function Ji(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
16059
+ `;function sl(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
16060
16060
  data-task-id="${H(t.taskId)}"
16061
16061
  data-agent-id="${H(t.agentId)}"
16062
16062
  data-node-url="${H(t.nodeUrl)}"
@@ -16099,7 +16099,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16099
16099
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
16100
16100
  </div>
16101
16101
  </footer>
16102
- </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:cf,scripts:`<script>${pf}</script>`})}var cf=`
16102
+ </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Cf,scripts:`<script>${If}</script>`})}var Cf=`
16103
16103
  /* The shell gives <main> no padding, so page content butted straight against
16104
16104
  the sticky topbar. Breathe. */
16105
16105
  .ax-task-page {
@@ -16241,7 +16241,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16241
16241
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
16242
16242
  }
16243
16243
 
16244
- `,pf=`
16244
+ `,If=`
16245
16245
  (function () {
16246
16246
  var root = document.querySelector('.ax-task-page');
16247
16247
  if (!root) return;
@@ -16626,7 +16626,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16626
16626
  });
16627
16627
 
16628
16628
  })();
16629
- `;function Vi(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16629
+ `;function il(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16630
16630
  data-agent-id="${H(t.agentId)}"
16631
16631
  data-agent-name="${H(e)}"
16632
16632
  data-node-url="${H(t.nodeUrl)}">
@@ -16655,7 +16655,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16655
16655
  <div class="ax-history__list" id="hist-list">
16656
16656
  <div class="ax-history__empty">loading\u2026</div>
16657
16657
  </div>
16658
- </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:uf,scripts:`<script>${mf}</script>`})}var uf=`
16658
+ </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Mf,scripts:`<script>${Rf}</script>`})}var Mf=`
16659
16659
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
16660
16660
  flush against the sticky topbar. */
16661
16661
  .ax-history {
@@ -16707,7 +16707,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16707
16707
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
16708
16708
  }
16709
16709
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
16710
- `,mf=`
16710
+ `,Rf=`
16711
16711
  (function () {
16712
16712
  var root = document.querySelector('.ax-history');
16713
16713
  if (!root) return;
@@ -16807,31 +16807,31 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16807
16807
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
16808
16808
  });
16809
16809
  })();
16810
- `;function Qi(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"])?P(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 Xe(t,e,l=>Yi(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:hf(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return P(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Xe(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:d})}):P(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"])?P(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Xe(t,e,l=>{try{let d=a.layouts.save(s,l);return P(e,200,{layout:d})}catch(d){return P(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Xe(t,e,l=>{let d=wa.safeParse(l);if(!d.success)return P(e,200,{ok:!1,issues:d.error.issues.map(p=>({path:p.path.join("."),message:p.message}))});let c=ka(d.data).map(p=>({path:"",message:p}));return P(e,200,{ok:c.length===0,issues:c,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?P(e,200,{workflow:l}):P(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Xe(t,e,c=>Yi(e,a,c,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var ff=["mesh"];function Yi(t,e,a,n){let r=wa.safeParse(a);if(!r.success)return P(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=ka(o);if(s.length>0)return P(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return P(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return P(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,d=e.store.get(n.id);if(d)for(let c of ff)!(c in l)&&c in d&&(o[c]=d[c])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),c=l?.yamlPath,p=!!c||/yaml round-trip failed/.test(d);return P(t,p?409:500,{error:p?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:p?"yaml-authored":"save-failed",...c?{path:c}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function hf(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,c=r.get("summary")==="1"||r.get("summary")==="true",p=a.runs.list({workflowId:d,limit:l});if(!c)return P(e,200,{runs:p});let m=p.map(g=>({id:g.id,workflowId:g.workflowId,workflowVersion:g.workflowVersion,homeNode:g.homeNode,status:g.status,pending:g.pending,entityRef:g.entityRef,history:(g.history||[]).slice(-5),parentRunId:g.parentRunId,parentNodeId:g.parentNodeId,rootRunId:g.rootRunId,depth:g.depth,createdAt:g.createdAt,updatedAt:g.updatedAt}));return P(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Xe(t,e,d=>{let c=d?.status;return c!=="paused"&&c!=="running"&&c!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,c)?P(e,200,{ok:!0,runId:l,status:c}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return gf(t,e,a,l);let d=a.runs.get(l);return d?P(e,200,{run:d}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function gf(t,e,a,n){let r=a.runs.get(n);if(!r)return P(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)}
16810
+ `;function dl(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"])?P(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 Ve(t,e,l=>ll(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Pf(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return P(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Ve(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:d})}):P(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"])?P(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Ve(t,e,l=>{try{let d=a.layouts.save(s,l);return P(e,200,{layout:d})}catch(d){return P(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ve(t,e,l=>{let d=Ta.safeParse(l);if(!d.success)return P(e,200,{ok:!1,issues:d.error.issues.map(c=>({path:c.path.join("."),message:c.message}))});let p=Aa(d.data).map(c=>({path:"",message:c}));return P(e,200,{ok:p.length===0,issues:p,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?P(e,200,{workflow:l}):P(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ve(t,e,p=>ll(e,a,p,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var Lf=["mesh"];function ll(t,e,a,n){let r=Ta.safeParse(a);if(!r.success)return P(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=Aa(o);if(s.length>0)return P(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return P(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return P(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,d=e.store.get(n.id);if(d)for(let p of Lf)!(p in l)&&p in d&&(o[p]=d[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),p=l?.yamlPath,c=!!p||/yaml round-trip failed/.test(d);return P(t,c?409:500,{error:c?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:c?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function Pf(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",c=a.runs.list({workflowId:d,limit:l});if(!p)return P(e,200,{runs:c});let m=c.map(g=>({id:g.id,workflowId:g.workflowId,workflowVersion:g.workflowVersion,homeNode:g.homeNode,status:g.status,pending:g.pending,entityRef:g.entityRef,history:(g.history||[]).slice(-5),parentRunId:g.parentRunId,parentNodeId:g.parentNodeId,rootRunId:g.rootRunId,depth:g.depth,createdAt:g.createdAt,updatedAt:g.updatedAt}));return P(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Ve(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?P(e,200,{ok:!0,runId:l,status:p}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return $f(t,e,a,l);let d=a.runs.get(l);return d?P(e,200,{run:d}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function $f(t,e,a,n){let r=a.runs.get(n);if(!r)return P(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)}
16811
16811
 
16812
- `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(c);try{e.end()}catch{}};t.on("close",s);let i=p=>{if(!o)try{e.write(`data: ${JSON.stringify(p)}
16812
+ `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=c=>{if(!o)try{e.write(`data: ${JSON.stringify(c)}
16813
16813
 
16814
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,c=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==d&&(d=p.updatedAt,i(p))},2e3);return!0}function Xe(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){P(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{P(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{P(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>P(e,400,{error:"body read failed",message:r.message})),!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as lh}from"fs";import{createRequire as dh}from"module";On();var el=50,xf=280;async function tl(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=bf(await o.recent(el))}catch(d){l=String(d?.message||"unreachable").slice(0,200)}return Zi(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Zi(e,404,{error:"not found"})}function al(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(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)return null;if(n.relayTo)return wt();let r=ut();return r?new sr(r):null}}}function bf(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:sn(typeof n.summary=="string"?n.summary:"",xf),by:typeof n.agentId=="string"?sn(n.agentId,100):null,node:sn(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,el)}function sn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Zi(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var vf="operator",yf=50,nl=4,rl=500;function wf(t){let e={channel:"app",chatId:t.chatId,sender:vf,...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 ol(t,e,a,n){let{path:r,body:o}=wf(e),s="",i=!1,l=[],d=new Map,c=(p,m,g)=>{let _=p!=="done",y=i?{text:xt(m,_),artifacts:[]}:gt(m,ce.perMessage,_),{cleanText:S,ui:T}=p==="done"?vt(y.text):{cleanText:y.text,ui:void 0},h=i?void 0:ln(T);return{status:p,text:S,tools:l,files:y.artifacts,...h?{ui:h}:{},...g?{error:g}:{}}};try{let p=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let m=await p.json().then(g=>g?.error).catch(()=>"");return c("error",s,m||`AgentX answered HTTP ${p.status}.`)}for await(let m of _f(p.body)){n(m.event,m.data);let g=m.data??{};if(m.event==="start")i=g.rich===!1;else if(m.event==="text"&&typeof g.text=="string")s+=g.text;else if(m.event==="tool"&&g.status==="start"&&l.length<yf){let _={name:String(g.name||"tool").slice(0,80),...g.arg?{arg:String(g.arg).slice(0,80)}:{}};l.push(_),g.id&&d.set(String(g.id),_)}else if(m.event==="tool"&&g.status==="result"&&g.error===!0&&d.has(String(g.id)))d.get(String(g.id)).error=!0;else{if(m.event==="done")return c("done",typeof g.content=="string"&&g.content?g.content:s);if(m.event==="error")return c("error",s,kf(g.error))}}return a.aborted?c("stopped",s):c("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?c("stopped",s):c("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function kf(t){let e=String(t||"The agent could not answer.");return Un(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ln(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,nl).map(s=>s.slice(0,rl));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,nl).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,rl)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*_f(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,`
16814
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let c=a.runs.get(n);c&&c.updatedAt!==d&&(d=c.updatedAt,i(c))},2e3);return!0}function Ve(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){P(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{P(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{P(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>P(e,400,{error:"body read failed",message:r.message})),!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Th}from"fs";import{createRequire as Ah}from"module";var cl=4e3;async function pl(t,e,a,n,r){if(n==="GET"&&a==="/api/app/desk")return it(e,200,await r.board());if(n!=="POST"||a!=="/api/app/desk/reply")return!1;let o;try{o=await qe(t)}catch(d){return it(e,400,{error:d.message})}let s=typeof o.id=="string"?o.id.trim():"",i=typeof o.text=="string"?o.text.trim():"";if(!s||!i)return it(e,400,{error:"id and text are required"});if(i.length>cl)return it(e,400,{error:`the answer is longer than ${cl} characters`});let l=await r.reply(s,i);return it(e,l.status,l.body)}function it(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Wn();var ml=50,jf=280;async function fl(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=Of(await o.recent(ml))}catch(d){l=String(d?.message||"unreachable").slice(0,200)}return ul(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return ul(e,404,{error:"not found"})}function hl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(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)return null;if(n.relayTo)return Et();let r=xt();return r?new hr(r):null}}}function Of(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:un(typeof n.summary=="string"?n.summary:"",jf),by:typeof n.agentId=="string"?un(n.agentId,100):null,node:un(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,ml)}function un(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function ul(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Nf="operator",Df=50,gl=4,xl=500;function Hf(t){let e={channel:"app",chatId:t.chatId,sender:Nf,...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 bl(t,e,a,n){let{path:r,body:o}=Hf(e),s="",i=!1,l=[],d=new Map,p=(c,m,g)=>{let k=c!=="done",b=i?{text:kt(m,k),artifacts:[]}:wt(m,pe.perMessage,k),{cleanText:S,ui:T}=c==="done"?St(b.text):{cleanText:b.text,ui:void 0},h=i?void 0:mn(T);return{status:c,text:S,tools:l,files:b.artifacts,...h?{ui:h}:{},...g?{error:g}:{}}};try{let c=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(!c.ok||!c.body){let m=await c.json().then(g=>g?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${c.status}.`)}for await(let m of qf(c.body)){n(m.event,m.data);let g=m.data??{};if(m.event==="start")i=g.rich===!1;else if(m.event==="text"&&typeof g.text=="string")s+=g.text;else if(m.event==="tool"&&g.status==="start"&&l.length<Df){let k={name:String(g.name||"tool").slice(0,80),...g.arg?{arg:String(g.arg).slice(0,80)}:{}};l.push(k),g.id&&d.set(String(g.id),k)}else if(m.event==="tool"&&g.status==="result"&&g.error===!0&&d.has(String(g.id)))d.get(String(g.id)).error=!0;else{if(m.event==="done")return p("done",typeof g.content=="string"&&g.content?g.content:s);if(m.event==="error")return p("error",s,Bf(g.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(c){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${c?.message||c}`)}}function Bf(t){let e=String(t||"The agent could not answer.");return Zn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function mn(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,gl).map(s=>s.slice(0,xl));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,gl).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,xl)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*qf(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,`
16815
16815
  `);let s;for(;(s=n.indexOf(`
16816
16816
 
16817
- `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let c of i.split(`
16818
- `))c.startsWith("event:")?l=c.slice(6).trim():c.startsWith("data:")&&d.push(c.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
16819
- `))}}catch{}}}}finally{e.releaseLock()}}var na=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];plain=!1;orphaned=!1;startedAt=Date.now();listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="start"&&(this.plain=a?.rich===!1),e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}watched(){return this.listeners.size>0}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
16817
+ `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
16818
+ `))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&d.push(p.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
16819
+ `))}}catch{}}}}finally{e.releaseLock()}}var ia=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];plain=!1;orphaned=!1;startedAt=Date.now();listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="start"&&(this.plain=a?.rich===!1),e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}watched(){return this.listeners.size>0}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
16820
16820
  data: ${JSON.stringify(s)}
16821
16821
 
16822
16822
  `)},r=setInterval(()=>{a()&&e.write(`: ping
16823
16823
 
16824
- `)},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 il(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=Sf(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:dn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function dn(t,e=120){for(let a of t.split(`
16825
- `)){let n=ll(a);if(n)return cn(n,e)}return""}function Sf(t,e=120){let a=t.split(`
16826
- `).map(ll).filter(Boolean);return a.length?cn(a[a.length-1],e):""}function ll(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function cn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var ra=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 oa(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var sl=140;function sa(t,e,a,n,r){let o=a==="error"?`Could not answer: ${dn(r||"",sl-18)||"something went wrong."}`:dn(n,sl)||"Answered.";return{deviceId:t,title:cn(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var cl=8e3,Tf=/^[A-Za-z0-9_.:-]{1,64}$/,je=new Map,pn=new Map,fn=new ra;function pl(){return fn}async function ul(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??fn;if(n==="GET"&&a==="/api/app/agents")return B(e,200,{nodes:await ml(o)});let i=o.store();if(!i)return B(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),B(e,200,{conversations:il(r.id,If(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),B(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return B(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let c=i.get(r.id,decodeURIComponent(l[1]));if(!c)return B(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,c.id);let p=je.get(c.id);return B(e,200,{...c,running:!!p,...p?{partial:{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let c=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=c&&je.get(c.id);if(!c||!p)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,c.id),fl(e);let{id:m,title:g,node:_,nodeName:y,agent:S,agentName:T}=c;return e.write(un("conversation",{id:m,title:g,node:_,nodeName:y,agent:S,agentName:T})),e.write(un("resume",{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return B(e,404,{error:"not found"});let d;try{d=await yt(t,64*1024)}catch(c){return B(e,400,{error:c.message})}if(a==="/api/app/chat/stop"){let c=i.get(r.id,String(d.conversationId??""));if(!c)return B(e,404,{error:"no such conversation"});let p=je.get(c.id);return p?(p.ac.abort(),mn(c,o,r.name),B(e,200,{stopped:!0})):await mn(c,o,r.name)?B(e,200,{stopped:!0}):B(e,404,{error:"nothing is running in this conversation"})}return await Cf(e,d,r,i,o),!0}function Af(t,e,a){let n=Ke(e.url),r=new Set,o=[];for(let s of t){let i=Ke(s.url),l=a.find(p=>Ke(p.peerUrl)===i);l&&r.add(l.peer);let d=i===n,c=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:c.map(p=>{let m=Array.isArray(p.runningTasks)?p.runningTasks.length:0;return{id:p.id,name:p.name||p.id,busy:m>0||(p.active??0)>0,running:m,...p.color?{color:p.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 ml(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Af(e.nodes,t.daemon,a)}async function Cf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>cl){B(t,400,{error:`message must be 1\u2013${cl} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){B(t,404,{error:"no such conversation"});return}}else{let _=typeof e.node=="string"?e.node:"",y=typeof e.agent=="string"?e.agent:"";if(!Tf.test(y)){B(t,400,{error:"pick an agent"});return}let S=(await ml(r)).find(h=>h.target===_);if(!S){B(t,400,{error:`unknown node "${_}"`});return}if(!S.online){B(t,409,{error:`${S.name} is offline`});return}let T=S.agents.find(h=>h.id===y);if(!T){B(t,400,{error:`no agent "${y}" on ${S.name}`});return}s=n.create(a.id,{node:_,nodeName:S.name,agent:y,agentName:T.name,...T.color?{color:T.color}:{}},o)}if(je.has(s.id)){B(t,409,{error:"The agent is still answering in this conversation."});return}let i=new na(r.orphanLimitMs??18e5);je.set(s.id,i);let{id:l,title:d,node:c,nodeName:p,agent:m,agentName:g}=s;pn.set(l,{id:l,deviceId:a.id,title:d,agent:m,...g?{agentName:g}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),fl(t),t.write(un("conversation",{id:l,title:d,node:c,nodeName:p,agent:m,agentName:g})),i.attach(t);try{let _=e.spoken===!0,y=await ol(r.daemon,{node:c,agent:m,message:o,chatId:`app:${l}`,spoken:_},i.ac.signal,(u,f)=>i.broadcast(u,f));i.orphaned&&(y.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,mn(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:y.text,status:y.status,at:Date.now(),...y.error?{error:y.error}:{},...y.ui?{ui:y.ui}:{},...y.tools.length?{tools:y.tools}:{}},y.files)??[];i.broadcast("final",{status:y.status,content:y.text,...y.error?{error:y.error}:{},...y.ui?{ui:y.ui}:{},...S.length?{files:S}:{}});let T=i.watched();T&&n.markRead(a.id,l);let h={status:y.status,attached:T,appOpen:(r.presence??fn).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&oa(h)&&r.notifyFinish(sa(a.id,s,y.status,y.text,y.error)).catch(()=>{})}finally{je.delete(l),pn.delete(l),i.finish()}}function If(){let t=[];for(let[e,a]of pn){let n=je.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function fl(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function un(t,e){return`event: ${t}
16824
+ `)},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 yl(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=zf(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:fn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function fn(t,e=120){for(let a of t.split(`
16825
+ `)){let n=wl(a);if(n)return hn(n,e)}return""}function zf(t,e=120){let a=t.split(`
16826
+ `).map(wl).filter(Boolean);return a.length?hn(a[a.length-1],e):""}function wl(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function hn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var la=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 da(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var vl=140;function ca(t,e,a,n,r){let o=a==="error"?`Could not answer: ${fn(r||"",vl-18)||"something went wrong."}`:fn(n,vl)||"Answered.";return{deviceId:t,title:hn(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var _l=8e3,Uf=/^[A-Za-z0-9_.:-]{1,64}$/,Oe=new Map,gn=new Map,vn=new la;function Sl(){return vn}async function El(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??vn;if(n==="GET"&&a==="/api/app/agents")return B(e,200,{nodes:await Tl(o)});let i=o.store();if(!i)return B(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),B(e,200,{conversations:yl(r.id,Xf(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),B(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return B(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 B(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let c=Oe.get(p.id);return B(e,200,{...p,running:!!c,...c?{partial:{text:c.text,tools:c.tools,...c.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")||""),c=p&&Oe.get(p.id);if(!p||!c)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Al(e);let{id:m,title:g,node:k,nodeName:b,agent:S,agentName:T}=p;return e.write(xn("conversation",{id:m,title:g,node:k,nodeName:b,agent:S,agentName:T})),e.write(xn("resume",{text:c.text,tools:c.tools,...c.plain?{plain:!0}:{}})),c.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return B(e,404,{error:"not found"});let d;try{d=await qe(t,64*1024)}catch(p){return B(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(d.conversationId??""));if(!p)return B(e,404,{error:"no such conversation"});let c=Oe.get(p.id);return c?(c.ac.abort(),bn(p,o,r.name),B(e,200,{stopped:!0})):await bn(p,o,r.name)?B(e,200,{stopped:!0}):B(e,404,{error:"nothing is running in this conversation"})}return await Gf(e,d,r,i,o),!0}function Wf(t,e,a){let n=Ye(e.url),r=new Set,o=[];for(let s of t){let i=Ye(s.url),l=a.find(c=>Ye(c.peerUrl)===i);l&&r.add(l.peer);let d=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:p.map(c=>{let m=Array.isArray(c.runningTasks)?c.runningTasks.length:0;return{id:c.id,name:c.name||c.id,busy:m>0||(c.active??0)>0,running:m,...c.color?{color:c.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 Tl(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Wf(e.nodes,t.daemon,a)}async function Gf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>_l){B(t,400,{error:`message must be 1\u2013${_l} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){B(t,404,{error:"no such conversation"});return}}else{let k=typeof e.node=="string"?e.node:"",b=typeof e.agent=="string"?e.agent:"";if(!Uf.test(b)){B(t,400,{error:"pick an agent"});return}let S=(await Tl(r)).find(h=>h.target===k);if(!S){B(t,400,{error:`unknown node "${k}"`});return}if(!S.online){B(t,409,{error:`${S.name} is offline`});return}let T=S.agents.find(h=>h.id===b);if(!T){B(t,400,{error:`no agent "${b}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:b,agentName:T.name,...T.color?{color:T.color}:{}},o)}if(Oe.has(s.id)){B(t,409,{error:"The agent is still answering in this conversation."});return}let i=new ia(r.orphanLimitMs??18e5);Oe.set(s.id,i);let{id:l,title:d,node:p,nodeName:c,agent:m,agentName:g}=s;gn.set(l,{id:l,deviceId:a.id,title:d,agent:m,...g?{agentName:g}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Al(t),t.write(xn("conversation",{id:l,title:d,node:p,nodeName:c,agent:m,agentName:g})),i.attach(t);try{let k=e.spoken===!0,b=await bl(r.daemon,{node:p,agent:m,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(u,f)=>i.broadcast(u,f));i.orphaned&&(b.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,bn(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:b.text,status:b.status,at:Date.now(),...b.error?{error:b.error}:{},...b.ui?{ui:b.ui}:{},...b.tools.length?{tools:b.tools}:{}},b.files)??[];i.broadcast("final",{status:b.status,content:b.text,...b.error?{error:b.error}:{},...b.ui?{ui:b.ui}:{},...S.length?{files:S}:{}});let T=i.watched();T&&n.markRead(a.id,l);let h={status:b.status,attached:T,appOpen:(r.presence??vn).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&da(h)&&r.notifyFinish(ca(a.id,s,b.status,b.text,b.error)).catch(()=>{})}finally{Oe.delete(l),gn.delete(l),i.finish()}}function Xf(){let t=[];for(let[e,a]of gn){let n=Oe.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Al(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function xn(t,e){return`event: ${t}
16827
16827
  data: ${JSON.stringify(e)}
16828
16828
 
16829
- `}async function mn(t,e,a){try{let n=Ke(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Ke(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ke(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 Ke(t){return t.replace(/\/+$/,"")}function B(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Mf}from"stream";var Lf=/^\/api\/app\/files\/([^/]+)$/,Rf=15e3;async function gl(t,e,a,n,r,o){let s=Lf.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Oe(e,405,{error:"GET only"});let i=o.store();if(!i)return Oe(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let d=i.getFile(r.id,l);if(!d)return Oe(e,404,{error:"no such file"});let c=await Pf(d.node,o);if(!c)return Oe(e,502,{error:`${d.node} is not linked to this computer's mesh any more.`});let p=new AbortController;e.on("close",()=>p.abort());let m=setTimeout(()=>p.abort(),Rf),g;try{let h=new URLSearchParams({agent:d.agent,file:d.path});g=await fetch(`${c.url}${br}?${h}`,{method:n,headers:{...c.token?{Authorization:`Bearer ${c.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return Oe(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(g.status!==200&&g.status!==206){let h=await g.json().then(f=>f?.error).catch(()=>""),u=[403,404,413,415,416].includes(g.status)?g.status:502;return Oe(e,u,{error:h||`The computer that made this file answered HTTP ${g.status}.`})}let _=Number(g.headers.get("content-length")||0);if(_>ce.bytes)return p.abort(),Oe(e,413,{error:"the file is too large"});let y=g.headers.get("content-range");if(e.writeHead(g.status,{...vr(d.mime,d.name,d.kind),...g.headers.get("content-length")?{"Content-Length":String(_)}:{},...g.status===206&&y?{"Content-Range":y}:{}}),n==="HEAD"||!g.body)return e.end(),!0;let S=0,T=Mf.fromWeb(g.body);return T.on("data",h=>{S+=h.length,S>ce.bytes&&(T.destroy(),e.destroy())}),T.on("error",()=>e.destroy()),T.pipe(e),!0}async function Pf(t,e){if(t==="local")return{url:hl(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=hl(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function hl(t){return t.replace(/\/+$/,"")}function Oe(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 bl=8e3;async function vl(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Y(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let g=String(t.headers["content-type"]||"");if(!Cr(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let _=Ar(t.headers["x-audio-duration-ms"]);if(_)return t.resume(),Y(e,_.status,{error:_.error});let y=await Te(t,Tr.bytes);if(!y)return Y(e,413,{error:Ir()});if(!y.length)return Y(e,400,{error:"The recording is empty."});let S={"Content-Type":g,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return xl(e,o.daemon,"/voice/transcribe",y,S,18e4)}let s,i=await Te(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let d=l.get(r.id,String(s?.conversationId??""));if(!d)return Y(e,404,{error:"no such conversation"});let c=typeof s?.text=="string"?s.text.slice(0,bl):"";if(!c.trim())return Y(e,400,{error:"text is required"});if(!jf(d.messages,c))return Y(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${d.agentName||d.agent}: ${c}`:c,m={agent:d.agent,text:p,...d.node!=="local"?{peer:d.node}:{}};return xl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function xl(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($f(l)?.endpoints)?Y(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 Y(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function $f(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function jf(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===bl&&a.content.startsWith(e)))}var Of=new Set(["ring","offer","answer","ice","hangup"]),Je=/^[A-Za-z0-9_-]{4,64}$/,Nf=128*1024,Df=24,Hf=2*1024*1024,Ne=new Map;async function wl(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 M(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return M(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return M(e,502,{error:`AgentX answered HTTP ${l.status}.`});let d=await l.json(),c=Ze(r.nodeName),p=(Array.isArray(d.peers)?d.peers:[]).filter(g=>Ze(String(g?.name??""))!==c),m=(Array.isArray(d.agents)?d.agents:[]).filter(g=>g&&typeof g.id=="string").map(g=>({id:g.id,name:typeof g.name=="string"&&g.name?g.name:g.id}));return M(e,200,{node:r.nodeName,iceServers:d.iceServers??[],peers:p,agents:m,camera:d.camera??null})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Te(t,Nf);if(!l)return M(e,413,{error:"signal too large"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let c=qf(d,r.nodeName);if(typeof c=="string")return M(e,400,{error:c});let p=kl(c.to);if(p&&c.kind==="ring"){let m=await De(o,s,"POST","/webrtc/camera/watch",{callId:c.callId,agentId:p});return M(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(c),signal:AbortSignal.timeout(15e3)}),g=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:g?.error||`AgentX answered HTTP ${m.status}.`})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Je.test(l)?zf(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Te(t,4096);if(!l)return M(e,413,{error:"note too long"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let c=String(d?.callId??"");if(!Je.test(c))return M(e,400,{error:"callId is required"});let p=typeof d?.note=="string"?d.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/look`,{note:p},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await yl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Je.test(d))return M(e,400,{error:"callId is required"});let c=Number(l.seconds??0);if(!Number.isFinite(c)||c<0)return M(e,400,{error:"seconds must be 0 or more"});let p=typeof l.note=="string"?l.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/stream`,{seconds:c,note:p});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await yl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Je.test(d))return M(e,400,{error:"callId is required"});let c=await De(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(d)}`);if(c.status>=300)return M(e,c.status,{error:c.body.error});let p=(Array.isArray(c.body.watch?.replies)?c.body.watch.replies:[]).find(y=>y&&y.at===l.at);if(!p||typeof p.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(c.body.watch.agentId??""),g=JSON.stringify([d,p.at,m,p.text]),_=Ne.get(g);return _?(Ne.delete(g),Ne.set(g,_),_l(e,_.type,_.bytes)):Bf(e,o,s,{agent:m,text:p.text},(y,S)=>{if(!(S.length>Hf))for(Ne.set(g,{type:y,bytes:S});Ne.size>Df;)Ne.delete(Ne.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await De(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let d=(Array.isArray(l.body.calls)?l.body.calls:[]).map(c=>({id:c.id,agentId:c.agentId,reason:c.reason,createdAt:c.createdAt}));return M(e,200,{asks:d,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 M(e,405,{error:"POST"});let l=await De(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Je.test(l))return M(e,400,{error:"callId is required"});let d=await De(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,d.status,d.status<300?{watch:d.body.watch}:{error:d.body.error})}return M(e,404,{error:"not found"})}function kl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function De(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."}}}}async function yl(t,e){let a=await Te(t,e);if(!a)return null;try{let n=JSON.parse(a.toString("utf8")||"{}");return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}async function Bf(t,e,a,n,r){try{let o=await fetch(`${e}/voice/speak`,{method:"POST",headers:{"Content-Type":"application/json",...a},body:JSON.stringify(n),signal:AbortSignal.timeout(9e4)}),s=o.headers.get("content-type")||"";if(o.ok&&s.startsWith("audio/")){let l=Buffer.from(await o.arrayBuffer());return r(s,l),_l(t,s,l)}let i=await o.json().catch(()=>({}));return o.ok||typeof i?.text=="string"?M(t,200,{text:typeof i?.text=="string"?i.text:n.text}):M(t,200,{text:n.text,error:i?.error||`AgentX answered HTTP ${o.status}.`})}catch{return M(t,200,{text:n.text,error:"Could not reach AgentX on this computer."})}}function _l(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function qf(t,e){let a=String(t?.kind??"");if(!Of.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Je.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:")&&!kl(r))return"to must be bot:<agent id> for an agent";if(Ze(r)===Ze(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 zf(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 M(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?M(e,503,{error:"Calls are off on this computer."}):M(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 M(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{mkdirSync as Ff,readFileSync as Uf,renameSync as Wf,writeFileSync as Gf}from"fs";import{dirname as Xf,isAbsolute as Kf,resolve as Jf}from"path";import{randomBytes as Vf}from"crypto";var Sl=60,El=500,Yf=200,Cl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Qf=/^[A-Za-z0-9_-]{8,64}$/,Zf=/^[A-Za-z0-9._-]{1,64}$/;function Il(t,e){return Kf(e)?e:Jf(t,e)}function Tl(t){return`${t}_${Vf(6).toString("hex")}`}function Al(){return{places:[],rules:[],seen:[]}}function Ml(t,e){let a=typeof t.name=="string"?t.name.trim():"";if(!a)return{ok:!1,error:"Give the place a name."};if([...a].length>Sl)return{ok:!1,error:`Keep the name under ${Sl} characters.`};let n=Number(t.lat),r=Number(t.lng);if(t.lat===void 0||t.lat===""||!Number.isFinite(n)||n<-90||n>90)return{ok:!1,error:"Latitude must be a number from -90 to 90."};if(t.lng===void 0||t.lng===""||!Number.isFinite(r)||r<-180||r>180)return{ok:!1,error:"Longitude must be a number from -180 to 180."};let o=t.radius===void 0||t.radius===""?e.defaultRadiusMeters:Math.round(Number(t.radius));if(!Number.isFinite(o)||o<e.minRadiusMeters||o>e.maxRadiusMeters)return{ok:!1,error:`The radius must be from ${e.minRadiusMeters} to ${e.maxRadiusMeters} metres.`};let s=i=>Math.round(i*1e6)/1e6;return{ok:!0,value:{name:a,lat:s(n),lng:s(r),radius:o}}}function Ll(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!Cl.test(a))return{ok:!1,error:"Pick a place."};let n=t.on===void 0?"enter":t.on;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"on must be enter or exit."};let r=typeof t.text=="string"?t.text.trim():"";if(!r)return{ok:!1,error:"Write what to remind you of."};if([...r].length>El)return{ok:!1,error:`Keep it under ${El} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Zf.test(o)||!e(o))?{ok:!1,error:`There is no agent called ${o.slice(0,64)} on this computer.`}:t.repeat!==void 0&&typeof t.repeat!="boolean"?{ok:!1,error:"repeat must be true or false."}:{ok:!0,value:{placeId:a,on:n,text:r,...o?{agent:o}:{},repeat:t.repeat===!0}}}function Rl(t){let e=typeof t.id=="string"?t.id:"";if(!Qf.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!Cl.test(a))return{ok:!1,error:"place must be a place id"};let n=t.transition;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"transition must be enter or exit"};let r=typeof t.time=="number"?t.time:typeof t.time=="string"?Date.parse(t.time):NaN;return Number.isFinite(r)?{ok:!0,value:{id:e,place:a,transition:n,time:r}}:{ok:!1,error:"time must be a timestamp"}}var ia=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(Uf(this.path,"utf-8"));return!e||typeof e!="object"?Al():{places:Array.isArray(e.places)?e.places:[],rules:Array.isArray(e.rules)?e.rules:[],seen:Array.isArray(e.seen)?e.seen.filter(a=>typeof a=="string"):[]}}catch{return Al()}}write(e){Ff(Xf(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Gf(a,JSON.stringify(e,null,2)+`
16830
- `,{mode:384}),Wf(a,this.path)}addPlace(e,a){let n=this.read();if(n.places.length>=a.maxPlaces)return{ok:!1,error:`You already have ${a.maxPlaces} places, the most allowed (app.places.maxPlaces). Remove one first.`};if(n.places.some(o=>o.name.toLowerCase()===e.name.toLowerCase()))return{ok:!1,error:`You already have a place called ${e.name}.`};let r={id:Tl("pl"),...e,createdAt:new Date(this.now()).toISOString()};return n.places.push(r),this.write(n),{ok:!0,place:r}}removePlace(e){let a=this.read(),n=a.places.length;return a.places=a.places.filter(r=>r.id!==e),a.places.length===n?!1:(a.rules=a.rules.filter(r=>r.placeId!==e),this.write(a),!0)}addRule(e,a){let n=this.read();if(!n.places.some(o=>o.id===e.placeId))return{ok:!1,error:"That place doesn't exist any more."};if(n.rules.filter(o=>o.placeId===e.placeId).length>=a.maxRulesPerPlace)return{ok:!1,error:`That place already has ${a.maxRulesPerPlace} reminders, the most allowed (app.places.maxRulesPerPlace).`};let r={id:Tl("pr"),...e,enabled:!0,createdAt:new Date(this.now()).toISOString()};return n.rules.push(r),this.write(n),{ok:!0,rule:r}}setRuleEnabled(e,a){let n=this.read(),r=n.rules.find(o=>o.id===e);return r?(r.enabled=a,this.write(n),r):null}removeRule(e){let a=this.read(),n=a.rules.length;return a.rules=a.rules.filter(r=>r.id!==e),a.rules.length===n?!1:(this.write(a),!0)}accept(e,a){let n=this.read();if(n.seen.includes(e.id))return{status:"duplicate"};n.seen=[...n.seen,e.id].slice(-Yf);let r=this.now(),o=n.places.find(i=>i.id===e.place),s;if(!o)s={status:"unknown-place"};else if(e.time<r-a.maxEventAgeMinutes*6e4)s={status:"too-old"};else{let i=a.cooldownMinutes*6e4,l=n.rules.filter(d=>d.placeId===o.id&&d.on===e.transition&&d.enabled&&!(d.lastFiredAt&&Date.parse(d.lastFiredAt)>r-i));for(let d of l)d.lastFiredAt=new Date(r).toISOString(),d.repeat||(d.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(d=>({...d}))}:{status:"no-rules"}}return this.write(n),s}};Dn();function eh(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function th(t,e,a){let n=new Date(a).toISOString().slice(0,16).replace("T"," ")+" UTC";return[`[Place reminder \xB7 ${e.on==="enter"?"the owner arrived at":"the owner left"} ${t.name} \xB7 ${n}]`,e.text,"","Your answer is sent to the owner's phone as a notification. Keep it short."].join(`
16831
- `)}async function Pl(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=eh(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,th(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16829
+ `}async function bn(t,e,a){try{let n=Ye(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Ye(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ye(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 Ye(t){return t.replace(/\/+$/,"")}function B(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Kf}from"stream";var Jf=/^\/api\/app\/files\/([^/]+)$/,Vf=15e3;async function Il(t,e,a,n,r,o){let s=Jf.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ne(e,405,{error:"GET only"});let i=o.store();if(!i)return Ne(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let d=i.getFile(r.id,l);if(!d)return Ne(e,404,{error:"no such file"});let p=await Yf(d.node,o);if(!p)return Ne(e,502,{error:`${d.node} is not linked to this computer's mesh any more.`});let c=new AbortController;e.on("close",()=>c.abort());let m=setTimeout(()=>c.abort(),Vf),g;try{let h=new URLSearchParams({agent:d.agent,file:d.path});g=await fetch(`${p.url}${Mr}?${h}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:c.signal})}catch{return Ne(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(g.status!==200&&g.status!==206){let h=await g.json().then(f=>f?.error).catch(()=>""),u=[403,404,413,415,416].includes(g.status)?g.status:502;return Ne(e,u,{error:h||`The computer that made this file answered HTTP ${g.status}.`})}let k=Number(g.headers.get("content-length")||0);if(k>pe.bytes)return c.abort(),Ne(e,413,{error:"the file is too large"});let b=g.headers.get("content-range");if(e.writeHead(g.status,{...Rr(d.mime,d.name,d.kind),...g.headers.get("content-length")?{"Content-Length":String(k)}:{},...g.status===206&&b?{"Content-Range":b}:{}}),n==="HEAD"||!g.body)return e.end(),!0;let S=0,T=Kf.fromWeb(g.body);return T.on("data",h=>{S+=h.length,S>pe.bytes&&(T.destroy(),e.destroy())}),T.on("error",()=>e.destroy()),T.pipe(e),!0}async function Yf(t,e){if(t==="local")return{url:Cl(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Cl(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Cl(t){return t.replace(/\/+$/,"")}function Ne(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 Rl=8e3;async function Ll(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Y(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let g=String(t.headers["content-type"]||"");if(!Br(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Hr(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Y(e,k.status,{error:k.error});let b=await Ce(t,Dr.bytes);if(!b)return Y(e,413,{error:qr()});if(!b.length)return Y(e,400,{error:"The recording is empty."});let S={"Content-Type":g,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Ml(e,o.daemon,"/voice/transcribe",b,S,18e4)}let s,i=await Ce(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let d=l.get(r.id,String(s?.conversationId??""));if(!d)return Y(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Rl):"";if(!p.trim())return Y(e,400,{error:"text is required"});if(!Zf(d.messages,p))return Y(e,404,{error:"no such answer in this conversation"});let c=s?.announce===!0?`${d.agentName||d.agent}: ${p}`:p,m={agent:d.agent,text:c,...d.node!=="local"?{peer:d.node}:{}};return Ml(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Ml(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(Qf(l)?.endpoints)?Y(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 Y(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function Qf(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Zf(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Rl&&a.content.startsWith(e)))}var eh=new Set(["ring","offer","answer","ice","hangup"]),Qe=/^[A-Za-z0-9_-]{4,64}$/,th=128*1024,ah=24,nh=2*1024*1024,De=new Map;async function $l(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 M(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return M(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return M(e,502,{error:`AgentX answered HTTP ${l.status}.`});let d=await l.json(),p=at(r.nodeName),c=(Array.isArray(d.peers)?d.peers:[]).filter(g=>at(String(g?.name??""))!==p),m=(Array.isArray(d.agents)?d.agents:[]).filter(g=>g&&typeof g.id=="string").map(g=>({id:g.id,name:typeof g.name=="string"&&g.name?g.name:g.id}));return M(e,200,{node:r.nodeName,iceServers:d.iceServers??[],peers:c,agents:m,camera:d.camera??null})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,th);if(!l)return M(e,413,{error:"signal too large"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=oh(d,r.nodeName);if(typeof p=="string")return M(e,400,{error:p});let c=jl(p.to);if(c&&p.kind==="ring"){let m=await He(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:c});return M(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)}),g=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:g?.error||`AgentX answered HTTP ${m.status}.`})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Qe.test(l)?sh(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,4096);if(!l)return M(e,413,{error:"note too long"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=String(d?.callId??"");if(!Qe.test(p))return M(e,400,{error:"callId is required"});let c=typeof d?.note=="string"?d.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:c},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Pl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Qe.test(d))return M(e,400,{error:"callId is required"});let p=Number(l.seconds??0);if(!Number.isFinite(p)||p<0)return M(e,400,{error:"seconds must be 0 or more"});let c=typeof l.note=="string"?l.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/stream`,{seconds:p,note:c});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Pl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Qe.test(d))return M(e,400,{error:"callId is required"});let p=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(d)}`);if(p.status>=300)return M(e,p.status,{error:p.body.error});let c=(Array.isArray(p.body.watch?.replies)?p.body.watch.replies:[]).find(b=>b&&b.at===l.at);if(!c||typeof c.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(p.body.watch.agentId??""),g=JSON.stringify([d,c.at,m,c.text]),k=De.get(g);return k?(De.delete(g),De.set(g,k),Ol(e,k.type,k.bytes)):rh(e,o,s,{agent:m,text:c.text},(b,S)=>{if(!(S.length>nh))for(De.set(g,{type:b,bytes:S});De.size>ah;)De.delete(De.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await He(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let d=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return M(e,200,{asks:d,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 M(e,405,{error:"POST"});let l=await He(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Qe.test(l))return M(e,400,{error:"callId is required"});let d=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,d.status,d.status<300?{watch:d.body.watch}:{error:d.body.error})}return M(e,404,{error:"not found"})}function jl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function He(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."}}}}async function Pl(t,e){let a=await Ce(t,e);if(!a)return null;try{let n=JSON.parse(a.toString("utf8")||"{}");return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}async function rh(t,e,a,n,r){try{let o=await fetch(`${e}/voice/speak`,{method:"POST",headers:{"Content-Type":"application/json",...a},body:JSON.stringify(n),signal:AbortSignal.timeout(9e4)}),s=o.headers.get("content-type")||"";if(o.ok&&s.startsWith("audio/")){let l=Buffer.from(await o.arrayBuffer());return r(s,l),Ol(t,s,l)}let i=await o.json().catch(()=>({}));return o.ok||typeof i?.text=="string"?M(t,200,{text:typeof i?.text=="string"?i.text:n.text}):M(t,200,{text:n.text,error:i?.error||`AgentX answered HTTP ${o.status}.`})}catch{return M(t,200,{text:n.text,error:"Could not reach AgentX on this computer."})}}function Ol(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function oh(t,e){let a=String(t?.kind??"");if(!eh.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Qe.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:")&&!jl(r))return"to must be bot:<agent id> for an agent";if(at(r)===at(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 sh(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 M(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?M(e,503,{error:"Calls are off on this computer."}):M(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 M(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{mkdirSync as ih,readFileSync as lh,renameSync as dh,writeFileSync as ch}from"fs";import{dirname as ph,isAbsolute as uh,resolve as mh}from"path";import{randomBytes as fh}from"crypto";var Nl=60,Dl=500,hh=200,ql=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,gh=/^[A-Za-z0-9_-]{8,64}$/,xh=/^[A-Za-z0-9._-]{1,64}$/;function zl(t,e){return uh(e)?e:mh(t,e)}function Hl(t){return`${t}_${fh(6).toString("hex")}`}function Bl(){return{places:[],rules:[],seen:[]}}function Fl(t,e){let a=typeof t.name=="string"?t.name.trim():"";if(!a)return{ok:!1,error:"Give the place a name."};if([...a].length>Nl)return{ok:!1,error:`Keep the name under ${Nl} characters.`};let n=Number(t.lat),r=Number(t.lng);if(t.lat===void 0||t.lat===""||!Number.isFinite(n)||n<-90||n>90)return{ok:!1,error:"Latitude must be a number from -90 to 90."};if(t.lng===void 0||t.lng===""||!Number.isFinite(r)||r<-180||r>180)return{ok:!1,error:"Longitude must be a number from -180 to 180."};let o=t.radius===void 0||t.radius===""?e.defaultRadiusMeters:Math.round(Number(t.radius));if(!Number.isFinite(o)||o<e.minRadiusMeters||o>e.maxRadiusMeters)return{ok:!1,error:`The radius must be from ${e.minRadiusMeters} to ${e.maxRadiusMeters} metres.`};let s=i=>Math.round(i*1e6)/1e6;return{ok:!0,value:{name:a,lat:s(n),lng:s(r),radius:o}}}function Ul(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!ql.test(a))return{ok:!1,error:"Pick a place."};let n=t.on===void 0?"enter":t.on;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"on must be enter or exit."};let r=typeof t.text=="string"?t.text.trim():"";if(!r)return{ok:!1,error:"Write what to remind you of."};if([...r].length>Dl)return{ok:!1,error:`Keep it under ${Dl} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!xh.test(o)||!e(o))?{ok:!1,error:`There is no agent called ${o.slice(0,64)} on this computer.`}:t.repeat!==void 0&&typeof t.repeat!="boolean"?{ok:!1,error:"repeat must be true or false."}:{ok:!0,value:{placeId:a,on:n,text:r,...o?{agent:o}:{},repeat:t.repeat===!0}}}function Wl(t){let e=typeof t.id=="string"?t.id:"";if(!gh.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!ql.test(a))return{ok:!1,error:"place must be a place id"};let n=t.transition;if(n!=="enter"&&n!=="exit")return{ok:!1,error:"transition must be enter or exit"};let r=typeof t.time=="number"?t.time:typeof t.time=="string"?Date.parse(t.time):NaN;return Number.isFinite(r)?{ok:!0,value:{id:e,place:a,transition:n,time:r}}:{ok:!1,error:"time must be a timestamp"}}var pa=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(lh(this.path,"utf-8"));return!e||typeof e!="object"?Bl():{places:Array.isArray(e.places)?e.places:[],rules:Array.isArray(e.rules)?e.rules:[],seen:Array.isArray(e.seen)?e.seen.filter(a=>typeof a=="string"):[]}}catch{return Bl()}}write(e){ih(ph(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;ch(a,JSON.stringify(e,null,2)+`
16830
+ `,{mode:384}),dh(a,this.path)}addPlace(e,a){let n=this.read();if(n.places.length>=a.maxPlaces)return{ok:!1,error:`You already have ${a.maxPlaces} places, the most allowed (app.places.maxPlaces). Remove one first.`};if(n.places.some(o=>o.name.toLowerCase()===e.name.toLowerCase()))return{ok:!1,error:`You already have a place called ${e.name}.`};let r={id:Hl("pl"),...e,createdAt:new Date(this.now()).toISOString()};return n.places.push(r),this.write(n),{ok:!0,place:r}}removePlace(e){let a=this.read(),n=a.places.length;return a.places=a.places.filter(r=>r.id!==e),a.places.length===n?!1:(a.rules=a.rules.filter(r=>r.placeId!==e),this.write(a),!0)}addRule(e,a){let n=this.read();if(!n.places.some(o=>o.id===e.placeId))return{ok:!1,error:"That place doesn't exist any more."};if(n.rules.filter(o=>o.placeId===e.placeId).length>=a.maxRulesPerPlace)return{ok:!1,error:`That place already has ${a.maxRulesPerPlace} reminders, the most allowed (app.places.maxRulesPerPlace).`};let r={id:Hl("pr"),...e,enabled:!0,createdAt:new Date(this.now()).toISOString()};return n.rules.push(r),this.write(n),{ok:!0,rule:r}}setRuleEnabled(e,a){let n=this.read(),r=n.rules.find(o=>o.id===e);return r?(r.enabled=a,this.write(n),r):null}removeRule(e){let a=this.read(),n=a.rules.length;return a.rules=a.rules.filter(r=>r.id!==e),a.rules.length===n?!1:(this.write(a),!0)}accept(e,a){let n=this.read();if(n.seen.includes(e.id))return{status:"duplicate"};n.seen=[...n.seen,e.id].slice(-hh);let r=this.now(),o=n.places.find(i=>i.id===e.place),s;if(!o)s={status:"unknown-place"};else if(e.time<r-a.maxEventAgeMinutes*6e4)s={status:"too-old"};else{let i=a.cooldownMinutes*6e4,l=n.rules.filter(d=>d.placeId===o.id&&d.on===e.transition&&d.enabled&&!(d.lastFiredAt&&Date.parse(d.lastFiredAt)>r-i));for(let d of l)d.lastFiredAt=new Date(r).toISOString(),d.repeat||(d.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(d=>({...d}))}:{status:"no-rules"}}return this.write(n),s}};Xn();function bh(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function vh(t,e,a){let n=new Date(a).toISOString().slice(0,16).replace("T"," ")+" UTC";return[`[Place reminder \xB7 ${e.on==="enter"?"the owner arrived at":"the owner left"} ${t.name} \xB7 ${n}]`,e.text,"","Your answer is sent to the owner's phone as a notification. Keep it short."].join(`
16831
+ `)}async function Gl(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=bh(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,vh(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16832
16832
 
16833
- (${o.agent} couldn't run this: ${String(l?.message||l).slice(0,160)})`}try{await r.push(t,s,i),r.log(`[places] ${o.id} on ${e.id}: pushed to ${t}`)}catch(l){r.log(`[places] ${o.id} on ${e.id}: push failed: ${String(l?.message||l).slice(0,200)}`)}}))}function $l(t,e=console.error){let a=t.url.replace(/\/+$/,""),n={"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`}:{}};return{async push(r,o,s){let i=await fetch(a+"/channel/send",{method:"POST",headers:n,body:JSON.stringify({channel:"push",chatId:r,text:`${o}
16834
- ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15e3)});if(!i.ok)throw new Error(`HTTP ${i.status} ${(await i.text().catch(()=>"")).slice(0,160)}`)},async task(r,o,s){let i=await fetch(a+"/task",{method:"POST",headers:{...n,...t.operatorKey?{[Nn]:t.operatorKey}:{}},body:JSON.stringify({agent:r,message:o,context:{channel:"app",chatId:`place:${s}`,sender:"places"}}),signal:AbortSignal.timeout(6e5)}),l=await i.json().catch(()=>({}));if(!i.ok||l.error)throw new Error(String(l.error||`HTTP ${i.status}`));return String(l.content??"")},log:e}}async function jl(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Nl(t,e,a.slice(15),n,o,r)}async function Ol(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Nl(t,e,a.slice(11),n,r,null)}async function Nl(t,e,a,n,r,o){if(n==="GET"&&a===""){let i=r.enabled?r.store.read():{places:[],rules:[]};return q(e,200,{enabled:r.enabled,reason:r.enabled?null:"Place reminders are off on this computer (app.places.enabled).",pushAvailable:!!r.fire,pushReason:r.fire?null:r.pushReason??null,limits:{defaultRadiusMeters:r.limits.defaultRadiusMeters,minRadiusMeters:r.limits.minRadiusMeters,maxRadiusMeters:r.limits.maxRadiusMeters,maxPlaces:r.limits.maxPlaces},syncMinutes:r.syncMinutes,android:{packageName:r.androidPackage},places:i.places,rules:i.rules,agents:r.agents()})}if(n!=="POST")return q(e,404,{error:"not found"});if(!r.enabled)return q(e,403,{error:"Place reminders are off on this computer (app.places.enabled)."});let s;try{s=await yt(t,4096)}catch(i){return q(e,400,{error:i.message})}if(a==="/event"){if(!o)return q(e,404,{error:"not found"});let i=Rl(s);if(!i.ok)return q(e,400,{error:i.error});let l=r.store.accept(i.value,r.limits);return r.log(`[places] ${o.id} ${i.value.transition} ${i.value.place}: ${l.status}${l.status==="fired"?` (${l.rules.length})`:""}`),l.status==="fired"&&(r.fire?Pl(o.id,l.place,l.rules,i.value.time,r.fire).catch(d=>r.log(`[places] delivery failed: ${d?.message||d}`)):r.log(`[places] ${l.rules.length} reminder(s) not sent: ${r.pushReason??"this computer doesn't send pushes"}`)),q(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=Ml(s,r.limits);if(!i.ok)return q(e,400,{error:i.error});let l=r.store.addPlace(i.value,r.limits);return l.ok?q(e,200,{ok:!0,place:l.place}):q(e,409,{error:l.error})}if(a==="/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removePlace(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such place."})}if(a==="/rules/add"){let i=new Set(r.agents()),l=Ll(s,c=>i.has(c));if(!l.ok)return q(e,400,{error:l.error});let d=r.store.addRule(l.value,r.limits);return d.ok?q(e,200,{ok:!0,rule:d.rule}):q(e,409,{error:d.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return q(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?q(e,200,{ok:!0,rule:i}):q(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such reminder."})}return q(e,404,{error:"not found"})}function Dl(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new ia(Il(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function Hl(t){let e=t.app.android;return e.certFingerprints.length?[{relation:["delegate_permission/common.handle_all_urls"],target:{namespace:"android_app",package_name:e.packageName,sha256_cert_fingerprints:e.certFingerprints.map(a=>a.toUpperCase())}}]:null}function q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Bl=`
16833
+ (${o.agent} couldn't run this: ${String(l?.message||l).slice(0,160)})`}try{await r.push(t,s,i),r.log(`[places] ${o.id} on ${e.id}: pushed to ${t}`)}catch(l){r.log(`[places] ${o.id} on ${e.id}: push failed: ${String(l?.message||l).slice(0,200)}`)}}))}function Xl(t,e=console.error){let a=t.url.replace(/\/+$/,""),n={"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`}:{}};return{async push(r,o,s){let i=await fetch(a+"/channel/send",{method:"POST",headers:n,body:JSON.stringify({channel:"push",chatId:r,text:`${o}
16834
+ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15e3)});if(!i.ok)throw new Error(`HTTP ${i.status} ${(await i.text().catch(()=>"")).slice(0,160)}`)},async task(r,o,s){let i=await fetch(a+"/task",{method:"POST",headers:{...n,...t.operatorKey?{[Gn]:t.operatorKey}:{}},body:JSON.stringify({agent:r,message:o,context:{channel:"app",chatId:`place:${s}`,sender:"places"}}),signal:AbortSignal.timeout(6e5)}),l=await i.json().catch(()=>({}));if(!i.ok||l.error)throw new Error(String(l.error||`HTTP ${i.status}`));return String(l.content??"")},log:e}}async function Kl(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Vl(t,e,a.slice(15),n,o,r)}async function Jl(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Vl(t,e,a.slice(11),n,r,null)}async function Vl(t,e,a,n,r,o){if(n==="GET"&&a===""){let i=r.enabled?r.store.read():{places:[],rules:[]};return q(e,200,{enabled:r.enabled,reason:r.enabled?null:"Place reminders are off on this computer (app.places.enabled).",pushAvailable:!!r.fire,pushReason:r.fire?null:r.pushReason??null,limits:{defaultRadiusMeters:r.limits.defaultRadiusMeters,minRadiusMeters:r.limits.minRadiusMeters,maxRadiusMeters:r.limits.maxRadiusMeters,maxPlaces:r.limits.maxPlaces},syncMinutes:r.syncMinutes,android:{packageName:r.androidPackage},places:i.places,rules:i.rules,agents:r.agents()})}if(n!=="POST")return q(e,404,{error:"not found"});if(!r.enabled)return q(e,403,{error:"Place reminders are off on this computer (app.places.enabled)."});let s;try{s=await qe(t,4096)}catch(i){return q(e,400,{error:i.message})}if(a==="/event"){if(!o)return q(e,404,{error:"not found"});let i=Wl(s);if(!i.ok)return q(e,400,{error:i.error});let l=r.store.accept(i.value,r.limits);return r.log(`[places] ${o.id} ${i.value.transition} ${i.value.place}: ${l.status}${l.status==="fired"?` (${l.rules.length})`:""}`),l.status==="fired"&&(r.fire?Gl(o.id,l.place,l.rules,i.value.time,r.fire).catch(d=>r.log(`[places] delivery failed: ${d?.message||d}`)):r.log(`[places] ${l.rules.length} reminder(s) not sent: ${r.pushReason??"this computer doesn't send pushes"}`)),q(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=Fl(s,r.limits);if(!i.ok)return q(e,400,{error:i.error});let l=r.store.addPlace(i.value,r.limits);return l.ok?q(e,200,{ok:!0,place:l.place}):q(e,409,{error:l.error})}if(a==="/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removePlace(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such place."})}if(a==="/rules/add"){let i=new Set(r.agents()),l=Ul(s,p=>i.has(p));if(!l.ok)return q(e,400,{error:l.error});let d=r.store.addRule(l.value,r.limits);return d.ok?q(e,200,{ok:!0,rule:d.rule}):q(e,409,{error:d.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return q(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?q(e,200,{ok:!0,rule:i}):q(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such reminder."})}return q(e,404,{error:"not found"})}function Yl(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new pa(zl(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function Ql(t){let e=t.app.android;return e.certFingerprints.length?[{relation:["delegate_permission/common.handle_all_urls"],target:{namespace:"android_app",package_name:e.packageName,sha256_cert_fingerprints:e.certFingerprints.map(a=>a.toUpperCase())}}]:null}function q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Zl=`
16835
16835
  :root {
16836
16836
  --ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
16837
16837
  --ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
@@ -16845,7 +16845,7 @@ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15
16845
16845
  --ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
16846
16846
  --phone-bubble: #1d2f52; --phone-green: #3dbe74;
16847
16847
  }
16848
- `,ql=`
16848
+ `,ed=`
16849
16849
  [hidden] { display: none !important; }
16850
16850
  main > .sw-peek[hidden] { display: block !important; }
16851
16851
  main > #panel-chat.sw-peek[hidden] { display: flex !important; }
@@ -16912,7 +16912,7 @@ main h2 { font-size: 28px; font-weight: 600; letter-spacing: -.02em; }
16912
16912
  .tabs [role=tab][aria-selected=true], [data-theme=dark] .tabs [role=tab][aria-selected=true] { background: transparent; color: var(--ax-accent); font-weight: 600; }
16913
16913
  .tab-icon { display: grid; place-items: center; width: 56px; height: 30px; border-radius: 16px; }
16914
16914
  .tab-icon svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
16915
- .tabs::before { content: ''; position: absolute; pointer-events: none; top: 4px; width: 56px; height: 30px; border-radius: 16px; background: var(--ax-accent-t); left: calc((var(--tab-position, 0) + .5) * 25% - 28px); }
16915
+ .tabs::before { content: ''; position: absolute; pointer-events: none; top: 4px; width: 56px; height: 30px; border-radius: 16px; background: var(--ax-accent-t); left: calc((var(--tab-position, 0) + .5) * 20% - 28px); }
16916
16916
  .tab-icon { position: relative; }
16917
16917
  .tabs button:active .tab-icon { background: var(--ax-surface-2); transform: scale(.92); }
16918
16918
  .fx-card { border-radius: 16px; padding: 16px; }
@@ -16951,7 +16951,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
16951
16951
  @media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
16952
16952
  @media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
16953
16953
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
16954
- `;var zl=`
16954
+ `;var td=`
16955
16955
  window.AXSheet = function (sheet, onClose) {
16956
16956
  var handle = document.createElement('button');
16957
16957
  handle.type = 'button'; handle.className = 'sheet-handle';
@@ -16980,7 +16980,7 @@ window.AXSheet = function (sheet, onClose) {
16980
16980
  handle.addEventListener('pointercancel', reset);
16981
16981
  sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
16982
16982
  };
16983
- `;var Fl=`
16983
+ `;var ad=`
16984
16984
  (function () {
16985
16985
  var fleetPanel = document.getElementById('panel-fleet');
16986
16986
  var activityPanel = document.getElementById('panel-activity');
@@ -17062,14 +17062,16 @@ window.AXSheet = function (sheet, onClose) {
17062
17062
  var input = document.getElementById('fx-input');
17063
17063
  var box = document.getElementById('fx-choices');
17064
17064
  var p = opts.pick;
17065
+ // p.sel: the choice the owner already tapped (the Desk); else the advised one.
17066
+ var sel = p ? (p.sel != null ? p.sel : p.rec) : -1;
17065
17067
  box.hidden = !p;
17066
17068
  box.innerHTML = p ? '<legend>Pick one</legend>' + p.choices.map(function (c, n) {
17067
- return '<label class="fx-opt"><input type="radio" name="fx-choice" required value="' + (n + 1) + '"' + (n === p.rec ? ' checked' : '') + '><span>' + esc(c) + (n === p.rec ? ' <em>suggested</em>' : '') + '</span></label>';
17069
+ return '<label class="fx-opt"><input type="radio" name="fx-choice" required value="' + (n + 1) + '"' + (n === sel ? ' checked' : '') + '><span>' + esc(c) + (n === p.rec ? ' <em>suggested</em>' : '') + '</span></label>';
17068
17070
  }).join('') : '';
17069
17071
  field.hidden = !opts.input && !(p && p.draft);
17070
17072
  document.getElementById('fx-field-label').textContent = p && p.draft ? 'Message the agent gets (you can edit it)' : 'Message';
17071
17073
  input.rows = p && p.draft ? 6 : 3;
17072
- input.value = p && p.draft ? fill(p.draft, p.rec >= 0 ? p.choices[p.rec] : '') : '';
17074
+ input.value = p && p.draft ? fill(p.draft, sel >= 0 ? p.choices[sel] : '') : '';
17073
17075
  delete input.dataset.edited;
17074
17076
  pending = opts;
17075
17077
  if (sheet.showModal) { sheet.showModal(); if (opts.input) input.focus(); }
@@ -17094,7 +17096,7 @@ window.AXSheet = function (sheet, onClose) {
17094
17096
  if (opts.input && !text) { flash(opts.panel, 'Nothing sent: the message was empty.', true); return; }
17095
17097
  api('POST', opts.path, opts.body(text, choice)).then(function (b) {
17096
17098
  flash(opts.panel, opts.done(b), false);
17097
- refresh();
17099
+ (opts.refresh || refresh)();
17098
17100
  }).catch(function (e) { flash(opts.panel, opts.title + ' failed: ' + e.message, true); });
17099
17101
  }
17100
17102
  // The refresh that follows an action re-renders the panel, so the last
@@ -17112,6 +17114,9 @@ window.AXSheet = function (sheet, onClose) {
17112
17114
  return '<p class="fx-status" role="status" aria-live="polite">Updated ' + esc(new Date(ts).toLocaleTimeString()) + '</p>';
17113
17115
  }
17114
17116
 
17117
+ // The Desk tab (app-desk.client.ts) asks through the same sheet.
17118
+ window.AXAsk = { ask: ask, api: api, esc: esc, ago: ago, advised: advised, flash: flash, statusLine: statusLine, open: function () { return sheet.open; } };
17119
+
17115
17120
  function statusPill(n) {
17116
17121
  if (!n.reachable) return '<span class="fx-pill fx-off"><span aria-hidden="true">\u2298 </span>Offline</span>';
17117
17122
  if (n.restart) return '<span class="fx-pill fx-warn">Restart ' + esc(n.restart.state) + '</span>';
@@ -17271,7 +17276,7 @@ window.AXSheet = function (sheet, onClose) {
17271
17276
  setInterval(refresh, 15000);
17272
17277
  refresh();
17273
17278
  })();
17274
- `;var Ul=`
17279
+ `;var nd=`
17275
17280
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
17276
17281
  .fx-head h2 { margin: 4px 0 0; }
17277
17282
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -17336,7 +17341,156 @@ details[open] > summary::before { transform: rotate(90deg); }
17336
17341
  .fx-opt em { font-style: normal; font-size: 12px; color: var(--ax-ok); white-space: nowrap; }
17337
17342
  .fx-error:empty { display: none; }
17338
17343
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
17339
- `;var Wl=`
17344
+ `;var rd=`
17345
+ (function () {
17346
+ var panel = document.getElementById('panel-desk');
17347
+ var ax = window.AXAsk;
17348
+ if (!panel || !ax) return;
17349
+ var esc = ax.esc, ago = ax.ago;
17350
+ var COLS = [['yours', 'Your turn'], ['agent', 'With agents'], ['quiet', 'No news'], ['done', 'Done']];
17351
+ var EMPTY = {
17352
+ yours: 'Nothing waits for you.',
17353
+ agent: 'No agent is working on a request right now.',
17354
+ quiet: 'Nothing open has gone quiet.',
17355
+ done: 'Nothing ended in the last 7 days.',
17356
+ };
17357
+ var col = 'yours';
17358
+
17359
+ function pill(c) {
17360
+ if (c.column === 'yours') return '<span class="fx-pill fx-warn">\u2161 Waiting</span>';
17361
+ if (c.column === 'agent') return '<span class="fx-pill fx-on">' + (c.live ? '\u25D4 Working now' : 'Active') + '</span>';
17362
+ if (c.column === 'quiet') return '<span class="fx-pill fx-off">No news</span>';
17363
+ return '';
17364
+ }
17365
+ function when(c) {
17366
+ if (c.column === 'yours') return (c.askedAt ? 'asked ' + ago(c.askedAt) : '') + (c.expires ? ' \xB7 answer by ' + new Date(c.expires).toLocaleString() : '');
17367
+ if (c.column === 'done') return c.changedAt ? 'ended ' + ago(c.changedAt) : '';
17368
+ return c.changedAt ? 'last change ' + ago(c.changedAt) : '';
17369
+ }
17370
+ function option(act, k, label, means, extra) {
17371
+ return '<button type="button" class="fx-btn dk-opt' + (extra && extra.cls ? ' ' + extra.cls : '') + '" data-act="' + act + '" data-k="' + k + '"' +
17372
+ (extra && extra.attr ? ' ' + extra.attr : '') + '>' + label + (means ? '<small>' + esc(means) + '</small>' : '') + '</button>';
17373
+ }
17374
+ function answers(c, k) {
17375
+ var h = '';
17376
+ if (c.can.answer) {
17377
+ if (c.choices) {
17378
+ var rec = ax.advised(c);
17379
+ c.choices.forEach(function (label, n) {
17380
+ h += option('pick', k, esc(label) + (n === rec ? ' <em>\xB7 suggested</em>' : ''), '', { cls: n === rec ? 'fx-primary' : '', attr: 'data-n="' + n + '"' });
17381
+ });
17382
+ } else {
17383
+ h += option('decide', k, 'Yes', c.yes, { cls: 'fx-primary', attr: 'data-v="yes"' });
17384
+ }
17385
+ h += option('decide', k, 'No', c.no, { attr: 'data-v="no"' });
17386
+ }
17387
+ if (c.can.reply) h += option('reply', k, c.column === 'yours' ? 'Write an answer' : 'Write to the agent', c.column === 'yours' ? '' : 'It gets your words and goes on.');
17388
+ if (c.can.later) h += option('decide', k, 'Later', 'Nothing is answered. It is shown again later.', { attr: 'data-v="later"' });
17389
+ return h ? '<div class="dk-answers">' + h + '</div>' : '';
17390
+ }
17391
+ function card(c, k, openKeys) {
17392
+ var key = c.node + '|' + c.key;
17393
+ return '<article class="fx-card"><div class="fx-row"><h4>' + esc(c.title) + '</h4>' + pill(c) + '</div>' +
17394
+ (c.ask ? '<p>' + esc(c.ask) + '</p>' : '') +
17395
+ (c.outcome ? '<p><strong>' + esc(c.outcome) + '</strong>' + (c.evidence ? ' \xB7 ' + esc(c.evidence) : '') + '</p>' : '') +
17396
+ (c.recommend ? '<p class="fx-muted">Suggested: ' + esc(c.recommend) + '</p>' : '') +
17397
+ (c.facts ? '<details data-key="' + esc(key) + '"' + (openKeys[key] ? ' open' : '') + '><summary>What is known</summary><p class="fx-muted">' + esc(c.facts) + '</p></details>' : '') +
17398
+ '<p class="fx-muted">' + [c.agent, c.nodeName, when(c)].filter(Boolean).map(esc).join(' \xB7 ') + '</p>' +
17399
+ answers(c, k) + '</article>';
17400
+ }
17401
+ function render(data) {
17402
+ // Redraws every 15 seconds; keep the facts the owner opened open.
17403
+ var openKeys = {};
17404
+ panel.querySelectorAll('details[open]').forEach(function (d) { openKeys[d.getAttribute('data-key')] = true; });
17405
+ var f = data.figures;
17406
+ var html = '<div class="fx-head"><h2>Desk</h2><button type="button" class="fx-btn" data-act="refresh">Refresh</button></div>' +
17407
+ ax.statusLine(panel, data.ts) +
17408
+ '<p class="fx-muted dk-figures">Waits for you: <strong>' + f.yours.count + '</strong>' + (f.yours.oldest ? ', the oldest asked ' + esc(ago(f.yours.oldest)) : '') +
17409
+ '. With agents: <strong>' + f.agent.count + '</strong>. No news: <strong>' + f.quiet.count + '</strong>' + (f.quiet.oldest ? ', the longest since ' + esc(ago(f.quiet.oldest)) : '') + '.</p>' +
17410
+ '<div class="dk-cols" role="group" aria-label="Column">' + COLS.map(function (x) {
17411
+ return '<button type="button" class="dk-col" aria-pressed="' + (x[0] === col) + '" data-act="col" data-col="' + x[0] + '">' + x[1] + '<span>' + f[x[0]].count + '</span></button>';
17412
+ }).join('') + '</div>';
17413
+ data.errors.forEach(function (e) { html += '<p class="fx-muted fx-bad">' + esc(e) + '</p>'; });
17414
+ var shown = 0;
17415
+ data.cards.forEach(function (c, k) {
17416
+ if (c.column !== col) return;
17417
+ html += card(c, k, openKeys);
17418
+ shown++;
17419
+ });
17420
+ if (!shown) html += '<p class="fx-muted">' + EMPTY[col] + '</p>';
17421
+ panel.innerHTML = html;
17422
+ panel._data = data;
17423
+ }
17424
+
17425
+ function decide(c, v, n) {
17426
+ var word = { yes: 'Yes', no: 'No', later: 'Later' }[v];
17427
+ var pick = n != null ? { choices: c.choices, draft: c.draft, rec: ax.advised(c), sel: n } : null;
17428
+ ax.ask({ panel: panel, refresh: refresh, pick: pick, danger: v === 'no',
17429
+ title: pick ? c.title : word + ': ' + c.title + '?', ok: pick ? 'Choose' : word,
17430
+ text: pick ? (c.ask || '') : v === 'yes' ? (c.yes || '') : v === 'no' ? (c.no || '') : 'Nothing is answered. It is shown again later.',
17431
+ path: '/api/app/approvals/decide',
17432
+ body: function (text, choice) {
17433
+ var b = { node: c.node, key: c.key, action: v };
17434
+ if (choice) { b.choice = choice; if (c.draft && text) b.text = text; }
17435
+ return b;
17436
+ },
17437
+ done: function () { return v === 'later' ? 'Put off: ' + c.title + '.' : 'Answered ' + (pick ? '' : word + ': ') + c.title + '.'; } });
17438
+ }
17439
+ function reply(c) {
17440
+ ax.ask({ panel: panel, refresh: refresh, input: true, ok: 'Send',
17441
+ title: (c.column === 'yours' ? 'Answer ' : 'Write to ') + (c.agent || 'the agent'),
17442
+ text: c.ask || c.title,
17443
+ path: '/api/app/desk/reply',
17444
+ body: function (text) { return { id: c.key.slice(c.key.indexOf(':') + 1), text: text }; },
17445
+ done: function (b) { return b.message || 'Sent.'; } });
17446
+ }
17447
+ panel.addEventListener('click', function (ev) {
17448
+ var b = ev.target.closest('[data-act]');
17449
+ if (!b) return;
17450
+ var act = b.getAttribute('data-act');
17451
+ if (act === 'refresh') return refresh();
17452
+ if (act === 'col') { col = b.getAttribute('data-col'); if (panel._data) render(panel._data); return; }
17453
+ var c = panel._data.cards[+b.getAttribute('data-k')];
17454
+ if (act === 'pick') decide(c, 'yes', +b.getAttribute('data-n'));
17455
+ if (act === 'decide') decide(c, b.getAttribute('data-v'));
17456
+ if (act === 'reply') reply(c);
17457
+ });
17458
+
17459
+ var loading = false, again = 0;
17460
+ function refresh() {
17461
+ // Never redraw under an open sheet or a finger pulling the next tab in.
17462
+ if (loading || ax.open() || panel.hidden || document.visibilityState !== 'visible') return;
17463
+ if (document.querySelector('main.sw-on')) { clearTimeout(again); again = setTimeout(refresh, 300); return; }
17464
+ loading = true;
17465
+ ax.api('GET', '/api/app/desk').then(render)
17466
+ .catch(function (e) { ax.flash(panel, 'Could not load the desk: ' + e.message, true); })
17467
+ .then(function () { loading = false; });
17468
+ }
17469
+ if (!panel.querySelector('.fx-status')) panel.insertAdjacentHTML('beforeend', '<p class="fx-status" role="status" aria-live="polite"></p>');
17470
+ document.addEventListener('ax-tab', function () { setTimeout(refresh, 0); });
17471
+ document.addEventListener('visibilitychange', refresh);
17472
+ window.addEventListener('online', refresh);
17473
+ setInterval(refresh, 15000);
17474
+ refresh();
17475
+ })();
17476
+ `;var od=`
17477
+ .dk-figures { margin: 0 0 4px; line-height: 1.5; }
17478
+ .dk-cols {
17479
+ position: sticky; top: 0; z-index: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px;
17480
+ padding: 8px 0; margin: 0 0 8px; background: var(--ax-bg);
17481
+ }
17482
+ .dk-col {
17483
+ min-width: 0; min-height: 52px; padding: 4px 2px; font: inherit; font-size: var(--ax-fs-xs); font-weight: 600; cursor: pointer;
17484
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm);
17485
+ background: var(--ax-surface); color: var(--ax-text-2);
17486
+ }
17487
+ .dk-col span { display: block; font-size: 16px; color: var(--ax-text); }
17488
+ .dk-col[aria-pressed=true] { background: var(--ax-accent-t); border-color: var(--ax-accent); color: var(--ax-accent); }
17489
+ .dk-answers { display: grid; gap: 8px; margin-top: 12px; }
17490
+ .dk-opt { width: 100%; min-height: 48px; padding: 8px 14px; text-align: left; border-radius: var(--ax-radius-sm); overflow-wrap: anywhere; }
17491
+ .dk-opt small { display: block; margin-top: 2px; font-weight: 400; color: var(--ax-text-2); }
17492
+ .dk-opt em { font-style: normal; font-weight: 400; color: var(--ax-text-2); }
17493
+ `;var sd=`
17340
17494
  (function () {
17341
17495
  var panel = document.getElementById('panel-alerts');
17342
17496
  if (!panel) return;
@@ -17547,7 +17701,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17547
17701
  refresh();
17548
17702
  loadRecent();
17549
17703
  })();
17550
- `;var Gl=`
17704
+ `;var id=`
17551
17705
  (function () {
17552
17706
  var panel = document.getElementById('panel-alerts');
17553
17707
  if (!panel) return;
@@ -17699,7 +17853,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17699
17853
  document.addEventListener('visibilitychange', function () { if (!document.hidden && state) load(); });
17700
17854
  load();
17701
17855
  })();
17702
- `,Xl=`
17856
+ `,ld=`
17703
17857
  .pl-card { margin-top: 12px; }
17704
17858
  .pl-list { margin-top: 8px; }
17705
17859
  .pl-rules { list-style: none; margin: 6px 0 0; padding: 0; }
@@ -17718,7 +17872,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17718
17872
  .pl-check { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); }
17719
17873
  .pl-check input { width: 20px; height: 20px; }
17720
17874
  #pl-here { justify-self: start; }
17721
- `;function Kl(t,e,a){return t!==1?"Could not find where you are. Try again outdoors, or type the coordinates.":e&&a!=="denied"?"The location was refused. If you tapped Don\u2019t allow, allow location for AgentX in the phone\u2019s settings. Otherwise Chrome hasn\u2019t linked the AgentX app yet: Force stop Chrome once (Settings \u203A Apps \u203A Chrome \u203A Force stop), then open AgentX again. Or type the coordinates.":"Location is blocked for this app. Allow it in the phone\u2019s settings, or type the coordinates."}var Jl=`
17875
+ `;function dd(t,e,a){return t!==1?"Could not find where you are. Try again outdoors, or type the coordinates.":e&&a!=="denied"?"The location was refused. If you tapped Don\u2019t allow, allow location for AgentX in the phone\u2019s settings. Otherwise Chrome hasn\u2019t linked the AgentX app yet: Force stop Chrome once (Settings \u203A Apps \u203A Chrome \u203A Force stop), then open AgentX again. Or type the coordinates.":"Location is blocked for this app. Allow it in the phone\u2019s settings, or type the coordinates."}var cd=`
17722
17876
  (function () {
17723
17877
  var panel = document.getElementById('panel-alerts');
17724
17878
  if (!panel) return;
@@ -17831,7 +17985,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17831
17985
  }
17832
17986
  load();
17833
17987
  })();
17834
- `;var Vl=`
17988
+ `;var pd=`
17835
17989
  (function () {
17836
17990
  var panel = document.getElementById('panel-chat');
17837
17991
  var V = window.AXChatView;
@@ -18114,7 +18268,7 @@ details[open] > summary::before { transform: rotate(90deg); }
18114
18268
  var last = recall('ax-chat-conv');
18115
18269
  if (!fromHash() && last) openConversation(last);
18116
18270
  })();
18117
- `;var Yl=`
18271
+ `;var ud=`
18118
18272
  window.AXChatView = (function () {
18119
18273
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
18120
18274
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -18395,7 +18549,7 @@ window.AXChatView = (function () {
18395
18549
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
18396
18550
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
18397
18551
  })();
18398
- `;var Ql=`
18552
+ `;var md=`
18399
18553
  window.AXChatSheets = function (o) {
18400
18554
  var V = o.V, picker = o.picker, hist = o.hist;
18401
18555
  function loadPicker() {
@@ -18441,7 +18595,7 @@ window.AXChatSheets = function (o) {
18441
18595
  });
18442
18596
  return { loadPicker: loadPicker, loadHistory: loadHistory };
18443
18597
  };
18444
- `;var Zl=`
18598
+ `;var fd=`
18445
18599
  window.AXChatLog = function (o) {
18446
18600
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
18447
18601
  function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
@@ -18504,7 +18658,7 @@ window.AXChatLog = function (o) {
18504
18658
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
18505
18659
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
18506
18660
  };
18507
- `;var ed=`
18661
+ `;var hd=`
18508
18662
  (function () {
18509
18663
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
18510
18664
  var top = panel && panel.querySelector('.cx-top');
@@ -18654,7 +18808,7 @@ window.AXChatLog = function (o) {
18654
18808
  window.AXStrip = { poll: poll, update: update, banner: banner };
18655
18809
  poll();
18656
18810
  })();
18657
- `;var td=`
18811
+ `;var gd=`
18658
18812
  .cs { margin: 0 -2px; }
18659
18813
  .cs[hidden] { display: none; }
18660
18814
  .cs-list {
@@ -18710,7 +18864,7 @@ window.AXChatLog = function (o) {
18710
18864
  @media (prefers-reduced-motion: reduce) {
18711
18865
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
18712
18866
  }
18713
- `;function ad(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 nd(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var rd=`
18867
+ `;function xd(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 bd(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var vd=`
18714
18868
  body { height: 100dvh; }
18715
18869
  main { min-height: 0; }
18716
18870
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -18820,7 +18974,7 @@ main { min-height: 0; }
18820
18974
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
18821
18975
  }
18822
18976
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
18823
- `;var od=`
18977
+ `;var yd=`
18824
18978
  window.AXOrb = (function () {
18825
18979
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
18826
18980
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -18937,7 +19091,7 @@ window.AXOrb = (function () {
18937
19091
  }
18938
19092
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
18939
19093
  })();
18940
- `;var sd=`
19094
+ `;var wd=`
18941
19095
  window.AXVoiceIO = (function () {
18942
19096
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
18943
19097
  var ac = null, playing = null;
@@ -19055,7 +19209,7 @@ window.AXVoiceIO = (function () {
19055
19209
 
19056
19210
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
19057
19211
  })();
19058
- `;var id=`
19212
+ `;var kd=`
19059
19213
  (function () {
19060
19214
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
19061
19215
  if (!panel || !C || !IO || !O) return;
@@ -19268,7 +19422,7 @@ window.AXVoiceIO = (function () {
19268
19422
  idle();
19269
19423
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
19270
19424
  })();
19271
- `;var ld=`
19425
+ `;var _d=`
19272
19426
  .vx {
19273
19427
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
19274
19428
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -19304,7 +19458,7 @@ window.AXVoiceIO = (function () {
19304
19458
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
19305
19459
  .cx-typing-on .vx-row { gap: 16px; }
19306
19460
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
19307
- `;var dd=`
19461
+ `;var Sd=`
19308
19462
  <main class="card">
19309
19463
  <h1>This phone isn't paired</h1>
19310
19464
  <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>
@@ -19318,7 +19472,7 @@ window.AXVoiceIO = (function () {
19318
19472
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
19319
19473
  </form>
19320
19474
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
19321
- </main>`,cd=`
19475
+ </main>`,Ed=`
19322
19476
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
19323
19477
  .pair-form label { font-weight: 600; }
19324
19478
  .pair-form input {
@@ -19340,7 +19494,7 @@ window.AXVoiceIO = (function () {
19340
19494
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
19341
19495
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
19342
19496
  }
19343
- `,pd=`
19497
+ `,Td=`
19344
19498
  (function () {
19345
19499
  var form = document.getElementById('pair-form');
19346
19500
  var input = document.getElementById('pair-code');
@@ -19432,7 +19586,7 @@ window.AXVoiceIO = (function () {
19432
19586
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
19433
19587
  }
19434
19588
  })();
19435
- `;var ud=`
19589
+ `;var Ad=`
19436
19590
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
19437
19591
  <video id="scan-video" playsinline muted autoplay></video>
19438
19592
  <div class="scan-frame" aria-hidden="true"></div>
@@ -19441,7 +19595,7 @@ window.AXVoiceIO = (function () {
19441
19595
  <button type="button" id="scan-close" class="scan-close">Close</button>
19442
19596
  </div>
19443
19597
  <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>
19444
- </div>`,md=`
19598
+ </div>`,Cd=`
19445
19599
  .pair-form .scan-btn {
19446
19600
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
19447
19601
  }
@@ -19470,7 +19624,7 @@ window.AXVoiceIO = (function () {
19470
19624
  }
19471
19625
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
19472
19626
  body.scanning { overflow: hidden; }
19473
- `,fd=`
19627
+ `,Id=`
19474
19628
  (function () {
19475
19629
  var openBtn = document.getElementById('scan-btn');
19476
19630
  var box = document.getElementById('scan');
@@ -19636,7 +19790,7 @@ body.scanning { overflow: hidden; }
19636
19790
  document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
19637
19791
  window.addEventListener('pagehide', close);
19638
19792
  })();
19639
- `;var hn=`
19793
+ `;var yn=`
19640
19794
  .cam { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; background: var(--ax-bg); }
19641
19795
  .cam[hidden] { display: none; }
19642
19796
  .cam-live {
@@ -19695,7 +19849,7 @@ body.scanning { overflow: hidden; }
19695
19849
  @keyframes cam-pulse { 50% { opacity: .3; } }
19696
19850
  @media (prefers-reduced-motion: reduce) { .cam-live.is-stream .cam-dot { animation: none; } }
19697
19851
  #cam-stream[aria-pressed="true"] { border-color: var(--ax-red); color: var(--ax-red-ink); }
19698
- `;var hd='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h12v12H3zM15 10l6-3v10l-6-3"/></svg><span>Share camera</span></button>',gd=`
19852
+ `;var Md='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h12v12H3zM15 10l6-3v10l-6-3"/></svg><span>Share camera</span></button>',Rd=`
19699
19853
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
19700
19854
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
19701
19855
  <span class="cam-dot" aria-hidden="true"></span>
@@ -19724,7 +19878,7 @@ body.scanning { overflow: hidden; }
19724
19878
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
19725
19879
  </div>
19726
19880
  </div>
19727
- </div>`,xd=`
19881
+ </div>`,Ld=`
19728
19882
  (function () {
19729
19883
  var btn = document.getElementById('cam-btn');
19730
19884
  var sheet = document.getElementById('cam');
@@ -20198,7 +20352,7 @@ body.scanning { overflow: hidden; }
20198
20352
  });
20199
20353
  window.addEventListener('pagehide', function () { stop(); });
20200
20354
  })();
20201
- `;var bd=`
20355
+ `;var Pd=`
20202
20356
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
20203
20357
  <div class="cam-askbar-text">
20204
20358
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -20208,7 +20362,7 @@ body.scanning { overflow: hidden; }
20208
20362
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
20209
20363
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
20210
20364
  </div>
20211
- </div>`,vd=`
20365
+ </div>`,$d=`
20212
20366
  .cam-askbar[hidden] { display: none; }
20213
20367
  .cam-askbar {
20214
20368
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -20223,7 +20377,7 @@ body.scanning { overflow: hidden; }
20223
20377
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
20224
20378
  }
20225
20379
  .cam-askbar-no { background: transparent; color: #fff; }
20226
- `,yd=`
20380
+ `,jd=`
20227
20381
  (function () {
20228
20382
  var bar = document.getElementById('cam-ask-bar');
20229
20383
  if (!bar) return;
@@ -20293,7 +20447,7 @@ body.scanning { overflow: hidden; }
20293
20447
  setInterval(poll, 5000);
20294
20448
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
20295
20449
  })();
20296
- `;function wd(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 kd(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}function _d(t){return t>=400?"send":"listen"}function Sd(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var Ed=`
20450
+ `;function Od(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 Nd(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}function Dd(t){return t>=400?"send":"listen"}function Hd(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var Bd=`
20297
20451
  (function () {
20298
20452
  var main = document.querySelector('main');
20299
20453
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
@@ -20412,7 +20566,7 @@ body.scanning { overflow: hidden; }
20412
20566
  main.addEventListener('touchend', function () { end(false); });
20413
20567
  main.addEventListener('touchcancel', function () { end(true); });
20414
20568
  })();
20415
- `,Td=`
20569
+ `,qd=`
20416
20570
  main { position: relative; }
20417
20571
  main.sw-on { overflow: hidden; }
20418
20572
  .sw-on > [role=tabpanel] { will-change: transform; }
@@ -20423,8 +20577,8 @@ main > .sw-peek {
20423
20577
  }
20424
20578
  main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
20425
20579
  @media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
20426
- `;function Ad(t){let e=["INPUT","TEXTAREA","SELECT","DIALOG"];return!t.some(a=>a.scrollsX||a.editable||a.touchAction==="none"||a.touchAction==="pan-x"||e.indexOf(a.tag)>=0)}function Cd(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Id(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Md(t,e,a,n,r){if(!(Math.abs(r)>.5?r*a>0&&Math.abs(a)>30:Math.abs(a)>n/3))return t;let i=t+(a<0?1:-1);return i<0||i>=e?t:i}var gn=`
20427
- ${z({afterUnauthorized:$o})}
20580
+ `;function zd(t){let e=["INPUT","TEXTAREA","SELECT","DIALOG"];return!t.some(a=>a.scrollsX||a.editable||a.touchAction==="none"||a.touchAction==="pan-x"||e.indexOf(a.tag)>=0)}function Fd(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Ud(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Wd(t,e,a,n,r){if(!(Math.abs(r)>.5?r*a>0&&Math.abs(a)>30:Math.abs(a)>n/3))return t;let i=t+(a<0?1:-1);return i<0||i>=e?t:i}var wn=`
20581
+ ${z({afterUnauthorized:Go})}
20428
20582
  var CACHE = 'agentx-app-v3';
20429
20583
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
20430
20584
  self.addEventListener('install', function (e) {
@@ -20515,7 +20669,7 @@ self.addEventListener('notificationclick', function (e) {
20515
20669
  return self.clients.openWindow(target);
20516
20670
  }));
20517
20671
  });
20518
- `;var ah="<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 xn(t){return`<meta charset="utf-8">
20672
+ `;var yh="<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 kn(t){return`<meta charset="utf-8">
20519
20673
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
20520
20674
  <meta name="theme-color" content="#2979FF">
20521
20675
  <meta name="referrer" content="no-referrer">
@@ -20526,58 +20680,59 @@ self.addEventListener('notificationclick', function (e) {
20526
20680
  <link rel="icon" type="image/png" href="/app/icon-192.png">
20527
20681
  <link rel="apple-touch-icon" href="/app/icon-192.png">
20528
20682
  <title>${t}</title>
20529
- ${ah}
20530
- <style>${qe}${Bl}${sh}</style>`}var nh={chat:"M21 11.5a8.5 8.5 0 0 1-8.5 8.5H4l-2 2V11.5a9.5 9.5 0 0 1 19 0Z",fleet:"M3 3h18v13H3zM8 21h8M12 16v5",activity:"M3 12h4l3-8 4 16 3-8h4",alerts:"M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4"},Ld=[{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 Rd(){let t=Ld.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}"><span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="${nh[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=Ld.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20683
+ ${yh}
20684
+ <style>${Ue}${Zl}${Sh}</style>`}var wh={chat:"M21 11.5a8.5 8.5 0 0 1-8.5 8.5H4l-2 2V11.5a9.5 9.5 0 0 1 19 0Z",fleet:"M3 3h18v13H3zM8 21h8M12 16v5",activity:"M3 12h4l3-8 4 16 3-8h4",alerts:"M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4",desk:"M3 13l3-8h12l3 8v6H3zM3 13h5l1 3h6l1-3h5"},Gd=[{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"},{id:"desk",label:"Desk",soon:"Loading what waits for you\u2026"}];function Xd(){let t=Gd.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}"><span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="${wh[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=Gd.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20531
20685
  <h2>${a.label}</h2>
20532
20686
  <p class="soon">${a.soon}</p>
20533
20687
  </section>`).join("");return`<!doctype html>
20534
20688
  <html lang="en">
20535
- <head>${xn("AgentX")}<style>${ih}${Ul}${rd}${td}${ld}${hn}${vd}${Td}${Xl}${ql}</style></head>
20689
+ <head>${kn("AgentX")}<style>${Eh}${nd}${od}${vd}${gd}${_d}${yn}${$d}${qd}${ld}${ed}</style></head>
20536
20690
  <body>
20537
20691
  <header class="bar">
20538
20692
  <div>
20539
20693
  <h1>AgentX</h1>
20540
20694
  <p id="who" class="who">Connecting\u2026</p>
20541
20695
  </div>
20542
- <div class="bar-btns">${hd}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 15.5A9 9 0 0 1 8.5 4 9 9 0 1 0 20 15.5Z"/></svg></button></div>
20696
+ <div class="bar-btns">${Md}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 15.5A9 9 0 0 1 8.5 4 9 9 0 1 0 20 15.5Z"/></svg></button></div>
20543
20697
  </header>
20544
20698
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
20545
- ${bd}
20699
+ ${Pd}
20546
20700
  <main>${e}</main>
20547
20701
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
20548
- ${gd}
20549
- <script>${rh}</script>
20550
- <script>${z({swipeMayStart:Ad,swipeAxis:Cd,swipeOffset:Id,swipeLanding:Md})}${Ed}</script>
20551
- <script>${zl}</script>
20552
- <script>${Fl}</script>
20553
- <script>${Wl}</script>
20554
- <script>${z({locationErrorText:Kl})}${Gl}</script>
20555
- <script>${Jl}</script>
20556
- <script>${z({markdownToHtml:hr})}${Yl}${Zl}${Ql}${Vl}</script>
20557
- <script>${z({queueSpeech:ad,nextSpeech:nd})}${od}${sd}${id}</script>
20558
- <script>${ed}</script>
20559
- <script>${z({cameraConstraints:wd,shareClock:kd,streamLabel:Sd,talkRelease:_d})}${xd}</script>
20560
- <script>${yd}</script>
20702
+ ${Rd}
20703
+ <script>${kh}</script>
20704
+ <script>${z({swipeMayStart:zd,swipeAxis:Fd,swipeOffset:Ud,swipeLanding:Wd})}${Bd}</script>
20705
+ <script>${td}</script>
20706
+ <script>${ad}</script>
20707
+ <script>${rd}</script>
20708
+ <script>${sd}</script>
20709
+ <script>${z({locationErrorText:dd})}${id}</script>
20710
+ <script>${cd}</script>
20711
+ <script>${z({markdownToHtml:Tr})}${ud}${fd}${md}${pd}</script>
20712
+ <script>${z({queueSpeech:xd,nextSpeech:bd})}${yd}${wd}${kd}</script>
20713
+ <script>${hd}</script>
20714
+ <script>${z({cameraConstraints:Od,shareClock:Nd,streamLabel:Hd,talkRelease:Dd})}${Ld}</script>
20715
+ <script>${jd}</script>
20561
20716
  </body>
20562
- </html>`}function Pd(){return`<!doctype html>
20717
+ </html>`}function Kd(){return`<!doctype html>
20563
20718
  <html lang="en">
20564
- <head>${xn("Pair \xB7 AgentX")}</head>
20719
+ <head>${kn("Pair \xB7 AgentX")}</head>
20565
20720
  <body>
20566
20721
  <main class="card">
20567
20722
  <h1>Pairing this phone\u2026</h1>
20568
20723
  <p id="msg" role="status">One moment.</p>
20569
20724
  </main>
20570
- <script>${oh}</script>
20725
+ <script>${_h}</script>
20571
20726
  </body>
20572
- </html>`}function $d(){return`<!doctype html>
20727
+ </html>`}function Jd(){return`<!doctype html>
20573
20728
  <html lang="en">
20574
- <head>${xn("Not paired \xB7 AgentX")}<style>${cd}${md}</style></head>
20575
- <body>${dd}${ud}
20576
- <script>${z({mayBounce:jo,formatPairInput:Ft,parsePairScan:Oo})}</script>
20577
- <script>${pd}</script>
20578
- <script>${fd}</script>
20729
+ <head>${kn("Not paired \xB7 AgentX")}<style>${Ed}${Cd}</style></head>
20730
+ <body>${Sd}${Ad}
20731
+ <script>${z({mayBounce:Xo,formatPairInput:Gt,parsePairScan:Ko})}</script>
20732
+ <script>${Td}</script>
20733
+ <script>${Id}</script>
20579
20734
  </body>
20580
- </html>`}function jd(){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:"#FFFFFF",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 rh=`
20735
+ </html>`}function Vd(){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:"#FFFFFF",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 kh=`
20581
20736
  (function () {
20582
20737
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
20583
20738
  function select(tab, focus, keepHash) {
@@ -20649,7 +20804,7 @@ ${gd}
20649
20804
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
20650
20805
  }
20651
20806
  })();
20652
- `,oh=`
20807
+ `,_h=`
20653
20808
  (function () {
20654
20809
  var msg = document.getElementById('msg');
20655
20810
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -20666,7 +20821,7 @@ ${gd}
20666
20821
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
20667
20822
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
20668
20823
  })();
20669
- `,sh=`
20824
+ `,Sh=`
20670
20825
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
20671
20826
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
20672
20827
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -20678,7 +20833,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
20678
20833
  .card h1 { font-size: 22px; margin: 0 0 12px; }
20679
20834
  .muted { color: var(--ax-text-2); }
20680
20835
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
20681
- `,ih=`
20836
+ `,Eh=`
20682
20837
  body { display: flex; flex-direction: column; }
20683
20838
  .bar {
20684
20839
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -20704,7 +20859,7 @@ main {
20704
20859
  main h2 { font-size: 20px; margin: 4px 0 8px; }
20705
20860
  .soon { color: var(--ax-text-2); line-height: 1.55; margin: 0; }
20706
20861
  .tabs {
20707
- display: grid; grid-template-columns: repeat(4, 1fr);
20862
+ display: grid; grid-template-columns: repeat(5, 1fr);
20708
20863
  position: sticky; bottom: 0;
20709
20864
  padding: 6px calc(6px + env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) calc(6px + env(safe-area-inset-left));
20710
20865
  background: var(--ax-surface); border-top: var(--ax-border-w) solid var(--ax-border);
@@ -20716,8 +20871,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20716
20871
  }
20717
20872
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
20718
20873
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
20719
- `;var la="agentx_app",ch=400*86400,ph=new At,uh=new Ie;async function Od(t,e,a,n,r={}){if(a==="/.well-known/assetlinks.json"&&n==="GET"){let i=r.assetLinks?.()??null;return i?me(e,200,"application/json",JSON.stringify(i),"public, max-age=300"):_e(e,404,{error:"not found"})}if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new G;if(n==="GET"){if(a==="/app/manifest.webmanifest")return me(e,200,"application/manifest+json",jd());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),me(e,200,"text/javascript; charset=utf-8",gn);if(a==="/app/icon-192.png")return me(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/app/icon-512.png")return me(e,200,"image/png",Fe(512),"public, max-age=86400");if(a==="/app/pair")return me(e,200,"text/html; charset=utf-8",Pd());if(a==="/app/qr.js"){let i=mh();return i?me(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):_e(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=bn(ot(t),o);return i?(e.setHeader("Set-Cookie",vn(ot(t))),_e(e,200,{device:i.name})):_e(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await fr(t,{codes:r.pairCodes??new kt,limiter:r.pairLimiter??ph,verify:l=>bn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",vn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),_e(e,i.status,i.body)}let s=bn(fh(t),o);if(!s){let i=ot(t);return(r.rejectLog??uh).record(a.slice(0,120),Bt(t,ze(yn(t,la),o),i?ze(i,o):null)),a==="/app"?me(e,401,"text/html; charset=utf-8",$d()):_e(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=yn(t,la);return i&&!ot(t)&&e.setHeader("Set-Cookie",vn(i)),me(e,200,"text/html; charset=utf-8",Rd())}return n==="GET"&&a==="/api/app/me"?_e(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await ir(t,e,a,n,s.name,r.fleet)||r.push&&await lr(t,e,a,n,s,r.push)||r.announce&&await tl(t,e,a,n,s,r.announce)||r.chat&&await ul(t,e,a,n,s,r.chat)||r.chat&&await gl(t,e,a,n,s,r.chat)||r.voice&&await vl(t,e,a,n,s,r.voice)||r.camera&&await wl(t,e,a,n,r.camera)||r.places&&await jl(t,e,a,n,s,r.places)?!0:_e(e,404,{error:"not found"})}var rt;function mh(){if(rt!==void 0)return rt;try{let t=dh(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
20720
- `;rt=Buffer.concat([Buffer.from(a),lh(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),rt=null}return rt}function bn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ee(a,"app")?a:null}function vn(t){return`${la}=${t}; Path=/; Max-Age=${ch}; HttpOnly; Secure; SameSite=Lax`}function fh(t){return ot(t)??yn(t,la)}function ot(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function yn(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 me(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function _e(t,e,a){return me(t,e,"application/json",JSON.stringify(a))}function Nd(t){let e=pe({kicker:"Phone",title:"Places",lead:"Places your phone watches, and what to remind you of when you arrive or leave. The AgentX Android app on your phone notices the crossing and tells this computer only which place and which way: never where you are."})+`
20874
+ `;var ua="agentx_app",Ch=400*86400,Ih=new Mt,Mh=new Re;async function Yd(t,e,a,n,r={}){if(a==="/.well-known/assetlinks.json"&&n==="GET"){let i=r.assetLinks?.()??null;return i?fe(e,200,"application/json",JSON.stringify(i),"public, max-age=300"):Ee(e,404,{error:"not found"})}if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new G;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",Vd());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",wn);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Ge(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Ge(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",Kd());if(a==="/app/qr.js"){let i=Rh();return i?fe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Ee(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=_n(dt(t),o);return i?(e.setHeader("Set-Cookie",Sn(dt(t))),Ee(e,200,{device:i.name})):Ee(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Er(t,{codes:r.pairCodes??new Tt,limiter:r.pairLimiter??Ih,verify:l=>_n(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Sn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ee(e,i.status,i.body)}let s=_n(Lh(t),o);if(!s){let i=dt(t);return(r.rejectLog??Mh).record(a.slice(0,120),Ft(t,We(En(t,ua),o),i?We(i,o):null)),a==="/app"?fe(e,401,"text/html; charset=utf-8",Jd()):Ee(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=En(t,ua);return i&&!dt(t)&&e.setHeader("Set-Cookie",Sn(i)),fe(e,200,"text/html; charset=utf-8",Xd())}return n==="GET"&&a==="/api/app/me"?Ee(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await gr(t,e,a,n,s.name,r.fleet)||r.desk&&await pl(t,e,a,n,r.desk)||r.push&&await xr(t,e,a,n,s,r.push)||r.announce&&await fl(t,e,a,n,s,r.announce)||r.chat&&await El(t,e,a,n,s,r.chat)||r.chat&&await Il(t,e,a,n,s,r.chat)||r.voice&&await Ll(t,e,a,n,s,r.voice)||r.camera&&await $l(t,e,a,n,r.camera)||r.places&&await Kl(t,e,a,n,s,r.places)?!0:Ee(e,404,{error:"not found"})}var lt;function Rh(){if(lt!==void 0)return lt;try{let t=Ah(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
20875
+ `;lt=Buffer.concat([Buffer.from(a),Th(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),lt=null}return lt}function _n(t,e){if(!t)return null;let a=e.verify(t);return a&&Ae(a,"app")?a:null}function Sn(t){return`${ua}=${t}; Path=/; Max-Age=${Ch}; HttpOnly; Secure; SameSite=Lax`}function Lh(t){return dt(t)??En(t,ua)}function dt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function En(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ee(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}function Qd(t){let e=ue({kicker:"Phone",title:"Places",lead:"Places your phone watches, and what to remind you of when you arrive or leave. The AgentX Android app on your phone notices the crossing and tells this computer only which place and which way: never where you are."})+`
20721
20876
  <div class="pl-wrap">
20722
20877
  <div id="pl-msg" class="pl-msg" role="status" aria-live="polite"></div>
20723
20878
  <form id="pl-add" class="pl-form" autocomplete="off">
@@ -20729,7 +20884,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20729
20884
  <button type="submit" class="ax-btn ax-btn--primary">Add place</button>
20730
20885
  </form>
20731
20886
  <ol id="pl-list" class="pl-list" aria-label="Places"><li class="pl-empty">Loading\u2026</li></ol>
20732
- </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:hh,scripts:`<script>${gh}</script>`})}var hh=`
20887
+ </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:Ph,scripts:`<script>${$h}</script>`})}var Ph=`
20733
20888
  .pl-wrap { max-width: 1040px; margin: 0 auto; padding: 0 24px 96px; box-sizing: border-box; }
20734
20889
  .pl-msg { min-height: 1.4em; margin: 8px 0 0; }
20735
20890
  .pl-msg.is-bad { color: var(--ax-red-ink); }
@@ -20752,7 +20907,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20752
20907
  .pl-rule-form { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
20753
20908
  .pl-rule-form input[name=text] { flex: 1 1 240px; }
20754
20909
  .pl-btns { margin-left: auto; display: flex; gap: 8px; }
20755
- `,gh=`
20910
+ `,$h=`
20756
20911
  (function () {
20757
20912
  var list = document.getElementById('pl-list');
20758
20913
  var msg = document.getElementById('pl-msg');
@@ -20831,7 +20986,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20831
20986
  });
20832
20987
  load();
20833
20988
  })();
20834
- `;import{randomBytes as Dd}from"crypto";var He={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ce.perMessage},xh=/^[a-f0-9]{32}$/,bh=/^c[a-z0-9]{8,32}$/,vh=/^#[0-9a-fA-F]{6}$/;function wn(t){return bh.test(t)}var st=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
20989
+ `;import{randomBytes as Zd}from"crypto";var Be={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:pe.perMessage},jh=/^[a-f0-9]{32}$/,Oh=/^c[a-z0-9]{8,32}$/,Nh=/^#[0-9a-fA-F]{6}$/;function Tn(t){return Oh.test(t)}var ct=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
20835
20990
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
20836
20991
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
20837
20992
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -20844,39 +20999,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20844
20999
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
20845
21000
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
20846
21001
  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 (
20847
- key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return wn(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)}${Dd(4).toString("hex")}`,{color:s,...i}=a,l=s&&vh.test(s)?s:void 0,d={id:o,title:wh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
20848
- (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,d.title,d.node,d.nodeName,d.agent,d.agentName??null,l??null,r,r,r),this.pruneDevice(e),d}get(e,a){if(!wn(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(yh);return{...Hd(n),messages:r}}list(e,a=He.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
21002
+ key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Tn(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)}${Zd(4).toString("hex")}`,{color:s,...i}=a,l=s&&Nh.test(s)?s:void 0,d={id:o,title:Hh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
21003
+ (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,d.title,d.node,d.nodeName,d.agent,d.agentName??null,l??null,r,r,r),this.pruneDevice(e),d}get(e,a){if(!Tn(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(Dh);return{...ec(n),messages:r}}list(e,a=Be.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
20849
21004
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
20850
21005
  (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
20851
- 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{...Hd(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){wn(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,
21006
+ 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{...ec(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Tn(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,
20852
21007
  substr(m.content, 1, 240) AS answer, m.status, m.at
20853
21008
  FROM app_chat_conversations c
20854
21009
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
20855
21010
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
20856
- 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>He.content?n.content.slice(0,He.content)+`
21011
+ 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>Be.content?n.content.slice(0,Be.content)+`
20857
21012
 
20858
- [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,He.toolsPerMessage),l=[];for(let m of r){if(l.length>=He.filesPerMessage)break;let g=m.filename.trim(),_=Yn(g);if(!_||!g||g.length>ce.pathChars||g.includes("\0"))continue;let y=(g.split(/[\\/]/).pop()||g).slice(0,120);l.push({id:Dd(16).toString("hex"),name:y,mime:_.mime,kind:_.kind,path:g})}let d=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),c=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
20859
- 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,d.length?JSON.stringify(d):null,n.at),p=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
20860
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)p.run(m.id,a,Number(c.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
20861
- (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,He.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
20862
- (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),d}getFile(e,a){if(!xh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
21013
+ [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Be.toolsPerMessage),l=[];for(let m of r){if(l.length>=Be.filesPerMessage)break;let g=m.filename.trim(),k=sr(g);if(!k||!g||g.length>pe.pathChars||g.includes("\0"))continue;let b=(g.split(/[\\/]/).pop()||g).slice(0,120);l.push({id:Zd(16).toString("hex"),name:b,mime:k.mime,kind:k.kind,path:g})}let d=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)
21014
+ 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,d.length?JSON.stringify(d):null,n.at),c=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
21015
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)c.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
21016
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Be.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
21017
+ (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),d}getFile(e,a){if(!jh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
20863
21018
  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 = ?
20864
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,He.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 Hd(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 yh(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 wh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var kh=4e3,kn=100,_h=15,Bd=t=>t.replace(/\/+$/,""),da=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=kh){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,kn);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??_h)-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>=kn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${kn}); 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||Bd(l)!==Bd(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 d=Sh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,d.row,d.declared)===null)return"skip";let p=d.row.status,m=!!this.deps.finishAlerts?.(s),g={status:p,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&oa(g)&&this.deps.notifyFinish(sa(s,i,p,d.row.content,d.row.error)).catch(()=>{}),"filed"}};function Sh(t,e){let a=t.plain?{text:xt(t.text,!1),artifacts:[]}:gt(t.text,ce.perMessage,!1),{cleanText:n,ui:r}=vt(a.text),o=t.plain?void 0:ln(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Eh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Eh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}On();function Ve(){let t=ut();return t&&ke(t,"dashboard"),t}function U0(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let g of a)try{s.set(g.id,Nh(g,t))}catch(_){console.error(` Board "${g.id}" failed to initialize: ${_.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?it(process.cwd(),t.workflows.dir):void 0,d=new Wn(l?{baseDir:l}:void 0),c=new Gn(l?{baseDir:l,nodeId:i}:{nodeId:i}),p=new Xn(l?{baseDir:l}:void 0);vi(t),Ve(),kr({business:t.business?.enabled===!0});let m=Th(async(g,_)=>{try{await Ph(g,_,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:c,workflowLayouts:p})}catch(y){w(_,500,{error:y.message||"internal error"})}});eg(t).start(),m.listen(n,r,()=>{let g=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
21019
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Be.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 ec(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 Dh(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 Hh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Bh=4e3,An=100,qh=15,tc=t=>t.replace(/\/+$/,""),ma=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Bh){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,An);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??qh)-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>=An&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${An}); 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||tc(l)!==tc(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 d=zh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,d.row,d.declared)===null)return"skip";let c=d.row.status,m=!!this.deps.finishAlerts?.(s),g={status:c,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&da(g)&&this.deps.notifyFinish(ca(s,i,c,d.row.content,d.row.error)).catch(()=>{}),"filed"}};function zh(t,e){let a=t.plain?{text:kt(t.text,!1),artifacts:[]}:wt(t.text,pe.perMessage,!1),{cleanText:n,ui:r}=St(a.text),o=t.plain?void 0:mn(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Fh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Fh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Wn();var Uh=3,Cn=7,In=50,Mn=120,Wh=280,nc=600,rc=36e5,Gh=24*rc;function pt(t,e){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}var fa=t=>new Date(t).toISOString();function Xh(t,e,a){let n=e.key.slice(0,Math.max(0,e.key.indexOf(":")))||"card";return{key:e.key,kind:n,column:"yours",node:t.node,nodeName:t.nodeName,title:pt(e.title,Mn),...e.ask?{ask:pt(e.ask,nc)}:{},...e.detail?{facts:pt(e.detail,Wh)}:{},...e.recommend?{recommend:e.recommend}:{},...e.raisedBy?{agent:e.raisedBy}:{},...e.yes?{yes:e.yes}:{},...e.no?{no:e.no}:{},...e.choices?.length?{choices:e.choices}:{},...e.draft?{draft:e.draft}:{},...e.expires?{expires:e.expires}:{},...e.createdAt?{askedAt:e.createdAt}:{},can:{answer:!0,later:!0,reply:a&&n==="request"}}}var Kh={done:"Done",declined:"Declined",dropped:"Dropped"};function Jh(t,e,a){let{record:n,links:r}=e,o={key:`request:${n.id}`,kind:"request",node:t.node,nodeName:t.nodeName,title:Ar(n.text,Mn),agent:n.agentId,askedAt:fa(n.createdAt),changedAt:fa(n.updatedAt)};switch(n.state){case"candidate":case"needs_attention":return null;case"waiting_owner":return r.some(s=>s.kind==="card"&&a.has(`card:${s.ref}`))?null:{...o,column:"yours",...n.question?{ask:pt(n.question,nc)}:{},can:{answer:!1,later:!1,reply:!0}};case"in_progress":case"waiting_other":{let s=r.some(l=>l.kind==="run"&&t.liveRuns.has(l.ref)),i=t.now-n.updatedAt<(t.quietHours??Uh)*rc;return{...o,column:s||i?"agent":"quiet",...s?{live:s}:{},can:{answer:!1,later:!1,reply:!s}}}default:{let s=n.state==="done"?n.evidence:n.closeReason;return{...o,column:"done",changedAt:fa(n.closedAt??n.updatedAt),outcome:Kh[n.state]??n.state,...s?{evidence:s}:{},can:{answer:!1,later:!1,reply:!1}}}}}function Vh(t){return t.status==="decided"?t.verdict==="yes"?`Answered yes${t.choice?`: ${t.choice}`:""}`:"Answered no":t.status==="expired"?`No answer in time: ${t.outcome==="discard"?"discarded":t.outcome==="pause"?"paused":"kept"}`:"Closed by the agent"}function Yh(t,e){return{key:`card:${e.id}`,kind:"card",column:"done",node:t.node,nodeName:t.nodeName,title:pt(e.title,Mn),ask:e.ask,agent:e.raised_by,askedAt:e.created_at,...e.decided_at?{changedAt:e.decided_at}:{},outcome:Vh(e),...e.resolution?{evidence:e.resolution}:{},can:{answer:!1,later:!1,reply:!1}}}var de=t=>t&&Date.parse(t)||0,ac=(t,e)=>t.map(a=>a[e]).filter(a=>!!de(a)).sort((a,n)=>de(a)-de(n))[0];function oc(t){let e=[],a=[];for(let c of t.inbox){c.error&&a.push(`What waits on ${c.nodeName} could not be read: ${c.error}`);for(let m of c.items)e.push(Xh(c,m,c.node===t.node))}let n=new Set([...e.filter(c=>c.node===t.node).map(c=>c.key),...t.deferred??[]]),r=[],o=[],s=[];for(let c of t.requests??[]){let m=Jh(t,c,n);m&&{yours:e,agent:r,quiet:o,done:s}[m.column].push(m)}let i=t.now-(t.doneDays??Cn)*Gh;for(let c of t.cards)c.status!=="pending"&&de(c.decided_at)>=i&&s.push(Yh(t,c));r.sort((c,m)=>de(m.changedAt)-de(c.changedAt)),o.sort((c,m)=>de(c.changedAt)-de(m.changedAt)),s.sort((c,m)=>de(m.changedAt)-de(c.changedAt));let l=s.filter(c=>de(c.changedAt)>=i).slice(0,In),d=ac(e,"askedAt"),p=ac(o,"changedAt");return{ts:fa(t.now),cards:[...e,...r,...o,...l],figures:{yours:{count:e.length,...d?{oldest:d}:{}},agent:{count:r.length},quiet:{count:o.length,...p?{oldest:p}:{}},done:{count:l.length}},errors:a}}function Ze(){let t=xt();return t&&Se(t,"dashboard"),t}function M_(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let g of a)try{s.set(g.id,dg(g,t))}catch(k){console.error(` Board "${g.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?ut(process.cwd(),t.workflows.dir):void 0,d=new er(l?{baseDir:l}:void 0),p=new tr(l?{baseDir:l,nodeId:i}:{nodeId:i}),c=new ar(l?{baseDir:l}:void 0);Mi(t),Ze(),$r({business:t.business?.enabled===!0});let m=Qh(async(g,k)=>{try{await og(g,k,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:c})}catch(b){w(k,500,{error:b.message||"internal error"})}});Ag(t).start(),m.listen(n,r,()=>{let g=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
20865
21020
  Live dashboard: http://${g}:${n}
20866
21021
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
20867
21022
  Kanban dashboard: http://${g}:${n}
20868
- `),console.log(` Boards: ${a.map(_=>_.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 Rh=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/places","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Ph(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if((t.url||"/").split(/[?#]/)[0]!==r){w(e,404,{error:"not found"});return}if(yr(t.headers)==="foreign"&&wr(o)){w(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ss(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>tt(a.config.people),members:zd(a.config.members.logRetentionDays),db:()=>Ve(),linkFor:(u,f)=>Co(u,f,{gitlab:a.config.channels.gitlab?.host})})||await Od(t,e,r,o,{nodeName:a.config.node?.name,fleet:Xd(a.config),push:An(a.config),announce:al(a.config),chat:Kd(a.config),voice:tg(a.config),camera:ag(a.config),places:qd(a.config),assetLinks:()=>Hl(a.config)}))return;let s=o==="GET"?Eo(r):null;if(s){e.writeHead(200,{"Content-Type":s.type,"Cache-Control":"public, max-age=86400"}),e.end(s.body);return}if(o==="GET"&&Rh.has(r)&&to("page",r),o==="GET"&&r==="/"){let u=qr();if(!u.configExists||u.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(on({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wi({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(on({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Se(a.config);if(!u){w(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let E="";t.on("data",x=>E+=x),t.on("end",()=>v(E)),t.on("error",()=>v(""))}),b=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:f||"{}"});e.writeHead(b.status,{"Content-Type":"application/json"}),e.end(await b.text())}catch(u){w(e,502,{error:"could not reach the node",message:String(u?.message||u)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let u=await Se(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),b=o==="POST"?await re(t):void 0,v=b?.node??f,E=v?u.find(R=>R.url===v):u[0];if(!E){w(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(E.url+r+x,{method:o,headers:{"Content-Type":"application/json",...E.token?{Authorization:`Bearer ${E.token}`}:{}},...o==="POST"?{body:JSON.stringify({...b,node:void 0})}:{}});w(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){w(e,502,{error:"could not reach the node",message:u?.message||String(u)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let u=await re(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let b=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${b}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Se(a.config);if(!u){w(e,200,{configured:!1,workflows:[]});return}let f=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});w(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{w(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(go({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ho({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(po({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,f=setTimeout(()=>u.abort(),8e3);try{let b=Zn(await Se(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(b.map(async k=>{try{let L=await fetch(k.url+"/monitor",{headers:k.token?{Authorization:`Bearer ${k.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:k.name,url:k.url,ok:!0,data:await L.json()}}catch(L){return{name:k.name,url:k.url,ok:!1,error:L.message}}}));w(e,200,{nodes:R});return}let v=b.find(R=>R.url===n.searchParams.get("node"));if(!v){w(e,400,{error:"Select a known node"});return}let E=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(E)||o==="POST"&&["register","ended","action","retry","clear"].includes(E))){w(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await Qn(t)):void 0,A=await fetch(v.url+"/monitor/"+E+(E==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):E==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:u.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});w(e,A.status,await A.json())}catch(b){w(e,502,{error:b.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bi({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nd({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qi({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=o==="POST"?await re(t).catch(()=>({})):void 0,v=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...b!==void 0?{body:JSON.stringify(b??{})}:{}});w(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gi({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ki({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Br({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!u){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(Ji({taskId:decodeURIComponent(l[1]),agentId:u,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:D(a.config)}));return}let d=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(d){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vi({agentId:decodeURIComponent(d[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){zr(t,e);return}if(o==="POST"&&r==="/api/setup"){await Fr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ur(t,e);return}if(o==="GET"&&r==="/admin"){xs(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){$s(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Es(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Us(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let u=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(u==="fleet"){if(r==="/api/admin/activity-graph"){await lg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await nn(t,e,r,b=>Vd(b,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let b=decodeURIComponent(f[1]),v=b.indexOf("::");if(v>0){let E=b.slice(0,v),x=b.slice(v+2),A=a.config.node?.id||a.config.node?.name||"local";if(E===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let R=(a.config.dashboard?.daemons||[]).find(k=>(k.name||k.url)===E);if(R){let k=lt(R.url.replace(/\/+$/,""),a.config);if(k){await Ud(t,e,k,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}w(e,404,{error:`unknown node "${E}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let f=lt(u,a.config);if(!f){w(e,404,{error:`unknown peer: ${u}`});return}let b=(n.search||"").replace(/[?&]peer=[^&]*/g,E=>E.startsWith("?")?"?":"");await Ud(t,e,f,r+(b==="?"?"":b));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ws(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await dg(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-XKT5FWPO.js"),b=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await u({running:b});w(e,200,v)}catch(u){w(e,500,{error:u?.message||String(u)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Js({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Ks(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vs({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ys({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await Bh(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 yi(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await nn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ki(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Ei(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let b=new G,v=f?b.verify(f):null;if(!v||!Ee(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await bs(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,Er()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await js(t,e,r,n);return}if(await Ns(t,e,r,{people:()=>tt(a.config.people),members:zd(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ve(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Ts(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Ti(t,e,r);return}if(r.startsWith("/api/admin/")){await vs(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(is);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){w(e,400,{error:"invalid asset name"});return}let f=sg("web/"+u);try{let b=await ig(f),v=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",E=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":E?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(b)}catch{w(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Ye(a.config);w(e,200,u)}catch(u){w(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let u=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",b=await Ye(a.config,{date:u,timezone:f});w(e,200,b)}catch(u){w(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(f,b,v,E)=>{let x=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(x)?Math.max(v,Math.min(E,x)):b};try{let f=await Se(a.config);w(e,200,await zi(f,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(f){w(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){w(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(b,v,E,x)=>{let A=parseInt(n.searchParams.get(b)||"",10);return Number.isFinite(A)?Math.max(E,Math.min(x,A)):v};try{let b=await Se(a.config);w(e,200,await Ui(b,{day:u,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(b){w(e,502,{error:b.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let u=n.searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}let f=n.searchParams,b;if(r==="/api/mesh/thread"){let[v,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}b=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,E]=[f.get("kind"),f.get("key")];if(!v||!E){w(e,400,{error:"kind and key required"});return}b=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(E)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}b=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){w(e,400,{error:"task required"});return}b=`/analytics/run/${encodeURIComponent(v)}`}try{await Fi(e,await Se(a.config),u,b)}catch(v){w(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Xh(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),b=u.searchParams.get("agent"),v=u.searchParams.get("task");if(!f||!b||!v){w(e,400,{error:"node, agent, task query params required"});return}await Kh(t,e,a,f,b,v);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),b=u.searchParams.get("agent"),v=u.searchParams.get("task"),E=u.searchParams.get("limit")||"50";if(!f||!b){w(e,400,{error:"node and agent query params required"});return}await Yh(e,a,f,b,v,E);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),b=u.searchParams.get("task"),v=u.searchParams.get("kind");if(!f||!b||v!=="cancel"&&v!=="followup"){w(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Qh(t,e,a,f,b,v);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!f.ok)throw new Error(`HTTP ${f.status}`);let b=await f.json();w(e,200,b)}catch(u){w(e,502,{error:u.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!f.ok){w(e,f.status,{error:`HTTP ${f.status}`});return}w(e,200,await f.json())}catch(u){w(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await re(t);try{let f=await rg(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!Jh(t,e,[`agent:${u}`]))return;await Vh(t,e,a.config,u);return}if(o==="GET"&&r==="/api/node/build"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);w(e,200,Sr(await f.json()))}catch(u){w(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let b=new G,v=f?b.verify(f):null;if(!v||!Ee(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await qh(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"){w(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(r==="/api/wiki/curate"||r==="/api/wiki/curate/restore"){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=o==="POST"?JSON.stringify(await re(t)??{}):void 0,v=await fetch(`${f}${r}${n.search}`,{method:o,headers:u,...b?{body:b}:{}});w(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(u){w(e,502,{error:"daemon unreachable",message:u?.message||String(u)})}return}if(await Ol(t,e,r,o,qd(a.config)))return;if(o==="POST"&&(r==="/api/signals/stop"||r==="/api/signals/resume"||r==="/api/signals/drop")){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,r);return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await ua(t,e,a,u,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 b=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(A=>({name:A.name,url:A.url,token:A.token}))],v={flag:!1},E=[];t.on("close",()=>{v.flag=!0;for(let A of E)try{A.abort()}catch{}});let x=setInterval(()=>{if(!v.flag)try{e.write(`: ping
21023
+ `),console.log(` Boards: ${a.map(k=>k.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 rg=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/places","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function og(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if((t.url||"/").split(/[?#]/)[0]!==r){w(e,404,{error:"not found"});return}if(Lr(t.headers)==="foreign"&&Pr(o)){w(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await bs(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>rt(a.config.people),members:ic(a.config.members.logRetentionDays),db:()=>Ze(),linkFor:(u,f)=>Bo(u,f,{gitlab:a.config.channels.gitlab?.host})})||await Yd(t,e,r,o,{nodeName:a.config.node?.name,fleet:On(a.config),desk:Eg(a.config),push:jn(a.config),announce:hl(a.config),chat:uc(a.config),voice:Cg(a.config),camera:Ig(a.config),places:sc(a.config),assetLinks:()=>Ql(a.config)}))return;let s=o==="GET"?No(r):null;if(s){e.writeHead(200,{"Content-Type":s.type,"Cache-Control":"public, max-age=86400"}),e.end(s.body);return}if(o==="GET"&&rg.has(r)&&fo("page",r),o==="GET"&&r==="/"){let u=Zr();if(!u.configExists||u.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(al({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Te(a.config);if(!u){w(e,503,{error:"no node available"});return}let f=await new Promise(y=>{let E="";t.on("data",x=>E+=x),t.on("end",()=>y(E)),t.on("error",()=>y(""))}),v=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:f||"{}"});e.writeHead(v.status,{"Content-Type":"application/json"}),e.end(await v.text())}catch(u){w(e,502,{error:"could not reach the node",message:String(u?.message||u)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let u=await Te(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),v=o==="POST"?await re(t):void 0,y=v?.node??f,E=y?u.find(L=>L.url===y):u[0];if(!E){w(e,400,{error:"unknown node"});return}let x=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(E.url+r+x,{method:o,headers:{"Content-Type":"application/json",...E.token?{Authorization:`Bearer ${E.token}`}:{}},...o==="POST"?{body:JSON.stringify({...v,node:void 0})}:{}});w(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){w(e,502,{error:"could not reach the node",message:u?.message||String(u)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let u=await re(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let v=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${v}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await y.json().catch(()=>({error:`HTTP ${y.status}`}));w(e,y.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Te(a.config);if(!u){w(e,200,{configured:!1,workflows:[]});return}let f=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});w(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{w(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Co({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ao({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_o({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,f=setTimeout(()=>u.abort(),8e3);try{let v=lr(await Te(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let L=await Promise.all(v.map(async _=>{try{let R=await fetch(_.url+"/monitor",{headers:_.token?{Authorization:`Bearer ${_.token}`}:{},signal:u.signal});if(!R.ok)throw new Error(`HTTP ${R.status}`);return{name:_.name,url:_.url,ok:!0,data:await R.json()}}catch(R){return{name:_.name,url:_.url,ok:!1,error:R.message}}}));w(e,200,{nodes:L});return}let y=v.find(L=>L.url===n.searchParams.get("node"));if(!y){w(e,400,{error:"Select a known node"});return}let E=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(E)||o==="POST"&&["register","ended","action","retry","clear"].includes(E))){w(e,405,{error:"Unknown monitor operation"});return}let x=o==="POST"?JSON.stringify(await ir(t)):void 0,A=await fetch(y.url+"/monitor/"+E+(E==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):E==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:x,signal:u.signal,headers:{"Content-Type":"application/json",...y.token?{Authorization:`Bearer ${y.token}`}:{}}});w(e,A.status,await A.json())}catch(v){w(e,502,{error:v.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Yi({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qd({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qi({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=o==="POST"?await re(t).catch(()=>({})):void 0,y=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...v!==void 0?{body:JSON.stringify(v??{})}:{}});w(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(nl({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rl({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ol({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qr({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!u){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(sl({taskId:decodeURIComponent(l[1]),agentId:u,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:D(a.config)}));return}let d=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(d){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(il({agentId:decodeURIComponent(d[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){eo(t,e);return}if(o==="POST"&&r==="/api/setup"){await to(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await ao(t,e);return}if(o==="GET"&&r==="/admin"){Is(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Ws(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Ns(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}ti(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let u=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(u==="fleet"){if(r==="/api/admin/activity-graph"){await jg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await dn(t,e,r,v=>fc(v,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let v=decodeURIComponent(f[1]),y=v.indexOf("::");if(y>0){let E=v.slice(0,y),x=v.slice(y+2),A=a.config.node?.id||a.config.node?.name||"local";if(E===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`;else{let L=(a.config.dashboard?.daemons||[]).find(_=>(_.name||_.url)===E);if(L){let _=mt(L.url.replace(/\/+$/,""),a.config);if(_){await dc(t,e,_,`/api/admin/activity-graph/dispatch/${encodeURIComponent(x)}`);return}}w(e,404,{error:`unknown node "${E}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let f=mt(u,a.config);if(!f){w(e,404,{error:`unknown peer: ${u}`});return}let v=(n.search||"").replace(/[?&]peer=[^&]*/g,E=>E.startsWith("?")?"?":"");await dc(t,e,f,r+(v==="?"?"":v));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await ai(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Og(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-GTRZ7GWF.js"),v=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",y=await u({running:v});w(e,200,y)}catch(u){w(e,500,{error:u?.message||String(u)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(si({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await oi(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ii({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(li({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await ug(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 Ri(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await dn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Pi(t,e,r))return;let p=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(p){Oi(t,e,p[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let v=new G,y=f?v.verify(f):null;if(!y||!Ae(y,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ms(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,Nr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Gs(t,e,r,n);return}if(await Ks(t,e,r,{people:()=>rt(a.config.people),members:ic(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ze(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Ds(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Ni(t,e,r);return}if(r.startsWith("/api/admin/")){await Rs(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(vs);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){w(e,400,{error:"invalid asset name"});return}let f=Pg("web/"+u);try{let v=await $g(f),y=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",E=n.searchParams.has("v");e.writeHead(200,{"Content-Type":y,"Cache-Control":E?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(v)}catch{w(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await et(a.config);w(e,200,u)}catch(u){w(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let u=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",v=await et(a.config,{date:u,timezone:f});w(e,200,v)}catch(u){w(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(f,v,y,E)=>{let x=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(x)?Math.max(y,Math.min(E,x)):v};try{let f=await Te(a.config);w(e,200,await Zi(f,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(f){w(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){w(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(v,y,E,x)=>{let A=parseInt(n.searchParams.get(v)||"",10);return Number.isFinite(A)?Math.max(E,Math.min(x,A)):y};try{let v=await Te(a.config);w(e,200,await tl(v,{day:u,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(v){w(e,502,{error:v.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let u=n.searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}let f=n.searchParams,v;if(r==="/api/mesh/thread"){let[y,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!y||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}v=`/analytics/thread?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[y,E]=[f.get("kind"),f.get("key")];if(!y||!E){w(e,400,{error:"kind and key required"});return}v=`/analytics/job?kind=${encodeURIComponent(y)}&key=${encodeURIComponent(E)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[y,E,x]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!y||!E||!x){w(e,400,{error:"agent, channel, chat required"});return}v=`/analytics/conversation?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(E)}&chat=${encodeURIComponent(x)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let y=f.get("task");if(!y){w(e,400,{error:"task required"});return}v=`/analytics/run/${encodeURIComponent(y)}`}try{await el(e,await Te(a.config),u,v)}catch(y){w(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){vg(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),v=u.searchParams.get("agent"),y=u.searchParams.get("task");if(!f||!v||!y){w(e,400,{error:"node, agent, task query params required"});return}await yg(t,e,a,f,v,y);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),v=u.searchParams.get("agent"),y=u.searchParams.get("task"),E=u.searchParams.get("limit")||"50";if(!f||!v){w(e,400,{error:"node and agent query params required"});return}await _g(e,a,f,v,y,E);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),v=u.searchParams.get("task"),y=u.searchParams.get("kind");if(!f||!v||y!=="cancel"&&y!=="followup"){w(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Sg(t,e,a,f,v,y);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await xa(t,e,a,u,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!f.ok)throw new Error(`HTTP ${f.status}`);let v=await f.json();w(e,200,v)}catch(u){w(e,502,{error:u.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!f.ok){w(e,f.status,{error:`HTTP ${f.status}`});return}w(e,200,await f.json())}catch(u){w(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await re(t);try{let f=await Rg(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let c=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(c&&o==="POST"){let u=c[1];if(!wg(t,e,[`agent:${u}`]))return;await kg(t,e,a.config,u);return}if(o==="GET"&&r==="/api/node/build"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);w(e,200,Or(await f.json()))}catch(u){w(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",f=u.startsWith("Bearer ")?u.slice(7):"";if(f!==a.token){let v=new G,y=f?v.verify(f):null;if(!y||!Ae(y,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await mg(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"){w(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(r==="/api/wiki/curate"||r==="/api/wiki/curate/restore"){try{let u={"Content-Type":"application/json"};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=o==="POST"?JSON.stringify(await re(t)??{}):void 0,y=await fetch(`${f}${r}${n.search}`,{method:o,headers:u,...v?{body:v}:{}});w(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(u){w(e,502,{error:"daemon unreachable",message:u?.message||String(u)})}return}if(await Jl(t,e,r,o,sc(a.config)))return;if(o==="POST"&&(r==="/api/signals/stop"||r==="/api/signals/resume"||r==="/api/signals/drop")){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await xa(t,e,a,u,r);return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){w(e,400,{error:"node query param required"});return}await xa(t,e,a,u,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 v=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(A=>({name:A.name,url:A.url,token:A.token}))],y={flag:!1},E=[];t.on("close",()=>{y.flag=!0;for(let A of E)try{A.abort()}catch{}});let x=setInterval(()=>{if(!y.flag)try{e.write(`: ping
20869
21024
 
20870
- `)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let A of b)(async()=>{let R={Accept:"text/event-stream"};A.token&&(R.Authorization=`Bearer ${A.token}`);let k=new AbortController;E.push(k);try{let L=await fetch(`${A.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:R,signal:k.signal});if(!L.ok||!L.body)return;let j=L.body.getReader(),$=new TextDecoder,O="";for(;!v.flag;){let{done:W,value:de}=await j.read();if(W)break;O+=$.decode(de,{stream:!0});let Q;for(;(Q=O.indexOf(`
21025
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let A of v)(async()=>{let L={Accept:"text/event-stream"};A.token&&(L.Authorization=`Bearer ${A.token}`);let _=new AbortController;E.push(_);try{let R=await fetch(`${A.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:L,signal:_.signal});if(!R.ok||!R.body)return;let j=R.body.getReader(),$=new TextDecoder,O="";for(;!y.flag;){let{done:W,value:ce}=await j.read();if(W)break;O+=$.decode(ce,{stream:!0});let Q;for(;(Q=O.indexOf(`
20871
21026
 
20872
- `))>=0;){let oe=O.slice(0,Q);if(O=O.slice(Q+2),v.flag)break;try{e.write(oe+`
21027
+ `))>=0;){let oe=O.slice(0,Q);if(O=O.slice(Q+2),y.flag)break;try{e.write(oe+`
20873
21028
 
20874
- `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/follow-ups"){let u=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))],f=[],b=await Promise.all(u.map(async x=>{let A={};x.token&&(A.Authorization=`Bearer ${x.token}`);try{let R=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs?limit=500&summary=1`,{headers:A,signal:AbortSignal.timeout(5e3)});if(!R.ok)return f.push(x.url),[];let k=await R.json();return Array.isArray(k.runs)?k.runs:[]}catch{return f.push(x.url),[]}})),v=new Map;for(let x of a.workflowRuns.list({limit:500}))v.set(x.id,x);for(let x of b)for(let A of x)v.set(A.id,{...A,history:A.history??[],pending:A.pending??[]});let E=new Map(a.workflowStore.list().map(x=>[x.id,x.title]));w(e,200,{groups:Vn([...v.values()],x=>E.get(x)),unreachable:f});return}if(r==="/api/workflows/required"){let u=()=>({settings:io(),agents:Object.keys(a.config.agents??{}).sort()});if(o==="GET"){w(e,200,u());return}if(o!=="POST"){w(e,405,{error:"Method not allowed"});return}if(a.config.workflows?.editor!=="edit"){w(e,403,{error:"the workflow editor is read-only on this node (workflows.editor)"});return}let f=await re(t).catch(()=>({})),b={};if(typeof f.enabled=="boolean"&&(b.enabled=f.enabled),typeof f.exemptQuestions=="boolean"&&(b.exemptQuestions=f.exemptQuestions),typeof f.agentId=="string"&&f.agentId){if(!Object.prototype.hasOwnProperty.call(a.config.agents??{},f.agentId)){w(e,400,{error:`no agent "${f.agentId}" on this node`});return}let E=f.agentRequired;if(E!=="on"&&E!=="off"&&E!=="default"){w(e,400,{error:"agentRequired is on, off or default"});return}b.agent={id:f.agentId,value:E==="default"?null:E==="on"}}if(b.enabled===void 0&&b.exemptQuestions===void 0&&!b.agent){w(e,400,{error:"nothing to change"});return}let v=await lo(b);if(!v.success){w(e,400,{error:v.error});return}w(e,200,{ok:!0,reloaded:!!v.reloaded,...u()});return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),b=u.searchParams.get("workflowId")||void 0,v=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",E=a.workflowRuns.list({limit:f,workflowId:b}),x=`?limit=${f}${b?`&workflowId=${encodeURIComponent(b)}`:""}${v?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],R=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let W=new AbortController,de=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let oe=await Q.json();return Array.isArray(oe.runs)?oe.runs:[]}finally{clearTimeout(de)}}catch{return[]}})),k=new Map;for(let $ of E)k.set($.id,$);for(let $ of R)for(let O of $)k.set(O.id,O);let L=Array.from(k.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,f),j=v?L.map($=>Oh($)):L;w(e,200,{runs:j})}catch(u){w(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let g=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(g){let u=decodeURIComponent(g[1]),f=a.workflowRuns.get(u);if(f){w(e,200,{run:f});return}let b=[{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 b)try{let E={};v.token&&(E.Authorization=`Bearer ${v.token}`);let x=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:E});if(x.ok){w(e,200,await x.json());return}}catch{}w(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${f}/api/actions/builtin`,{headers:u}),v=await b.json().catch(()=>({error:`HTTP ${b.status}`}));w(e,b.status,v)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let _=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(_){try{let u=await re(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let b=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${b}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(r.startsWith("/api/workflows")&&Qi(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,b,v)=>{if(a.token)return!0;let E=Sa(f);if(!E)return!0;let x=new G().verify(E);if(!x)return w(b,401,{error:"invalid or revoked token"}),!1;for(let A of v)if(!Ee(x,A))return w(b,403,{error:`token missing scope: ${A}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){w(e,200,a.boards.map(u=>({id:u.id,name:u.name,source:u.source,primaryToolLabel:u.primaryToolLabel,labels:u.labels,columns:u.columns,timeRangeDays:u.timeRangeDays})));return}let y=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(y&&o==="GET"){let u=a.sources.get(y[1]);if(!u){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMembers=="function"?await u.listMembers():[];w(e,200,f)}catch(f){w(e,502,{error:f.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(S&&o==="GET"){let u=a.sources.get(S[1]);if(!u){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMilestones=="function"?await u.listMilestones():[];w(e,200,f)}catch(f){w(e,502,{error:f.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),h=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(T&&o==="PATCH"){let[,u,f]=T,b=decodeURIComponent(f),v=a.boards.find(k=>k.id===u);if(!v){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}let x=await re(t),A=v.columns.find(k=>k.id===x.to),R=v.columns.find(k=>k.id===x.from);if(!A){w(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await jh(E,b,R,A),_n({actor:Sn(t),action:"move",boardId:u,itemId:b,payload:{from:x.from,to:x.to}}),w(e,200,{ok:!0})}catch(k){w(e,502,{error:k.message||"transition failed"})}return}if(h){let[,u,f]=h,b=f?decodeURIComponent(f):void 0,v=a.boards.find(x=>x.id===u);if(!v){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!b){let{columns:x,totals:A}=await $h(v,E,n.searchParams);w(e,200,{columns:x,totals:A});return}if(o==="GET"&&b){try{let x=typeof E.getItem=="function"?await E.getItem(b):null;if(!x){w(e,404,{error:"not found"});return}w(e,200,x)}catch(x){w(e,502,{error:x.message})}return}if(o==="PATCH"&&b){let x=await re(t);try{let A=typeof E.updateItem=="function"?await E.updateItem(b,x):null;if(!A){w(e,501,{error:"update unsupported"});return}_n({actor:Sn(t),action:"update",boardId:u,itemId:b,payload:x}),w(e,200,A)}catch(A){w(e,502,{error:A.message})}return}if(o==="POST"&&!b){let x=await re(t);if(!x.title){w(e,400,{error:"title required"});return}if(!E.capabilities.create||!E.create){w(e,400,{error:`source ${E.type} does not support create`});return}try{let A=await E.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});_n({actor:Sn(t),action:"create",boardId:u,itemId:A.id,payload:{title:x.title}}),w(e,201,A)}catch(A){w(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),b={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(b){e.writeHead(302,{Location:b}),e.end();return}}w(e,404,{error:"not found",path:r})}async function $h(t,e,a){if(!e.capabilities.listAll||!e.listAll){let h={};for(let u of t.columns)h[u.id]=[];return{columns:h,totals:Object.fromEntries(t.columns.map(u=>[u.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),c=t.columns.some(h=>h.kind!=="closed"),p=t.columns.some(h=>h.kind==="closed"),m=c?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],g=p?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let h of t.columns)_[h.id]=[];let y=t.columns.find(h=>h.kind==="closed");for(let h of g)y&&_[y.id].push({...h,stage:y.id});let S=t.columns.filter(h=>h.kind!=="closed");for(let h of m){let u=Mn(h,S);if(!u)continue;let f=_[u];f&&f.push({...h,stage:u})}if(i)for(let h of Object.keys(_))_[h]=_[h].filter(u=>u.assignee===i);for(let h of Object.keys(_))_[h].sort((u,f)=>{let b=(u.priority??99)-(f.priority??99);return b!==0?b:(f.updatedAt||"").localeCompare(u.updatedAt||"")});let T=Object.fromEntries(Object.entries(_).map(([h,u])=>[h,u.length]));return{columns:_,totals:T}}async function jh(t,e,a,n){let r=Ln(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 Oh(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,...t.meta?{meta:t.meta}:{},...t.pausedAt?{pausedAt:Jn(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function Nh(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 Mr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function _n(t){try{let e=it(process.cwd(),".agentx");Wd(e)||Ch(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
20875
- `;Ah(it(e,"board-audit.jsonl"),a)}catch{}}function Sn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Dh=2e3;async function Hh(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=h=>{let u=new AbortController,f=setTimeout(()=>u.abort(),Dh),b=()=>u.abort();return a?.addEventListener("abort",b,{once:!0}),fetch(t+h,{headers:r,signal:u.signal}).then(async v=>{let E=v.ok?await v.json().catch(()=>{}):void 0;return{ok:E!==void 0,json:async()=>E}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",b)})},[l,d,c,p,m,g,_,y,S]=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"),i("/api/signals/stopped?limit=20")]);if(!d||!d.ok)return o.error=d?`HTTP ${d.status}`:"unreachable",o;let T=await d.json();if(o.agents=T.map(h=>({id:h.id,name:h.name,tier:h.tier,model:h.model,...typeof h.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(h.color)?{color:h.color}:{},skillCount:Number.isFinite(h.skillCount)?h.skillCount:void 0,active:h.active||0,total:h.total||0,errors:h.errors||0,lastActive:h.lastActive,lastSummary:h.lastSummary,hourlyTasks:Array.isArray(h.hourlyTasks)?h.hourlyTasks:void 0,runningTasks:Array.isArray(h.runningTasks)?h.runningTasks:[]})),l&&l.ok){let h=await l.json().catch(()=>({}));o.uptimeSec=h.uptime,typeof h.inflight?.total=="number"&&(o.inflight=h.inflight.total),h.restart&&typeof h.restart.state=="string"&&(o.restart=h.restart),o.name=h.node?.name||h.node?.id||t,o.id=h.node?.id||t,h.usage&&(o.usage=h.usage)}if(S&&S.ok){let h=await S.json().catch(()=>({})),u=Array.isArray(h?.tasks)?h.tasks:[];o.stoppedTasks=u.filter(f=>f&&f.state!=="resumed").slice(0,10).map(f=>({id:String(f.id),agentId:String(f.agentId),channel:String(f.channel??""),chatId:String(f.chatId??""),state:String(f.state),stoppedAt:String(f.stoppedAt),stoppedBy:String(f.stoppedBy??""),reason:typeof f.reason=="string"?f.reason:void 0,request:String(f.request??""),plan:f.plan&&typeof f.plan.text=="string"?{author:String(f.plan.author),text:f.plan.text,note:f.plan.note}:void 0,resumable:f.resumable===!0,...f.workflow&&typeof f.workflow.runId=="string"?{workflow:{runId:f.workflow.runId,workflowId:String(f.workflow.workflowId??""),nodeId:String(f.workflow.nodeId??"")}}:{}}))}if(p&&p.ok){let h=await p.json().then(u=>Array.isArray(u)?u:[],()=>[]);o.crons=h.map(u=>({id:u.id,enabled:u.enabled===!0,schedule:String(u.schedule||""),timezone:u.timezone,agent:String(u.agent||""),kind:typeof u.command=="string"&&u.command.trim()?"command":"agent",model:u.model,nextRun:u.nextRun,retryPending:u.retryPending===!0,consecutiveErrors:Number(u.consecutiveErrors)||0}))}if(m&&m.ok){let h=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(h.runs)?h.runs:[]}if(_&&_.ok){let h=await _.json().catch(()=>null);h&&Array.isArray(h.routines)&&(o.routines=h.routines.slice(0,ar.routines))}if(g&&g.ok){let h=await g.json().catch(()=>null);h?.active&&h.kind==="lesson"&&(o.lesson={agentId:h.agentId??null,mode:String(h.mode||"teach"),goal:String(h.goal||""),step:Number(h.step)||0,saying:String(h.saying||""),startedAt:String(h.startedAt||"")})}if(y&&y.ok){let h=await y.json().catch(()=>null);h&&Array.isArray(h.sessions)&&Gh(o,h.sessions,h.saved??{})}o.reachable=!0,o._peers=Array.isArray(c?.ok?await c.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var ca=null;function Bh(t){if(ca)return ca;let e=it(process.cwd(),".agentx/wiki");return ca=so({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph",curator:!0,curatorToken:()=>t.token}),ca}async function ma(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 qh(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||U(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){w(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();w(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){w(t,502,{error:s.message||"daemon unreachable"})}}async function Se(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(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:U(a,l)})}let s=await ma(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var zh=3e3,Fh=6e3,Uh=5*6e4,Tn=new Map,pa=new Map;function Ye(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=pa.get(a);if(n)return n;let r=(async()=>{let o=await Se(t,AbortSignal.timeout(zh)),s=await Promise.all(o.map(async i=>{let l=await Hh(i.url,i.token,AbortSignal.timeout(Fh),e);return e?l:Wh(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>pa.delete(a));return pa.set(a,r),r}function Wh(t,e,a=Date.now()){if(e.reachable&&!e.error)return Tn.set(t,{node:e,at:a}),e;let n=Tn.get(t);return!n||a-n.at>Uh?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function W0(){Tn.clear(),pa.clear()}function Gh(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 Xh(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,d)=>{n||e.write(`event: ${l}
21029
+ `)}catch{y.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/follow-ups"){let u=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))],f=[],v=await Promise.all(u.map(async x=>{let A={};x.token&&(A.Authorization=`Bearer ${x.token}`);try{let L=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs?limit=500&summary=1`,{headers:A,signal:AbortSignal.timeout(5e3)});if(!L.ok)return f.push(x.url),[];let _=await L.json();return Array.isArray(_.runs)?_.runs:[]}catch{return f.push(x.url),[]}})),y=new Map;for(let x of a.workflowRuns.list({limit:500}))y.set(x.id,x);for(let x of v)for(let A of x)y.set(A.id,{...A,history:A.history??[],pending:A.pending??[]});let E=new Map(a.workflowStore.list().map(x=>[x.id,x.title]));w(e,200,{groups:or([...y.values()],x=>E.get(x)),unreachable:f});return}if(r==="/api/workflows/required"){let u=()=>({settings:yo(),agents:Object.keys(a.config.agents??{}).sort()});if(o==="GET"){w(e,200,u());return}if(o!=="POST"){w(e,405,{error:"Method not allowed"});return}if(a.config.workflows?.editor!=="edit"){w(e,403,{error:"the workflow editor is read-only on this node (workflows.editor)"});return}let f=await re(t).catch(()=>({})),v={};if(typeof f.enabled=="boolean"&&(v.enabled=f.enabled),typeof f.exemptQuestions=="boolean"&&(v.exemptQuestions=f.exemptQuestions),typeof f.agentId=="string"&&f.agentId){if(!Object.prototype.hasOwnProperty.call(a.config.agents??{},f.agentId)){w(e,400,{error:`no agent "${f.agentId}" on this node`});return}let E=f.agentRequired;if(E!=="on"&&E!=="off"&&E!=="default"){w(e,400,{error:"agentRequired is on, off or default"});return}v.agent={id:f.agentId,value:E==="default"?null:E==="on"}}if(v.enabled===void 0&&v.exemptQuestions===void 0&&!v.agent){w(e,400,{error:"nothing to change"});return}let y=await wo(v);if(!y.success){w(e,400,{error:y.error});return}w(e,200,{ok:!0,reloaded:!!y.reloaded,...u()});return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),v=u.searchParams.get("workflowId")||void 0,y=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",E=a.workflowRuns.list({limit:f,workflowId:v}),x=`?limit=${f}${v?`&workflowId=${encodeURIComponent(v)}`:""}${y?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],L=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let W=new AbortController,ce=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let oe=await Q.json();return Array.isArray(oe.runs)?oe.runs:[]}finally{clearTimeout(ce)}}catch{return[]}})),_=new Map;for(let $ of E)_.set($.id,$);for(let $ of L)for(let O of $)_.set(O.id,O);let R=Array.from(_.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,f),j=y?R.map($=>lg($)):R;w(e,200,{runs:j})}catch(u){w(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let g=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(g){let u=decodeURIComponent(g[1]),f=a.workflowRuns.get(u);if(f){w(e,200,{run:f});return}let v=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({url:y.url,token:y.token}))];for(let y of v)try{let E={};y.token&&(E.Authorization=`Bearer ${y.token}`);let x=await fetch(`${y.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:E});if(x.ok){w(e,200,await x.json());return}}catch{}w(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let u={};a.config.dashboard.token&&(u.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${f}/api/actions/builtin`,{headers:u}),y=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,y)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let k=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(k){try{let u=await re(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let v=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${v}/workflows/${encodeURIComponent(k[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),E=await y.json().catch(()=>({error:`HTTP ${y.status}`}));w(e,y.status,E)}catch(u){w(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(r.startsWith("/api/workflows")&&dl(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,v,y)=>{if(a.token)return!0;let E=Ia(f);if(!E)return!0;let x=new G().verify(E);if(!x)return w(v,401,{error:"invalid or revoked token"}),!1;for(let A of y)if(!Ae(x,A))return w(v,403,{error:`token missing scope: ${A}`,scopes:x.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){w(e,200,a.boards.map(u=>({id:u.id,name:u.name,source:u.source,primaryToolLabel:u.primaryToolLabel,labels:u.labels,columns:u.columns,timeRangeDays:u.timeRangeDays})));return}let b=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(b&&o==="GET"){let u=a.sources.get(b[1]);if(!u){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMembers=="function"?await u.listMembers():[];w(e,200,f)}catch(f){w(e,502,{error:f.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(S&&o==="GET"){let u=a.sources.get(S[1]);if(!u){w(e,404,{error:"unknown board"});return}try{let f=typeof u.listMilestones=="function"?await u.listMilestones():[];w(e,200,f)}catch(f){w(e,502,{error:f.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),h=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(T&&o==="PATCH"){let[,u,f]=T,v=decodeURIComponent(f),y=a.boards.find(_=>_.id===u);if(!y){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}let x=await re(t),A=y.columns.find(_=>_.id===x.to),L=y.columns.find(_=>_.id===x.from);if(!A){w(e,400,{error:`unknown 'to' column: ${x.to}`});return}try{await ig(E,v,L,A),Rn({actor:Ln(t),action:"move",boardId:u,itemId:v,payload:{from:x.from,to:x.to}}),w(e,200,{ok:!0})}catch(_){w(e,502,{error:_.message||"transition failed"})}return}if(h){let[,u,f]=h,v=f?decodeURIComponent(f):void 0,y=a.boards.find(x=>x.id===u);if(!y){w(e,404,{error:`unknown board: ${u}`});return}let E=a.sources.get(u);if(!E){w(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!v){let{columns:x,totals:A}=await sg(y,E,n.searchParams);w(e,200,{columns:x,totals:A});return}if(o==="GET"&&v){try{let x=typeof E.getItem=="function"?await E.getItem(v):null;if(!x){w(e,404,{error:"not found"});return}w(e,200,x)}catch(x){w(e,502,{error:x.message})}return}if(o==="PATCH"&&v){let x=await re(t);try{let A=typeof E.updateItem=="function"?await E.updateItem(v,x):null;if(!A){w(e,501,{error:"update unsupported"});return}Rn({actor:Ln(t),action:"update",boardId:u,itemId:v,payload:x}),w(e,200,A)}catch(A){w(e,502,{error:A.message})}return}if(o==="POST"&&!v){let x=await re(t);if(!x.title){w(e,400,{error:"title required"});return}if(!E.capabilities.create||!E.create){w(e,400,{error:`source ${E.type} does not support create`});return}try{let A=await E.create({title:x.title,description:x.description,labels:x.labels,assigneeUsernames:x.assigneeUsernames,milestoneTitle:x.milestoneTitle,projectHint:x.projectHint});Rn({actor:Ln(t),action:"create",boardId:u,itemId:A.id,payload:{title:x.title}}),w(e,201,A)}catch(A){w(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),v={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(v){e.writeHead(302,{Location:v}),e.end();return}}w(e,404,{error:"not found",path:r})}async function sg(t,e,a){if(!e.capabilities.listAll||!e.listAll){let h={};for(let u of t.columns)h[u.id]=[];return{columns:h,totals:Object.fromEntries(t.columns.map(u=>[u.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(h=>h.kind!=="closed"),c=t.columns.some(h=>h.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],g=c?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let h of t.columns)k[h.id]=[];let b=t.columns.find(h=>h.kind==="closed");for(let h of g)b&&k[b.id].push({...h,stage:b.id});let S=t.columns.filter(h=>h.kind!=="closed");for(let h of m){let u=Hn(h,S);if(!u)continue;let f=k[u];f&&f.push({...h,stage:u})}if(i)for(let h of Object.keys(k))k[h]=k[h].filter(u=>u.assignee===i);for(let h of Object.keys(k))k[h].sort((u,f)=>{let v=(u.priority??99)-(f.priority??99);return v!==0?v:(f.updatedAt||"").localeCompare(u.updatedAt||"")});let T=Object.fromEntries(Object.entries(k).map(([h,u])=>[h,u.length]));return{columns:k,totals:T}}async function ig(t,e,a,n){let r=Bn(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 lg(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,...t.meta?{meta:t.meta}:{},...t.pausedAt?{pausedAt:rr(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function dg(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 zr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Rn(t){try{let e=ut(process.cwd(),".agentx");cc(e)||eg(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
21030
+ `;Zh(ut(e,"board-audit.jsonl"),a)}catch{}}function Ln(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var cg=2e3;async function pg(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=h=>{let u=new AbortController,f=setTimeout(()=>u.abort(),cg),v=()=>u.abort();return a?.addEventListener("abort",v,{once:!0}),fetch(t+h,{headers:r,signal:u.signal}).then(async y=>{let E=y.ok?await y.json().catch(()=>{}):void 0;return{ok:E!==void 0,json:async()=>E}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",v)})},[l,d,p,c,m,g,k,b,S]=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"),i("/api/signals/stopped?limit=20")]);if(!d||!d.ok)return o.error=d?`HTTP ${d.status}`:"unreachable",o;let T=await d.json();if(o.agents=T.map(h=>({id:h.id,name:h.name,tier:h.tier,model:h.model,...typeof h.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(h.color)?{color:h.color}:{},skillCount:Number.isFinite(h.skillCount)?h.skillCount:void 0,active:h.active||0,total:h.total||0,errors:h.errors||0,lastActive:h.lastActive,lastSummary:h.lastSummary,hourlyTasks:Array.isArray(h.hourlyTasks)?h.hourlyTasks:void 0,runningTasks:Array.isArray(h.runningTasks)?h.runningTasks:[]})),l&&l.ok){let h=await l.json().catch(()=>({}));o.uptimeSec=h.uptime,typeof h.inflight?.total=="number"&&(o.inflight=h.inflight.total),h.restart&&typeof h.restart.state=="string"&&(o.restart=h.restart),o.name=h.node?.name||h.node?.id||t,o.id=h.node?.id||t,h.usage&&(o.usage=h.usage)}if(S&&S.ok){let h=await S.json().catch(()=>({})),u=Array.isArray(h?.tasks)?h.tasks:[];o.stoppedTasks=u.filter(f=>f&&f.state!=="resumed").slice(0,10).map(f=>({id:String(f.id),agentId:String(f.agentId),channel:String(f.channel??""),chatId:String(f.chatId??""),state:String(f.state),stoppedAt:String(f.stoppedAt),stoppedBy:String(f.stoppedBy??""),reason:typeof f.reason=="string"?f.reason:void 0,request:String(f.request??""),plan:f.plan&&typeof f.plan.text=="string"?{author:String(f.plan.author),text:f.plan.text,note:f.plan.note}:void 0,resumable:f.resumable===!0,...f.workflow&&typeof f.workflow.runId=="string"?{workflow:{runId:f.workflow.runId,workflowId:String(f.workflow.workflowId??""),nodeId:String(f.workflow.nodeId??"")}}:{}}))}if(c&&c.ok){let h=await c.json().then(u=>Array.isArray(u)?u:[],()=>[]);o.crons=h.map(u=>({id:u.id,enabled:u.enabled===!0,schedule:String(u.schedule||""),timezone:u.timezone,agent:String(u.agent||""),kind:typeof u.command=="string"&&u.command.trim()?"command":"agent",model:u.model,nextRun:u.nextRun,retryPending:u.retryPending===!0,consecutiveErrors:Number(u.consecutiveErrors)||0}))}if(m&&m.ok){let h=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(h.runs)?h.runs:[]}if(k&&k.ok){let h=await k.json().catch(()=>null);h&&Array.isArray(h.routines)&&(o.routines=h.routines.slice(0,pr.routines))}if(g&&g.ok){let h=await g.json().catch(()=>null);h?.active&&h.kind==="lesson"&&(o.lesson={agentId:h.agentId??null,mode:String(h.mode||"teach"),goal:String(h.goal||""),step:Number(h.step)||0,saying:String(h.saying||""),startedAt:String(h.startedAt||"")})}if(b&&b.ok){let h=await b.json().catch(()=>null);h&&Array.isArray(h.sessions)&&bg(o,h.sessions,h.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 ha=null;function ug(t){if(ha)return ha;let e=ut(process.cwd(),".agentx/wiki");return ha=vo({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph",curator:!0,curatorToken:()=>t.token}),ha}async function ba(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 mg(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||U(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){w(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();w(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){w(t,502,{error:s.message||"daemon unreachable"})}}async function Te(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(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:U(a,l)})}let s=await ba(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var fg=3e3,hg=6e3,gg=5*6e4,$n=new Map,ga=new Map;function et(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=ga.get(a);if(n)return n;let r=(async()=>{let o=await Te(t,AbortSignal.timeout(fg)),s=await Promise.all(o.map(async i=>{let l=await pg(i.url,i.token,AbortSignal.timeout(hg),e);return e?l:xg(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ga.delete(a));return ga.set(a,r),r}function xg(t,e,a=Date.now()){if(e.reachable&&!e.error)return $n.set(t,{node:e,at:a}),e;let n=$n.get(t);return!n||a-n.at>gg?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function R_(){$n.clear(),ga.clear()}function bg(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 vg(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,d)=>{n||e.write(`event: ${l}
20876
21031
  data: ${JSON.stringify(d)}
20877
21032
 
20878
- `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ye(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 Kh(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let _ of a.config.dashboard.daemons)i.add(_.url.replace(/\/+$/,""));try{let _=await ma(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let y of _)i.add(y.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let c=new AbortController,p;try{p=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:c.signal})}catch(_){w(e,502,{error:_.message||"upstream connect failed"});return}if(!p.ok||!p.body){w(e,p.status||502,{error:`upstream HTTP ${p.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=p.body.getReader();(async()=>{try{for(;;){let{value:_,done:y}=await m.read();if(y)break;_&&e.write(_)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{c.abort();try{e.end()}catch{}})}function Jh(t,e,a){let n=Sa(t);if(!n)return w(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new G().verify(n);if(!r)return w(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!Ee(r,o))return w(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Vh(t,e,a,n){let r=a.agents?.[n];if(!r){w(e,404,{error:"unknown agent"});return}if(r.access!=="public"){w(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await re(t)}catch{w(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){w(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),c=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(c)}catch(d){w(e,502,{error:d.message||"upstream call failed"})}}async function Yh(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let p of e.config.dashboard.daemons)i.add(p.url.replace(/\/+$/,""));try{let p=await ma(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of p)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let c=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let p=await fetch(`${s}${c}`,{headers:d}),m=await p.text();t.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(p){w(t,502,{error:p.message||"upstream fetch failed"})}}async function Qh(t,e,a,n,r,o){await ua(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function ua(t,e,a,n,r){let o={};try{o=await re(t)??{}}catch{}let s=await Gd(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Gd(t,e,a,n){let r=(d,c)=>({status:d,text:JSON.stringify(c),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await ma(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let c of d)s.add(c.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function An(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){let r=t.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(t.dashboard,r);return wt(),{...a(`Can't reach ${e.relayTo}, the computer that sends notifications`),async forward(s){let i=await fetch(`${r}/push/app`,{method:"POST",headers:{"Content-Type":"application/json",...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify({op:"app",call:s}),signal:AbortSignal.timeout(2e4)}),l=await i.json().catch(()=>({}));if(!i.ok||typeof l.status!="number")throw new Error(l.error||`the daemon answered ${i.status}`);return{status:l.status,body:l.body??{}}}}}let n=cr(e.keysFile);return{store:()=>{let r=Ve();return r?new Or(r):null},publicKey:()=>pr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function qd(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?$l({url:a,token:U(t.dashboard,a),operatorKey:va(process.cwd())??void 0}):null,r=e.relayTo?`this computer relays notifications to ${e.relayTo}; place reminders work on a phone paired with ${e.relayTo}.`:An(t).reason;return Dl(t,process.cwd(),n,r)}function Xd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ye(t,n),async nodePost(n,r,o){let s=await Gd(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=Et({root:process.cwd()}).items.map(Fd)}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=lt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let d=await l.json();s.items=(d.items??[]).map(Fd)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s,i={}){let l=n.replace(/\/+$/,"");if(l===e){let c=Ae(),p=await Tt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s,...i});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let d=lt(l,t);if(!d)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let c=await fetch(`${d.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:JSON.stringify({key:r,action:o,...i}),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"}}}}}}var En=null;function zd(t){return En?.days!==t&&(En={days:t,store:new ht(process.cwd(),Date.now,t)}),En.store}function Kd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Xd(t);return{store:()=>{let r=Ve();return r?new st(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:va(process.cwd())??void 0},snapshot:()=>Ye(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=>U(t.dashboard,r.replace(/\/+$/,"")),...Zh(t,e,a)}}function Zh(t,e,a){let n=An(t);return{finishAlerts:r=>{if(n.forward)return dr.finishOn(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}
20879
- ${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 eg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Kd(t);return new da({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 d=await l.json();return{events:Array.isArray(d.events)?d.events:[],gap:d.gap===!0}},nodeUrl:async o=>{let i=(await Ye(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:pl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function tg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ve();return a?new st(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function ag(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function Fd(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,...t.choices?{choices:t.choices}:{},...t.draft?{draft:t.draft}:{}}}var ng=`
21033
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await et(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 yg(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await ba(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let b of k)i.add(b.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,c;try{c=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(k){w(e,502,{error:k.message||"upstream connect failed"});return}if(!c.ok||!c.body){w(e,c.status||502,{error:`upstream HTTP ${c.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=c.body.getReader();(async()=>{try{for(;;){let{value:k,done:b}=await m.read();if(b)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function wg(t,e,a){let n=Ia(t);if(!n)return w(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new G().verify(n);if(!r)return w(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!Ae(r,o))return w(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function kg(t,e,a,n){let r=a.agents?.[n];if(!r){w(e,404,{error:"unknown agent"});return}if(r.access!=="public"){w(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await re(t)}catch{w(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){w(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(d){w(e,502,{error:d.message||"upstream call failed"})}}async function _g(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of e.config.dashboard.daemons)i.add(c.url.replace(/\/+$/,""));try{let c=await ba(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of c)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let c=await fetch(`${s}${p}`,{headers:d}),m=await c.text();t.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(c){w(t,502,{error:c.message||"upstream fetch failed"})}}async function Sg(t,e,a,n,r,o){await xa(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function xa(t,e,a,n,r){let o={};try{o=await re(t)??{}}catch{}let s=await pc(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function pc(t,e,a,n){let r=(d,p)=>({status:d,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await ba(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of d)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function jn(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){let r=t.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(t.dashboard,r);return Et(),{...a(`Can't reach ${e.relayTo}, the computer that sends notifications`),async forward(s){let i=await fetch(`${r}/push/app`,{method:"POST",headers:{"Content-Type":"application/json",...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify({op:"app",call:s}),signal:AbortSignal.timeout(2e4)}),l=await i.json().catch(()=>({}));if(!i.ok||typeof l.status!="number")throw new Error(l.error||`the daemon answered ${i.status}`);return{status:l.status,body:l.body??{}}}}}let n=vr(e.keysFile);return{store:()=>{let r=Ze();return r?new Kr(r):null},publicKey:()=>yr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function sc(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?Xl({url:a,token:U(t.dashboard,a),operatorKey:Sa(process.cwd())??void 0}):null,r=e.relayTo?`this computer relays notifications to ${e.relayTo}; place reminders work on a phone paired with ${e.relayTo}.`:jn(t).reason;return Yl(t,process.cwd(),n,r)}function On(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>et(t,n),async nodePost(n,r,o){let s=await pc(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=Ct({root:process.cwd()}).items.map(lc)}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=mt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let d=await l.json();s.items=(d.items??[]).map(lc)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s,i={}){let l=n.replace(/\/+$/,"");if(l===e){let p=Ie(),c=await It({root:process.cwd()},r,o,{laterHours:p.laterHours,by:s,...i});return c.ok?{status:200,body:{ok:!0,message:c.message}}:{status:409,body:{error:c.error}}}let d=mt(l,t);if(!d)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let p=await fetch(`${d.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:JSON.stringify({key:r,action:o,...i}),signal:AbortSignal.timeout(1e4)});return{status:p.status,body:a(await p.text())}}catch(p){return{status:502,body:{error:p.message||"peer dashboard unreachable"}}}}}}function Eg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=On(t),n={root:process.cwd()};return{async board(){let[r,o]=await Promise.all([a.approvals(),a.snapshot()]),s=new Set,i=[],l=o.nodes.find(k=>k.url.replace(/\/+$/,"")===e);if(!l||!l.reachable||l.stale)i.push("The running tasks could not be read, so no request is shown as working now.");else for(let k of l.agents)for(let b of k.runningTasks??[])s.add(b.id);let d=Date.now(),p=null;try{let k=ze(n);k&&(p=[...k.listOpen(),...k.listClosedSince(d-Cn*864e5,In)].map(b=>({record:b,links:k.links(b.id)})))}catch(k){i.push(`Requests could not be read: ${k.message}`)}let c=[];try{c=wr(n.root).filter(k=>k.status!=="pending")}catch(k){i.push(`Finished cards could not be read: ${k.message}`)}let m=new Set(Object.entries(kr(n.root).snoozed).filter(([,k])=>Date.parse(k)>d).map(([k])=>k)),g=oc({now:d,node:e,nodeName:t.node?.name||"this computer",inbox:r,requests:p,cards:c,liveRuns:s,deferred:m});return{...g,errors:[...g.errors,...i]}},async reply(r,o){return ta("POST",`${xe}/reply`,{id:r,text:o},n)}}}var Pn=null;function ic(t){return Pn?.days!==t&&(Pn={days:t,store:new yt(process.cwd(),Date.now,t)}),Pn.store}function uc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=On(t);return{store:()=>{let r=Ze();return r?new ct(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:Sa(process.cwd())??void 0},snapshot:()=>et(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=>U(t.dashboard,r.replace(/\/+$/,"")),...Tg(t,e,a)}}function Tg(t,e,a){let n=jn(t);return{finishAlerts:r=>{if(n.forward)return br.finishOn(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}
21034
+ ${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 Ag(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=uc(t);return new ma({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 d=await l.json();return{events:Array.isArray(d.events)?d.events:[],gap:d.gap===!0}},nodeUrl:async o=>{let i=(await et(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:Sl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Cg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ze();return a?new ct(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Ig(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function lc(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,...t.choices?{choices:t.choices}:{},...t.draft?{draft:t.draft}:{},...t.detail?{detail:t.detail}:{},...t.created_at?{createdAt:t.created_at}:{}}}var Mg=`
20880
21035
  You are helping draft a new GitLab issue. Follow these conventions strictly.
20881
21036
 
20882
21037
  Title pattern:
@@ -20908,16 +21063,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
20908
21063
  Shape:
20909
21064
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
20910
21065
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
20911
- `;async function rg(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):
21066
+ `;async function Rg(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):
20912
21067
  - ${r.knownLabels.slice(0,60).join(`
20913
21068
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
20914
- `),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:ng}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let c=(d.content||"").toString(),p=og(c);if(!p||typeof p.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+c.slice(0,400));let m=Array.isArray(p.labels)?p.labels.filter(g=>typeof g=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:p.title.trim(),description:(p.description||"").toString(),labels:m,assigneeUsername:typeof p.assigneeUsername=="string"?p.assigneeUsername:void 0,kind:typeof p.kind=="string"?p.kind:void 0,raw:c}}function og(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 sg(t){let e=Lh(Mh(import.meta.url));return it(e,t)}async function ig(t){return Ih(t)}function w(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function re(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 Jd(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:Jd(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 lg(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;w(e,200,await ta(await Vd(r,a.config)))}async function Vd(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=an(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=lt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,c=setTimeout(()=>d.abort(),8e3);try{let p=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return p.ok?{nodeId:i.name||i.url,snap:await p.json()}:null}finally{clearTimeout(c)}}catch{return null}}));for(let i of s)i&&n.push(i);return xi(n)}async function dg(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 p=process.env.HOME||"",m=[p&&`${p}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),g=m.find(_=>Wd(_));if(!g){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",g]}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}
21069
+ `),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:Mg}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let p=(d.content||"").toString(),c=Lg(p);if(!c||typeof c.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(c.labels)?c.labels.filter(g=>typeof g=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:c.title.trim(),description:(c.description||"").toString(),labels:m,assigneeUsername:typeof c.assigneeUsername=="string"?c.assigneeUsername:void 0,kind:typeof c.kind=="string"?c.kind:void 0,raw:p}}function Lg(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 Pg(t){let e=ng(ag(import.meta.url));return ut(e,t)}async function $g(t){return tg(t)}function w(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function re(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 mc(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:mc(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 jg(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;w(e,200,await oa(await fc(r,a.config)))}async function fc(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=ln(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=mt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let c=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return c.ok?{nodeId:i.name||i.url,snap:await c.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Ci(n)}async function Og(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 c=process.env.HOME||"",m=[c&&`${c}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),g=m.find(k=>cc(k));if(!g){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",g]}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}
20915
21070
 
20916
- `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=p=>{i+=p.toString("utf8");let m;for(;(m=i.indexOf(`
21071
+ `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=c=>{i+=c.toString("utf8");let m;for(;(m=i.indexOf(`
20917
21072
  `))>=0;){let g=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
20918
21073
  data: ${g.replace(/\n/g," ")}
20919
21074
 
20920
21075
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
20921
21076
 
20922
- `)}catch{}},15e3),c=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",c),s.on("exit",c),s.on("error",c)}async function Ud(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((p,m)=>{let g=[];t.on("data",_=>g.push(_)),t.on("end",()=>p(Buffer.concat(g))),t.on("error",m)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let c=t.headers["x-requested-with"];c&&(l["X-Requested-With"]=Array.isArray(c)?c[0]:c),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let p=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await p.arrayBuffer());e.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(p){w(e,502,{error:`proxy to peer failed: ${p?.message||p}`,target:r})}}function lt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Jd(n),token:n.dashboardToken||n.token}:null}export{Gh as applyAttachSessions,Hh as fetchDaemonAgents,Ph as handleBoardRequest,W0 as resetLiveCaches,Se as resolveNodeTargets,U0 as startBoardDashboard,Wh as withLastGood};
20923
- //# sourceMappingURL=board-dashboard-2A6VSQ7V.js.map
21077
+ `)}catch{}},15e3),p=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function dc(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((c,m)=>{let g=[];t.on("data",k=>g.push(k)),t.on("end",()=>c(Buffer.concat(g))),t.on("error",m)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let c=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await c.arrayBuffer());e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(c){w(e,502,{error:`proxy to peer failed: ${c?.message||c}`,target:r})}}function mt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:mc(n),token:n.dashboardToken||n.token}:null}export{bg as applyAttachSessions,pg as fetchDaemonAgents,og as handleBoardRequest,R_ as resetLiveCaches,Te as resolveNodeTargets,M_ as startBoardDashboard,xg as withLastGood};
21078
+ //# sourceMappingURL=board-dashboard-33NGOGWC.js.map