agentix-cli 0.145.0 → 0.147.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 (145) hide show
  1. package/dist/{App-MYHUCIKZ.js → App-AW4OROPH.js} +2 -2
  2. package/dist/{ChatApp-D6QN6HJP.js → ChatApp-USXQHII3.js} +2 -2
  3. package/dist/{absorb-eval-UAGD42BG.js → absorb-eval-WZCC5VPS.js} +2 -2
  4. package/dist/{agent-HEGEDDUE.js → agent-TJ2K7FZG.js} +2 -2
  5. package/dist/{board-dashboard-4KIFLAFO.js → board-dashboard-JY4YQ5TM.js} +230 -217
  6. package/dist/board-dashboard-JY4YQ5TM.js.map +1 -0
  7. package/dist/{chunk-HSRNH4NR.js → chunk-4F5XUF6T.js} +2 -2
  8. package/dist/{chunk-SH5TNMS5.js → chunk-5TGY4RIQ.js} +2 -2
  9. package/dist/chunk-6UP5VD3H.js +64 -0
  10. package/dist/chunk-6UP5VD3H.js.map +1 -0
  11. package/dist/{chunk-YUY35PY7.js → chunk-7HCSLOTP.js} +3 -3
  12. package/dist/{chunk-TM3I6C4V.js → chunk-7ICJCJ43.js} +2 -2
  13. package/dist/{chunk-WUBSX6S5.js → chunk-7T6SMNVY.js} +2 -2
  14. package/dist/{chunk-YWDXRGVC.js → chunk-7W3TLSZQ.js} +78 -78
  15. package/dist/chunk-7W3TLSZQ.js.map +1 -0
  16. package/dist/chunk-E7YHXMJG.js +7 -0
  17. package/dist/chunk-E7YHXMJG.js.map +1 -0
  18. package/dist/{chunk-5E37FADJ.js → chunk-EG7Y2XLK.js} +2 -2
  19. package/dist/{chunk-KAGLCJA3.js → chunk-EKAUOUN2.js} +2 -2
  20. package/dist/{chunk-SANYTBHX.js → chunk-GJMYG53S.js} +2 -2
  21. package/dist/{chunk-JTDQO4LI.js → chunk-GLLHUHX2.js} +41 -41
  22. package/dist/chunk-GLLHUHX2.js.map +1 -0
  23. package/dist/{chunk-YEFEUSB2.js → chunk-GTOQWMRY.js} +2 -2
  24. package/dist/chunk-HAEI2LNC.js +7 -0
  25. package/dist/chunk-HAEI2LNC.js.map +1 -0
  26. package/dist/chunk-JCFVH3NC.js +533 -0
  27. package/dist/chunk-JCFVH3NC.js.map +1 -0
  28. package/dist/{chunk-VDJZ2Q3M.js → chunk-JLEVL66V.js} +2 -2
  29. package/dist/{chunk-WBG6NA7R.js → chunk-KP7KDLZ2.js} +2 -2
  30. package/dist/{chunk-P42M6CYF.js → chunk-KW6SHOAN.js} +2 -2
  31. package/dist/{chunk-GMVWDQFF.js → chunk-MXDTLR45.js} +2 -2
  32. package/dist/{chunk-QXPMWP4R.js → chunk-P5BFFU4Y.js} +2 -2
  33. package/dist/chunk-P6PFTNN4.js +128 -0
  34. package/dist/chunk-P6PFTNN4.js.map +1 -0
  35. package/dist/{chunk-VTVEJ3RA.js → chunk-PUW4C6YO.js} +2 -2
  36. package/dist/{chunk-DG2DC43E.js → chunk-PYHR4HXO.js} +2 -2
  37. package/dist/{chunk-BPOMIEEE.js → chunk-Q2QU32JP.js} +2 -2
  38. package/dist/{chunk-EV76NT3E.js → chunk-QXPX2NGL.js} +2 -2
  39. package/dist/{chunk-HP2NWDCS.js → chunk-UVF3K5YS.js} +2 -2
  40. package/dist/{chunk-OFJKTKRM.js → chunk-YE2X3AFU.js} +2 -2
  41. package/dist/chunk-Z3AI4KXT.js +18 -0
  42. package/dist/chunk-Z3AI4KXT.js.map +1 -0
  43. package/dist/{chunk-HCSIM2QW.js → chunk-ZZNAR6R2.js} +298 -297
  44. package/dist/chunk-ZZNAR6R2.js.map +1 -0
  45. package/dist/cli.js +1 -1
  46. package/dist/{client-ZU5AWBXQ.js → client-GLBNS45C.js} +2 -2
  47. package/dist/config-VRDFC7LW.js +2 -0
  48. package/dist/{config-mutate-DVARJ4KM.js → config-mutate-HU3KKYCD.js} +2 -2
  49. package/dist/config-mutator-JCAIGP6W.js +2 -0
  50. package/dist/{contributions-HKWDGIQV.js → contributions-JXPYCLVB.js} +2 -2
  51. package/dist/doctor-5Y7QSXNQ.js +2 -0
  52. package/dist/{follow-up-tool-2T4SIFY2.js → follow-up-tool-53AYA2UQ.js} +2 -2
  53. package/dist/{hub-3LDKRLTH.js → hub-YCOUZFNU.js} +2 -2
  54. package/dist/index.d.ts +181 -1
  55. package/dist/index.js +1 -1
  56. package/dist/{program-MAM4NX5P.js → program-CIJEGFYG.js} +215 -215
  57. package/dist/program-CIJEGFYG.js.map +1 -0
  58. package/dist/{promote-YOV5ELNF.js → promote-THTEHZHU.js} +2 -2
  59. package/dist/{query-LTKK3M2Y.js → query-N7JBDLR7.js} +2 -2
  60. package/dist/{query-settings-ACXSGMDU.js → query-settings-BJTVDDCH.js} +2 -2
  61. package/dist/{registry-NIAPKDQF.js → registry-LJ66OZYJ.js} +2 -2
  62. package/dist/{request-planner-433C7M3L.js → request-planner-PCELXLK7.js} +2 -2
  63. package/dist/{review-candidates-SI3QBYNH.js → review-candidates-EMJUROJH.js} +2 -2
  64. package/dist/{routing-CXT77HBF.js → routing-D2KNBEMG.js} +2 -2
  65. package/dist/schedule-tool-55MOWHKD.js +2 -0
  66. package/dist/{scheduler-SFHWPWCA.js → scheduler-73UEBYV4.js} +2 -2
  67. package/dist/{seat-CJVTUIM2.js → seat-UFAMWG7M.js} +2 -2
  68. package/dist/{select-JHGDG4H2.js → select-EPWELLAV.js} +2 -2
  69. package/dist/{set-enabled-NOJGCJAL.js → set-enabled-LS65QZQS.js} +2 -2
  70. package/dist/{tool-YOSMTSJM.js → tool-4S3YKLCN.js} +4 -4
  71. package/dist/tool-4S3YKLCN.js.map +1 -0
  72. package/dist/{tool-ERK543LL.js → tool-7LKYIA6D.js} +2 -2
  73. package/dist/{wiki-2LLXQUEP.js → wiki-LHT6X2JF.js} +2 -2
  74. package/dist/wiki-enrich-CBBS3AC7.js +2 -0
  75. package/package.json +1 -1
  76. package/dist/board-dashboard-4KIFLAFO.js.map +0 -1
  77. package/dist/chunk-42BEORFZ.js +0 -7
  78. package/dist/chunk-42BEORFZ.js.map +0 -1
  79. package/dist/chunk-4NKPVTVP.js +0 -62
  80. package/dist/chunk-4NKPVTVP.js.map +0 -1
  81. package/dist/chunk-HCSIM2QW.js.map +0 -1
  82. package/dist/chunk-JTDQO4LI.js.map +0 -1
  83. package/dist/chunk-LJ62ABOZ.js +0 -128
  84. package/dist/chunk-LJ62ABOZ.js.map +0 -1
  85. package/dist/chunk-S2GAEH2F.js +0 -13
  86. package/dist/chunk-S2GAEH2F.js.map +0 -1
  87. package/dist/chunk-VMMCT27Z.js +0 -5
  88. package/dist/chunk-VMMCT27Z.js.map +0 -1
  89. package/dist/chunk-VXBL2DET.js +0 -535
  90. package/dist/chunk-VXBL2DET.js.map +0 -1
  91. package/dist/chunk-YWDXRGVC.js.map +0 -1
  92. package/dist/config-Q4MNOHRI.js +0 -2
  93. package/dist/config-mutator-5NYGSUJD.js +0 -2
  94. package/dist/doctor-RTVGZP3X.js +0 -2
  95. package/dist/program-MAM4NX5P.js.map +0 -1
  96. package/dist/schedule-tool-3R4ISM5R.js +0 -2
  97. package/dist/tool-YOSMTSJM.js.map +0 -1
  98. package/dist/wiki-enrich-6C2O2MNV.js +0 -2
  99. /package/dist/{App-MYHUCIKZ.js.map → App-AW4OROPH.js.map} +0 -0
  100. /package/dist/{ChatApp-D6QN6HJP.js.map → ChatApp-USXQHII3.js.map} +0 -0
  101. /package/dist/{absorb-eval-UAGD42BG.js.map → absorb-eval-WZCC5VPS.js.map} +0 -0
  102. /package/dist/{agent-HEGEDDUE.js.map → agent-TJ2K7FZG.js.map} +0 -0
  103. /package/dist/{chunk-HSRNH4NR.js.map → chunk-4F5XUF6T.js.map} +0 -0
  104. /package/dist/{chunk-SH5TNMS5.js.map → chunk-5TGY4RIQ.js.map} +0 -0
  105. /package/dist/{chunk-YUY35PY7.js.map → chunk-7HCSLOTP.js.map} +0 -0
  106. /package/dist/{chunk-TM3I6C4V.js.map → chunk-7ICJCJ43.js.map} +0 -0
  107. /package/dist/{chunk-WUBSX6S5.js.map → chunk-7T6SMNVY.js.map} +0 -0
  108. /package/dist/{chunk-5E37FADJ.js.map → chunk-EG7Y2XLK.js.map} +0 -0
  109. /package/dist/{chunk-KAGLCJA3.js.map → chunk-EKAUOUN2.js.map} +0 -0
  110. /package/dist/{chunk-SANYTBHX.js.map → chunk-GJMYG53S.js.map} +0 -0
  111. /package/dist/{chunk-YEFEUSB2.js.map → chunk-GTOQWMRY.js.map} +0 -0
  112. /package/dist/{chunk-VDJZ2Q3M.js.map → chunk-JLEVL66V.js.map} +0 -0
  113. /package/dist/{chunk-WBG6NA7R.js.map → chunk-KP7KDLZ2.js.map} +0 -0
  114. /package/dist/{chunk-P42M6CYF.js.map → chunk-KW6SHOAN.js.map} +0 -0
  115. /package/dist/{chunk-GMVWDQFF.js.map → chunk-MXDTLR45.js.map} +0 -0
  116. /package/dist/{chunk-QXPMWP4R.js.map → chunk-P5BFFU4Y.js.map} +0 -0
  117. /package/dist/{chunk-VTVEJ3RA.js.map → chunk-PUW4C6YO.js.map} +0 -0
  118. /package/dist/{chunk-DG2DC43E.js.map → chunk-PYHR4HXO.js.map} +0 -0
  119. /package/dist/{chunk-BPOMIEEE.js.map → chunk-Q2QU32JP.js.map} +0 -0
  120. /package/dist/{chunk-EV76NT3E.js.map → chunk-QXPX2NGL.js.map} +0 -0
  121. /package/dist/{chunk-HP2NWDCS.js.map → chunk-UVF3K5YS.js.map} +0 -0
  122. /package/dist/{chunk-OFJKTKRM.js.map → chunk-YE2X3AFU.js.map} +0 -0
  123. /package/dist/{client-ZU5AWBXQ.js.map → client-GLBNS45C.js.map} +0 -0
  124. /package/dist/{config-Q4MNOHRI.js.map → config-VRDFC7LW.js.map} +0 -0
  125. /package/dist/{config-mutate-DVARJ4KM.js.map → config-mutate-HU3KKYCD.js.map} +0 -0
  126. /package/dist/{config-mutator-5NYGSUJD.js.map → config-mutator-JCAIGP6W.js.map} +0 -0
  127. /package/dist/{contributions-HKWDGIQV.js.map → contributions-JXPYCLVB.js.map} +0 -0
  128. /package/dist/{doctor-RTVGZP3X.js.map → doctor-5Y7QSXNQ.js.map} +0 -0
  129. /package/dist/{follow-up-tool-2T4SIFY2.js.map → follow-up-tool-53AYA2UQ.js.map} +0 -0
  130. /package/dist/{hub-3LDKRLTH.js.map → hub-YCOUZFNU.js.map} +0 -0
  131. /package/dist/{promote-YOV5ELNF.js.map → promote-THTEHZHU.js.map} +0 -0
  132. /package/dist/{query-LTKK3M2Y.js.map → query-N7JBDLR7.js.map} +0 -0
  133. /package/dist/{query-settings-ACXSGMDU.js.map → query-settings-BJTVDDCH.js.map} +0 -0
  134. /package/dist/{registry-NIAPKDQF.js.map → registry-LJ66OZYJ.js.map} +0 -0
  135. /package/dist/{request-planner-433C7M3L.js.map → request-planner-PCELXLK7.js.map} +0 -0
  136. /package/dist/{review-candidates-SI3QBYNH.js.map → review-candidates-EMJUROJH.js.map} +0 -0
  137. /package/dist/{routing-CXT77HBF.js.map → routing-D2KNBEMG.js.map} +0 -0
  138. /package/dist/{schedule-tool-3R4ISM5R.js.map → schedule-tool-55MOWHKD.js.map} +0 -0
  139. /package/dist/{scheduler-SFHWPWCA.js.map → scheduler-73UEBYV4.js.map} +0 -0
  140. /package/dist/{seat-CJVTUIM2.js.map → seat-UFAMWG7M.js.map} +0 -0
  141. /package/dist/{select-JHGDG4H2.js.map → select-EPWELLAV.js.map} +0 -0
  142. /package/dist/{set-enabled-NOJGCJAL.js.map → set-enabled-LS65QZQS.js.map} +0 -0
  143. /package/dist/{tool-ERK543LL.js.map → tool-7LKYIA6D.js.map} +0 -0
  144. /package/dist/{wiki-2LLXQUEP.js.map → wiki-LHT6X2JF.js.map} +0 -0
  145. /package/dist/{wiki-enrich-6C2O2MNV.js.map → wiki-enrich-CBBS3AC7.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{C as Bt,D as vo,E as yo,F as wo,H as ko,I as _o,a as to,b as ao,c as no,d as ro,e as Ie,f as oo,g as so,h as Ht,j as io,p as lo,q as co,r as po,s as uo,t as mo,x as fo,y as ho}from"./chunk-JTDQO4LI.js";import{a as xo,b as bo}from"./chunk-NZQBS7GN.js";import"./chunk-XVTD6I34.js";import"./chunk-QAWKN2N4.js";import"./chunk-MTX4UPNB.js";import{a as C}from"./chunk-5E37FADJ.js";import{a as go}from"./chunk-5NTWGUSJ.js";import{a as eo}from"./chunk-BKHIR2YJ.js";import{a as Ue,b as z,c as I,h as ue,i as Nt,j as se,k as K,l as Dt,m as Yr,n as Qr,o as Zr}from"./chunk-B2QYMUTD.js";import{a as Vr}from"./chunk-LNY6N73E.js";import{B as Ct,C as Sr,D as ze,E as Er,F as It,G as Mt,H as Tr,La as Hr,Na as Br,Oa as qr,Pa as zr,Q as Rt,R as Ar,S as Ir,T as Mr,W as Rr,X as Lr,Xa as Fr,Y as Pr,Za as Ce,a as dr,c as St,cb as Ur,d as Ia,da as U,e as pr,ea as $r,eb as Fe,fa as jr,fb as Lt,gb as Pt,hb as $t,i as Et,ib as jt,jb as Wr,kb as Gr,l as at,lb as Xr,mb as Ot,n as ur,ob as Kr,rb as Jr,v as _r}from"./chunk-VXBL2DET.js";import"./chunk-GTJIKXDB.js";import{h as lr,i as cr}from"./chunk-WUBSX6S5.js";import{p as mr,t as fr}from"./chunk-S2GAEH2F.js";import{a as H,b as Or,c as Nr,g as Dr}from"./chunk-7LN4VKDU.js";import{a as Cr}from"./chunk-IMLAPB7G.js";import{b as yr,c as wr}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import{m as kr}from"./chunk-TJZGAKIB.js";import"./chunk-QXPMWP4R.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ae,d as hr,e as Ma}from"./chunk-EMGB23H5.js";import{a as xr,b as qe,d as br,e as vr,f as Tt}from"./chunk-YMX3QCV7.js";import{b as gr}from"./chunk-JWDJMFU6.js";import{g as At}from"./chunk-LQE73AZR.js";import"./chunk-VY7TBMJU.js";import"./chunk-WBG6NA7R.js";import"./chunk-SANYTBHX.js";import"./chunk-2AXFYDWF.js";import{F as sr,W as wt,X as kt,Y as _t,Z as pe,_ as ir,a as Zn,f as er,g as Aa,h as Ca,l as tr,n as ar,o as nr,z as or}from"./chunk-P42M6CYF.js";import"./chunk-MEFPXHQJ.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-5TTHN7DP.js";import"./chunk-LJ62ABOZ.js";import{a as rr}from"./chunk-VMMCT27Z.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-VTVEJ3RA.js";import"./chunk-HP2NWDCS.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import{g as Qn}from"./chunk-BPOMIEEE.js";import"./chunk-WPNRDEHW.js";import"./chunk-SH5TNMS5.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{F as ka,K as Sd,L as _a,La as X,M as Sa,T as Ed,Ta as yt,_ as Xn,a as Bn,b as qn,ba as Ea,c as wd,ea as Kn,ga as vt,ha as Jn,ja as Vn,la as Yn,pa as Ta,x as gt,y as kd}from"./chunk-4NKPVTVP.js";import{a as zn,b as xt,c as wa,d as Fn,h as Un}from"./chunk-BRK6M6LA.js";import{d as Wn,e as _d,f as bt,n as Gn}from"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ra(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 So(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ra(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>",qt=(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 Eo(t={}){return I({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{A as bo,B as vo,F as Bt,G as _o,H as So,I as Eo,K as To,L as Ao,a as ro,b as oo,c as so,d as io,e as lo,h as Ie,i as co,j as po,k as Ht,m as uo,s as mo,t as fo,u as ho,v as go,w as xo}from"./chunk-GLLHUHX2.js";import{a as wo,b as ko}from"./chunk-NZQBS7GN.js";import"./chunk-XVTD6I34.js";import"./chunk-QAWKN2N4.js";import"./chunk-MTX4UPNB.js";import{a as C}from"./chunk-EG7Y2XLK.js";import{a as yo}from"./chunk-5NTWGUSJ.js";import{a as no}from"./chunk-BKHIR2YJ.js";import{a as Ue,b as z,c as I,h as ue,i as Nt,j as se,k as K,l as Dt,m as eo,n as to,o as ao}from"./chunk-B2QYMUTD.js";import{a as Zr}from"./chunk-LNY6N73E.js";import{$a as Jr,Aa as zr,B as Ct,C as Ar,Ca as Fr,D as ze,Da as Ur,E as Cr,Ea as Wr,F as It,G as Mt,H as Rt,I as Pr,L as $r,M as jr,Ma as Gr,N as Or,Oa as Ce,Ta as Xr,U,V as Nr,Va as Fe,W as Dr,Wa as Lt,Xa as Pt,Ya as $t,Za as jt,_a as Kr,a as mr,ab as Vr,bb as Ot,c as St,d as Ia,db as Yr,e as fr,gb as Qr,i as Et,l as nt,n as hr,v as Tr}from"./chunk-JCFVH3NC.js";import"./chunk-GTJIKXDB.js";import{h as pr,i as ur}from"./chunk-7T6SMNVY.js";import{E as Rr,F as Lr,s as gr,u as xr,v as Mr}from"./chunk-Z3AI4KXT.js";import{a as H,b as Hr,c as Br,g as qr}from"./chunk-7LN4VKDU.js";import{a as Ir}from"./chunk-IMLAPB7G.js";import{b as _r,c as Sr}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import{m as Er}from"./chunk-TJZGAKIB.js";import"./chunk-P5BFFU4Y.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ae,d as br,e as Ma}from"./chunk-EMGB23H5.js";import{a as yr,b as qe,d as wr,e as kr,f as Tt}from"./chunk-YMX3QCV7.js";import{b as vr}from"./chunk-JWDJMFU6.js";import{g as At}from"./chunk-LQE73AZR.js";import"./chunk-VY7TBMJU.js";import"./chunk-KP7KDLZ2.js";import"./chunk-GJMYG53S.js";import"./chunk-2AXFYDWF.js";import{F as cr,W as wt,X as kt,Y as _t,Z as pe,_ as dr,a as ar,f as nr,g as Aa,h as Ca,l as rr,n as or,o as sr,z as lr}from"./chunk-KW6SHOAN.js";import"./chunk-MEFPXHQJ.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-5TTHN7DP.js";import"./chunk-P6PFTNN4.js";import{a as ir}from"./chunk-E7YHXMJG.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-PUW4C6YO.js";import"./chunk-UVF3K5YS.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import{g as tr}from"./chunk-Q2QU32JP.js";import"./chunk-WPNRDEHW.js";import"./chunk-5TGY4RIQ.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{F as ka,Ja as Qn,K as Cd,Ka as Zn,L as _a,La as X,M as Sa,Ma as er,T as Id,Ua as yt,_ as Xn,a as Bn,b as qn,ba as Ea,c as Ed,ea as Kn,ga as vt,ha as Jn,ja as Vn,la as Yn,pa as Ta,x as gt,y as Td}from"./chunk-6UP5VD3H.js";import{a as zn,b as xt,c as wa,d as Fn,h as Un}from"./chunk-BRK6M6LA.js";import{d as Wn,e as Ad,f as bt,n as Gn}from"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ra(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:Ra(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>",qt=(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 Io(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>
@@ -85,7 +85,7 @@ ${qt(ie.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:Td,scripts:`<script>${z({decayOf:Ra,rankByDecay:So})}const ICON = ${JSON.stringify(ie)};${Ad}</script>`})}var Td=`
88
+ </div>`,css:Md,scripts:`<script>${z({decayOf:Ra,rankByDecay:Co})}const ICON = ${JSON.stringify(ie)};${Rd}</script>`})}var Md=`
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
- }`,Ad=String.raw`
364
+ }`,Rd=String.raw`
365
365
  (function(){
366
366
  const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
367
367
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -776,13 +776,13 @@ if(document.querySelector('form :focus'))return;
776
776
  if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
777
777
  refresh();
778
778
  },15000);
779
- })();`;function La(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let d=r[p].from-r[p-1].to;d<c&&(c=d,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function Pa(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 To(t,e=[],a){let{bands:n,gaps:r}=La(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(b=>l.startedAt>=b.from&&l.startedAt<=b.to);if(c===-1)continue;let p=n[c],d=p.to-p.from||1,m=(l.startedAt-p.from)/d*100,g=Math.min(Math.max((l.durationMs||0)/d*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:c,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((c,p)=>Pa(l.runs.filter(d=>d.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Cd}from"crypto";import{readFileSync as Id,statSync as Md}from"fs";import{resolve as Rd,dirname as Ld}from"path";import{fileURLToPath as Pd}from"url";var Ao=new Map;function zt(t){let e=Ao.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Ld(Pd(import.meta.url)),r=Rd(n,"web",t),o=Md(r),s=o.size<8e6?Cd("sha1").update(Id(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Ao.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"/>'},Ft=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",$d=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],Co={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 Io(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 La(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let d=r[p].from-r[p-1].to;d<c&&(c=d,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function Pa(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 Mo(t,e=[],a){let{bands:n,gaps:r}=La(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(b=>l.startedAt>=b.from&&l.startedAt<=b.to);if(c===-1)continue;let p=n[c],d=p.to-p.from||1,m=(l.startedAt-p.from)/d*100,g=Math.min(Math.max((l.durationMs||0)/d*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:c,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((c,p)=>Pa(l.runs.filter(d=>d.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Ld}from"crypto";import{readFileSync as Pd,statSync as $d}from"fs";import{resolve as jd,dirname as Od}from"path";import{fileURLToPath as Nd}from"url";var Ro=new Map;function zt(t){let e=Ro.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Od(Nd(import.meta.url)),r=jd(n,"web",t),o=$d(r),s=o.size<8e6?Ld("sha1").update(Pd(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Ro.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"/>'},Ft=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Dd=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],Lo={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 Po(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">${Co[e]}</p>
785
+ <p class="ac-sub" id="sub">${Lo[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
@@ -799,7 +799,7 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${$d.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ft(o,13)}${r}</button>`).join("")}
802
+ ${Dd.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ft(o,13)}${r}</button>`).join("")}
803
803
  </div>
804
804
  <div class="ac-key">
805
805
  <span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
@@ -819,7 +819,7 @@ refresh();
819
819
  <div id="ax-fleet-root" data-hours="24" data-src="${zt("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:jd,scripts:`<script>${z({computeBands:La,packTracks:Pa,buildTimeline:To})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(Co)};${Od}</script>`})}var jd=`
822
+ </div>`,css:Hd,scripts:`<script>${z({computeBands:La,packTracks:Pa,buildTimeline:Mo})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(Lo)};${Bd}</script>`})}var Hd=`
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
- `,Od=String.raw`
908
+ `,Bd=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 Mo(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:Nd,scripts:`<script src="${zt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Nd=`
1027
+ `;function $o(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:qd,scripts:`<script src="${zt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var qd=`
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 ag}from"http";import{appendFileSync as ng,existsSync as md,mkdirSync as rg}from"fs";import{readFile as og}from"fs/promises";import{fileURLToPath as sg}from"url";import{dirname as ig,resolve as mt}from"path";Kn();function We(t,e){if(!t)return"absent";let a=hr(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 Ut(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Ro(t.headers["sec-fetch-mode"]),n.site=Ro(t.headers["sec-fetch-site"]),n}function Ro(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Bd}from"zlib";var Dd=[[[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},$a="#1a1a18",ja="#ffffff",Lo=Math.hypot(ke.width,ke.height)/2/ke.width,Wt={full:.74,safe:.37/Lo,android:.29/Lo,mac:.6};function Oa(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 Dd.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function Hd(t,e){let a=n=>String(Math.round(n*100)/100);return Oa(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function Po(t=64,e=Wt.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${ja}"/><path fill="${$a}" d="${Hd(t,e)}"/></svg>`}var qd=qo($a),$o=qo(ja),jo=new Map;function Ge(t){let e=jo.get(t);return e||(e=Bo({size:t,width:Wt.safe,background:"square"}),jo.set(t,e)),e}var zd=Po();function Ho(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:zd}:t==="/favicon.ico"?{type:"image/png",body:No(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:No(180)}:null}var Oo=new Map;function No(t){let e=Oo.get(t);return e||(e=Bo({size:t,width:Wt.full,background:"square"}),Oo.set(t,e)),e}function Bo(t){let{size:e}=t,a=t.background==="mac"?Do(e,[Fd(e)]):null,n=Do(e,Oa(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,c=n[l],p=s*r+1+i*4;for(let d=0;d<3;d++)o[p+d]=Math.round($o[d]+(qd[d]-$o[d])*c);o[p+3]=Math.round(255*(a?a[l]:1))}return Ud(e,o)}function Fd(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,c]of s)for(let p=0;p<=12;p++){let d=(c+90*p/12)*Math.PI/180;o.push([i+r*Math.cos(d),l+r*Math.sin(d)])}return o}var Na=8;function Do(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],[c,p]=o[(s+1)%o.length];l!==p&&n.push([i,l,c,p])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Na;s++){let i=o+(s+.5)/Na;r.length=0;for(let[l,c,p,d]of n)(i>=c&&i<d||i>=d&&i<c)&&r.push(l+(i-c)*(p-l)/(d-c));r.sort((l,c)=>l-c);for(let l=0;l+1<r.length;l+=2){let c=Math.max(0,r[l]),p=Math.min(t,r[l+1]);for(let d=Math.floor(c);d<p;d++){let m=Math.min(d+1,p)-Math.max(d,c);m>0&&(a[o*t+d]+=m/Na)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function qo(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function Ud(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]),Da("IHDR",a),Da("IDAT",Bd(e)),Da("IEND",Buffer.alloc(0))])}function Da(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(Gd(n)),Buffer.concat([a,n,r])}var Wd=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 Gd(t){let e=4294967295;for(let a of t)e=Wd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}yt();Ed();var Gt=7,Xd=["waiting_owner","needs_attention"],Kd={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=Kd[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 zo(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 Fo(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 (${_a.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,..._a).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Sa.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1048
+ `;import{createServer as sg}from"http";import{appendFileSync as ig,existsSync as xd,mkdirSync as lg}from"fs";import{readFile as cg}from"fs/promises";import{fileURLToPath as dg}from"url";import{dirname as pg,resolve as mt}from"path";Kn();function We(t,e){if(!t)return"absent";let a=br(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 Ut(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=jo(t.headers["sec-fetch-mode"]),n.site=jo(t.headers["sec-fetch-site"]),n}function jo(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Ud}from"zlib";var zd=[[[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},$a="#1a1a18",ja="#ffffff",Oo=Math.hypot(ke.width,ke.height)/2/ke.width,Wt={full:.74,safe:.37/Oo,android:.29/Oo,mac:.6};function Oa(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 zd.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function Fd(t,e){let a=n=>String(Math.round(n*100)/100);return Oa(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function No(t=64,e=Wt.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${ja}"/><path fill="${$a}" d="${Fd(t,e)}"/></svg>`}var Wd=Wo($a),Do=Wo(ja),Ho=new Map;function Ge(t){let e=Ho.get(t);return e||(e=Uo({size:t,width:Wt.safe,background:"square"}),Ho.set(t,e)),e}var Gd=No();function Fo(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:Gd}:t==="/favicon.ico"?{type:"image/png",body:qo(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:qo(180)}:null}var Bo=new Map;function qo(t){let e=Bo.get(t);return e||(e=Uo({size:t,width:Wt.full,background:"square"}),Bo.set(t,e)),e}function Uo(t){let{size:e}=t,a=t.background==="mac"?zo(e,[Xd(e)]):null,n=zo(e,Oa(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,c=n[l],p=s*r+1+i*4;for(let d=0;d<3;d++)o[p+d]=Math.round(Do[d]+(Wd[d]-Do[d])*c);o[p+3]=Math.round(255*(a?a[l]:1))}return Kd(e,o)}function Xd(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,c]of s)for(let p=0;p<=12;p++){let d=(c+90*p/12)*Math.PI/180;o.push([i+r*Math.cos(d),l+r*Math.sin(d)])}return o}var Na=8;function zo(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],[c,p]=o[(s+1)%o.length];l!==p&&n.push([i,l,c,p])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Na;s++){let i=o+(s+.5)/Na;r.length=0;for(let[l,c,p,d]of n)(i>=c&&i<d||i>=d&&i<c)&&r.push(l+(i-c)*(p-l)/(d-c));r.sort((l,c)=>l-c);for(let l=0;l+1<r.length;l+=2){let c=Math.max(0,r[l]),p=Math.min(t,r[l+1]);for(let d=Math.floor(c);d<p;d++){let m=Math.min(d+1,p)-Math.max(d,c);m>0&&(a[o*t+d]+=m/Na)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function Wo(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function Kd(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]),Da("IHDR",a),Da("IDAT",Ud(e)),Da("IEND",Buffer.alloc(0))])}function Da(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(Vd(n)),Buffer.concat([a,n,r])}var Jd=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 Vd(t){let e=4294967295;for(let a of t)e=Jd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}yt();Id();var Gt=7,Yd=["waiting_owner","needs_attention"],Qd={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=Qd[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 Go(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 Xo(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 (${_a.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,..._a).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Sa.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1049
1049
  ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...Sa,n-Gt*864e5).map(i):[],p=[];try{p=Ht(t,e,50).filter(b=>b.startedAt>=n-Gt*864e5)}catch{}let d=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)d.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:d.get(b.taskId)??null})),g=new Set(m.map(b=>b.request?.id).filter(Boolean)),k=[...l.filter(b=>!Xd.includes(b.state)),...c].filter(b=>!g.has(b.id));return{open:l,recent:c,runs:m,other:k}}Ta();_d();var Uo={waiting:0,yours:0,ahead:null};function Wo(t,e,a={}){let n=Wn(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,c=s.get(l)??0;s.set(l,c+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=c),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:c})),r.set(i.agentId,p)}return{byAgent:r,mine:o}}var Jd=4e3;function Go(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
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)d.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:d.get(b.taskId)??null})),g=new Set(m.map(b=>b.request?.id).filter(Boolean)),k=[...l.filter(b=>!Yd.includes(b.state)),...c].filter(b=>!g.has(b.id));return{open:l,recent:c,runs:m,other:k}}Ta();Ad();var Ko={waiting:0,yours:0,ahead:null};function Jo(t,e,a={}){let n=Wn(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,c=s.get(l)??0;s.set(l,c+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=c),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:c})),r.set(i.agentId,p)}return{byAgent:r,mine:o}}var Zd=4e3;function Vo(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-Gt*864e5).map(r=>r.agent_id)}function Xo(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(vt);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 c=n.queue?.get(l)??Uo,p=s.get(l),d=p??i.get(l);if(!d)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:c};let m=o(d.person??null),g=d.status==="error"||d.status==="timeout",k=p?"working":g&&m==="you"?"blocked":"free",b=m==="you"&&d.channel!=="a2a",S=b&&d.channel;return{agentId:l,state:k,by:m,at:p?d.started_at:d.finished_at??d.started_at,text:p||b?d.message_preview??null:null,fullText:b&&p&&String(d.original_message??d.message_preview??"").slice(0,Jd)||null,where:S?{label:Xe(d.channel,d.chat_id??""),url:n.linkFor?.(d.channel,d.chat_id??"")??null}:null,queue:c}})}function Ko(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Jo(t,e){return!t||e-t>=3e4||t>e}function Xt(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 Vo(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 Kt(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 Jt(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 Yo(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 Qo(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 Zo(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 es(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 ts(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 as=`
1052
+ GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-Gt*864e5).map(r=>r.agent_id)}function Yo(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(vt);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 c=n.queue?.get(l)??Ko,p=s.get(l),d=p??i.get(l);if(!d)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:c};let m=o(d.person??null),g=d.status==="error"||d.status==="timeout",k=p?"working":g&&m==="you"?"blocked":"free",b=m==="you"&&d.channel!=="a2a",S=b&&d.channel;return{agentId:l,state:k,by:m,at:p?d.started_at:d.finished_at??d.started_at,text:p||b?d.message_preview??null:null,fullText:b&&p&&String(d.original_message??d.message_preview??"").slice(0,Zd)||null,where:S?{label:Xe(d.channel,d.chat_id??""),url:n.linkFor?.(d.channel,d.chat_id??"")??null}:null,queue:c}})}function Qo(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Zo(t,e){return!t||e-t>=3e4||t>e}function Xt(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 es(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 Kt(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 Jt(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 ts(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 as(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 ns(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 rs(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 os(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 ss=`
1053
1053
  (function () {
1054
1054
  var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
1055
1055
  var who = document.getElementById('who');
@@ -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
- `,ns=`
1367
+ `,is=`
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
- `,rs=`
1379
+ `,ls=`
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 Vd="<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 Ha(t,e={}){return`<meta charset="utf-8">
1383
+ `;var ep="<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 Ha(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
- ${Vd}
1394
- <style>${Ue}${Vt}</style>`}function os(){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 ss=`
1393
+ ${ep}
1394
+ <style>${Ue}${Vt}</style>`}function cs(){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 ds=`
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) {
@@ -1424,7 +1424,7 @@ self.addEventListener('fetch', function (e) {
1424
1424
  `;function Ba(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 qa=Ha,za=Ba;function is(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 ls(){return`<!doctype html>
1427
+ </header>`}var qa=Ha,za=Ba;function ps(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 us(){return`<!doctype html>
1428
1428
  <html lang="en">
1429
1429
  <head>${qa("My work \xB7 AgentX")}<style>${Yt}</style></head>
1430
1430
  <body>
@@ -1439,15 +1439,15 @@ ${za("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:Yd,ageText:Fa,connectionNote:Kt,plainPreview:Jt,agentLine:Yo,sentState:Qo,requestState:Zo,summaryLine:es,freedAgents:ts})}${as}</script>
1442
+ <script>${z({workState:tp,ageText:Fa,connectionNote:Kt,plainPreview:Jt,agentLine:ts,sentState:as,requestState:ns,summaryLine:rs,freedAgents:os})}${ss}</script>
1443
1443
  </body>
1444
- </html>`}function cs(){return`<!doctype html>
1444
+ </html>`}function ms(){return`<!doctype html>
1445
1445
  <html lang="en">
1446
- <head>${qa("Pair this machine \xB7 AgentX")}<style>${ns}</style></head>
1446
+ <head>${qa("Pair this machine \xB7 AgentX")}<style>${is}</style></head>
1447
1447
  <body>
1448
1448
  ${za("This machine is not paired yet")}
1449
1449
  <main class="narrow">
1450
- ${is(0)}
1450
+ ${ps(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 @@ ${za("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:Xt})}${Qd}</script>
1467
+ <script>${z({formatPairInput:Xt})}${ap}</script>
1468
1468
  </body>
1469
- </html>`}function ds(){return`<!doctype html>
1469
+ </html>`}function fs(){return`<!doctype html>
1470
1470
  <html lang="en">
1471
- <head>${qa("Waiting for the owner \xB7 AgentX")}<style>${rs}</style></head>
1471
+ <head>${qa("Waiting for the owner \xB7 AgentX")}<style>${ls}</style></head>
1472
1472
  <body>
1473
1473
  ${za("This machine is paired")}
1474
1474
  <main class="narrow">
1475
- ${is(1)}
1475
+ ${ps(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>${Zd}</script>
1482
+ <script>${np}</script>
1483
1483
  </body>
1484
- </html>`}function Yd(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 Fa(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 Qd=`
1484
+ </html>`}function tp(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 Fa(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 ap=`
1485
1485
  (function () {
1486
1486
  var form = document.getElementById('pair-form');
1487
1487
  var machine = document.getElementById('machine');
@@ -1525,7 +1525,7 @@ ${za("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
- `,Zd=`
1528
+ `,np=`
1529
1529
  (function () {
1530
1530
  var msg = document.getElementById('msg');
1531
1531
  function check() {
@@ -1536,16 +1536,16 @@ ${za("This machine is paired")}
1536
1536
  }
1537
1537
  setInterval(check, 5000);
1538
1538
  })();
1539
- `;function ps(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 us(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 ms(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 Ua="/member/client.webmanifest",nt="Your project";function fs(){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 ep=`
1539
+ `;function hs(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 gs(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 xs(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 Ua="/member/client.webmanifest",rt="Your project";function bs(){return JSON.stringify({id:"/member?client",name:`${rt} \xB7 AgentX`,short_name:rt,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 rp=`
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 hs(){return`<!doctype html>
1543
+ `;function vs(){return`<!doctype html>
1544
1544
  <html lang="en">
1545
- <head>${Ha(`${nt} \xB7 AgentX`,{manifest:Ua,appTitle:nt})}<style>${Ue}${Vt}${Yt}${ep}</style></head>
1545
+ <head>${Ha(`${rt} \xB7 AgentX`,{manifest:Ua,appTitle:rt})}<style>${Ue}${Vt}${Yt}${rp}</style></head>
1546
1546
  <body>
1547
1547
  ${Ba("Connecting\u2026",`
1548
- <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,nt)}
1548
+ <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,rt)}
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 @@ ${Ba("Connecting\u2026",`
1557
1557
  </section>
1558
1558
  <p id="updated" class="foot"></p>
1559
1559
  </main>
1560
- <script>${z({ageText:Fa,connectionNote:Kt,plainPreview:Jt,clientSentState:ps,clientRequestState:us,clientSummary:ms})}${tp}</script>
1560
+ <script>${z({ageText:Fa,connectionNote:Kt,plainPreview:Jt,clientSentState:hs,clientRequestState:gs,clientSummary:xs})}${op}</script>
1561
1561
  </body>
1562
- </html>`}var tp=`
1562
+ </html>`}var op=`
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 @@ ${Ba("Connecting\u2026",`
1666
1666
  showConn();
1667
1667
  load();
1668
1668
  })();
1669
- `;var Qt="agentx_member",ap=90*86400,np=new Rt,vs=t=>t.replace(/^\[app\]/,"[member]"),rp=new Re(t=>console.log(vs(t))),gs=new WeakMap;function op(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return rp;let e=gs.get(t.log);return e||gs.set(t.log,e=new Re(a=>t.log(vs(a)))),e}var xs=null;function rt(t,e=X){try{return xs=e().people}catch{return xs??t}}async function ys(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 wt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new At(r.root),limiter:r.pairLimiter??np,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return he(e,200,"application/manifest+json",os());if(a===Ua)return he(e,200,"application/manifest+json",fs());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),he(e,200,"text/javascript; charset=utf-8",ss);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 d=await co(t,i);return d.status===200&&e.setHeader("Set-Cookie",bs(d.token)),d.status===429&&e.setHeader("Retry-After",String(d.retryAfter)),_e(e,d.status,d.body)}let l=uo(ip(t),i,lo(t));if(!l.ok){if(l.status===401){let d=Wa(t);return op(r).record(a.slice(0,120),Ut(t,We(Ga(t,Qt),o),d?We(d,o):null)),a==="/member"?he(e,401,"text/html; charset=utf-8",cs()):_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",ds()):_e(e,403,{error:l.error,waiting:!0})}let c=r.people().find(d=>d.id===l.personId),p=c?.role==="client";if(n==="GET"&&a==="/member"){let d=Ga(t,Qt);return d&&!Wa(t)&&e.setHeader("Set-Cookie",bs(d)),he(e,200,"text/html; charset=utf-8",p?hs():ls())}if(n==="GET"&&a==="/api/member/me")return _e(e,200,{person:l.personId,name:c?.name??l.personId,role:c?.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 d=r.db?.()??null;if(!d)return _e(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=Fo(d,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=Wo(d,l.personId,{linkFor:r.linkFor})}catch(T){k("the line",T)}let S=[];if(p)return _e(e,200,{...sp(g),agents:S});try{let T=Go(d,c??{id:l.personId},m);S=Xo(d,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 sp(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 bs(t){return`${Qt}=${t}; Path=/; Max-Age=${ap}; HttpOnly; Secure; SameSite=Lax`}function ip(t){return Wa(t)??Ga(t,Qt)}function Wa(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ga(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))}wd();var ws='/*! 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 ea,readFileSync as Is,writeFileSync as Ms,rmSync as cb,mkdirSync as mp,copyFileSync as fp,readdirSync as hp}from"fs";import{resolve as Je}from"path";kd();function _s(t){let e=gt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:gt.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 Zt(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=gt.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 ks=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Ss(t){return Zt(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 Es(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Zt((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:ks(t?.chats),senders:ks(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 Ts(t){let e=String(t?.id??"");return Zt(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 As(t){let e=String(t?.id??"");return Zt(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}"`})}yt();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 Cs(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.`})+Nt([{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+cp()+Yr,css:pp,scripts:`${e}<script>${Qr}
1670
- ${Zr}
1671
- ${lp}
1672
- ${up}</script>`})}var lp=`
1669
+ `;var Qt="agentx_member",sp=90*86400,ip=new Rt,_s=t=>t.replace(/^\[app\]/,"[member]"),lp=new Re(t=>console.log(_s(t))),ys=new WeakMap;function cp(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return lp;let e=ys.get(t.log);return e||ys.set(t.log,e=new Re(a=>t.log(_s(a)))),e}var ws=null;function ot(t,e=X){try{return ws=e().people}catch{return ws??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 wt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new At(r.root),limiter:r.pairLimiter??ip,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return he(e,200,"application/manifest+json",cs());if(a===Ua)return he(e,200,"application/manifest+json",bs());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),he(e,200,"text/javascript; charset=utf-8",ds);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 d=await fo(t,i);return d.status===200&&e.setHeader("Set-Cookie",ks(d.token)),d.status===429&&e.setHeader("Retry-After",String(d.retryAfter)),_e(e,d.status,d.body)}let l=go(pp(t),i,mo(t));if(!l.ok){if(l.status===401){let d=Wa(t);return cp(r).record(a.slice(0,120),Ut(t,We(Ga(t,Qt),o),d?We(d,o):null)),a==="/member"?he(e,401,"text/html; charset=utf-8",ms()):_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",fs()):_e(e,403,{error:l.error,waiting:!0})}let c=r.people().find(d=>d.id===l.personId),p=c?.role==="client";if(n==="GET"&&a==="/member"){let d=Ga(t,Qt);return d&&!Wa(t)&&e.setHeader("Set-Cookie",ks(d)),he(e,200,"text/html; charset=utf-8",p?vs():us())}if(n==="GET"&&a==="/api/member/me")return _e(e,200,{person:l.personId,name:c?.name??l.personId,role:c?.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 d=r.db?.()??null;if(!d)return _e(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=Xo(d,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=Jo(d,l.personId,{linkFor:r.linkFor})}catch(T){k("the line",T)}let S=[];if(p)return _e(e,200,{...dp(g),agents:S});try{let T=Vo(d,c??{id:l.personId},m);S=Yo(d,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 dp(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 ks(t){return`${Qt}=${t}; Path=/; Max-Age=${sp}; HttpOnly; Secure; SameSite=Lax`}function pp(t){return Wa(t)??Ga(t,Qt)}function Wa(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ga(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))}Ed();var Es='/*! 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 ea,readFileSync as Ps,writeFileSync as $s,rmSync as mb,mkdirSync as xp,copyFileSync as bp,readdirSync as vp}from"fs";import{resolve as Je}from"path";Td();function As(t){let e=gt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:gt.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 Zt(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=gt.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 Ts=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Cs(t){return Zt(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 Is(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Zt((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:Ts(t?.chats),senders:Ts(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 Ms(t){let e=String(t?.id??"");return Zt(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 Rs(t){let e=String(t?.id??"");return Zt(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}"`})}yt();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 Ls(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.`})+Nt([{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+mp()+eo,css:hp,scripts:`${e}<script>${to}
1670
+ ${ao}
1671
+ ${up}
1672
+ ${gp}</script>`})}var up=`
1673
1673
  (function(){
1674
1674
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1675
1675
  async function voiceMissing() {
@@ -1763,8 +1763,8 @@ ${up}</script>`})}var lp=`
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 cp(){let t=Nr().business?`<button data-tab="business">Business</button>
1767
- `:"";return dp.replace("__BUSINESS_TABS__",t)}var dp=`
1766
+ })();`;function mp(){let t=Br().business?`<button data-tab="business">Business</button>
1767
+ `:"";return fp.replace("__BUSINESS_TABS__",t)}var fp=`
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>
@@ -2459,7 +2459,7 @@ ${up}</script>`})}var lp=`
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
- `,pp=`
2462
+ `,hp=`
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
- `,up=`
2670
+ `,gp=`
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 Rs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Cs({peers:a,localToken:n}))}async function Ls(t,e){let a=Ja();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Ps(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 gp(t),r={"GET /api/admin/state":()=>bp(),"POST /api/admin/agents":()=>Sp(n),"PATCH /api/admin/agents":()=>Ep(n),"DELETE /api/admin/agents":()=>Tp(n),"POST /api/admin/agents/access":()=>vp(n),"POST /api/admin/channels/telegram":()=>Ap(n),"DELETE /api/admin/channels/telegram":()=>Yp(n),"POST /api/admin/channels/telegram/toggle":()=>Qp(n),"POST /api/admin/crons":()=>Zp(n),"DELETE /api/admin/crons":()=>eu(n),"POST /api/admin/config/raw":()=>tu(n),"GET /api/admin/tokens":()=>yp(),"POST /api/admin/tokens":()=>wp(n),"DELETE /api/admin/tokens":()=>kp(n),"POST /api/admin/agents/test":()=>_p(n),"POST /api/admin/agents/integrations":()=>jp(n),"DELETE /api/admin/agents/integrations":()=>Op(n),"PATCH /api/admin/agents/integrations":()=>Np(n),"PATCH /api/admin/channels/telegram":()=>Cp(n),"POST /api/admin/channels/slack":()=>Up(n),"POST /api/admin/channels/slack/toggle":()=>Wp(n),"POST /api/admin/channels/discord":()=>Gp(n),"POST /api/admin/channels/discord/toggle":()=>Xp(n),"POST /api/admin/channels/gitlab":()=>Kp(n),"POST /api/admin/channels/gitlab/toggle":()=>Jp(n),"POST /api/admin/channels/request-status":()=>ho(n),"GET /api/admin/channels/whatsapp/state":()=>Ke("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Ke("/webrtc/history"),"POST /api/admin/actions":()=>fu(n),"DELETE /api/admin/actions":()=>hu(n),"POST /api/admin/actions/run":()=>gu(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":()=>Vp(n),"POST /api/admin/webhooks":()=>Dp(n),"PATCH /api/admin/webhooks":()=>Hp(n),"DELETE /api/admin/webhooks":()=>Fp(n),"POST /api/admin/whatsapp-triage":()=>Ss(n),"POST /api/admin/whatsapp-triage/rules":()=>Es(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Ts(n),"DELETE /api/admin/whatsapp-triage/rules":()=>As(n),"POST /api/admin/mesh/peers":()=>Bp(n),"DELETE /api/admin/mesh/peers":()=>qp(n),"POST /api/admin/mesh/toggle":()=>zp(n),"GET /api/admin/files":()=>Mp(t),"GET /api/admin/files/read":()=>Rp(t),"PUT /api/admin/files":()=>Lp(n),"POST /api/admin/files/skill":()=>Pp(n),"DELETE /api/admin/files/skill":()=>$p(n),"POST /api/admin/business/orgchart":()=>au(n),"DELETE /api/admin/business/orgchart":()=>nu(n),"POST /api/admin/business/project":()=>ru(n),"DELETE /api/admin/business/project":()=>iu(n),"POST /api/admin/business/client":()=>ou(n),"DELETE /api/admin/business/client":()=>su(n),"POST /api/admin/business/contact":()=>lu(n),"DELETE /api/admin/business/contact":()=>cu(n),"POST /api/admin/boards":()=>du(n),"DELETE /api/admin/boards":()=>pu(n),"POST /api/admin/boards/columns":()=>uu(n),"DELETE /api/admin/boards/columns":()=>mu(n),"POST /api/admin/notifications":()=>vu(n),"POST /api/admin/wiki/curator":()=>bu(n),"POST /api/admin/screen":()=>wu(n),"POST /api/admin/wiki-notes":()=>yu(n),"GET /api/admin/wiki-notes/list":()=>Ke("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>ku(n),"POST /api/admin/mesh/health":()=>xu(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){Xa(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Xa(e,200,i)}catch(n){Xa(e,400,{error:n.message||"admin op failed"})}}function Xa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function gp(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 xp(t){let e=Je(process.cwd(),t);if(!ea(e))return[];let a=[];for(let n of hp(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Is(Je(e,n.name),"utf-8")))}catch{}return a}function Ja(){let t=Je(process.cwd(),"agentx.json");return ea(t)?JSON.parse(Is(t,"utf-8")):null}function bp(){let t=Ja();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})),c=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}},d=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:mr(k.local),ntfy:vo(t.channels?.ntfy)},S=[];try{S=xp(".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:fo(t),whatsappTriage:_s(t),crons:l,webhooks:c,mesh:p,daemonUrl:d,nodeName:t.node?.name,business:g,boards:T,notifications:b,screen:Kr(t.screen),wikiNotes:xo(t.wikiNotes),actions:S,wikiCurator:Os(t)}}function vp(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 yp(){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 wp(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 kp(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 _p(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(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Sp(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=js(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 d={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(d.model=o),s&&(d.systemPrompt=s.slice(0,400)),p.agents[e]=d,`added agent "${e}"`}),c=Je(i,"CLAUDE.md");if(!ea(c))try{mp(i,{recursive:!0}),Ms(c,`# ${a}
5639
+ `;function js(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ls({peers:a,localToken:n}))}async function Os(t,e){let a=Ja();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Ns(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Pp(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await yp(t),r={"GET /api/admin/state":()=>kp(),"POST /api/admin/agents":()=>Cp(n),"PATCH /api/admin/agents":()=>Ip(n),"DELETE /api/admin/agents":()=>Mp(n),"POST /api/admin/agents/access":()=>_p(n),"POST /api/admin/channels/telegram":()=>Rp(n),"DELETE /api/admin/channels/telegram":()=>tu(n),"POST /api/admin/channels/telegram/toggle":()=>au(n),"POST /api/admin/crons":()=>nu(n),"DELETE /api/admin/crons":()=>ru(n),"POST /api/admin/config/raw":()=>ou(n),"GET /api/admin/tokens":()=>Sp(),"POST /api/admin/tokens":()=>Ep(n),"DELETE /api/admin/tokens":()=>Tp(n),"POST /api/admin/agents/test":()=>Ap(n),"POST /api/admin/agents/integrations":()=>Hp(n),"DELETE /api/admin/agents/integrations":()=>Bp(n),"PATCH /api/admin/agents/integrations":()=>qp(n),"PATCH /api/admin/channels/telegram":()=>Lp(n),"POST /api/admin/channels/slack":()=>Kp(n),"POST /api/admin/channels/slack/toggle":()=>Jp(n),"POST /api/admin/channels/discord":()=>Vp(n),"POST /api/admin/channels/discord/toggle":()=>Yp(n),"POST /api/admin/channels/gitlab":()=>Qp(n),"POST /api/admin/channels/gitlab/toggle":()=>Zp(n),"POST /api/admin/channels/request-status":()=>vo(n),"GET /api/admin/channels/whatsapp/state":()=>Ke("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Ke("/webrtc/history"),"POST /api/admin/actions":()=>bu(n),"DELETE /api/admin/actions":()=>vu(n),"POST /api/admin/actions/run":()=>yu(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":()=>eu(n),"POST /api/admin/webhooks":()=>zp(n),"PATCH /api/admin/webhooks":()=>Fp(n),"DELETE /api/admin/webhooks":()=>Xp(n),"POST /api/admin/whatsapp-triage":()=>Cs(n),"POST /api/admin/whatsapp-triage/rules":()=>Is(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Ms(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Rs(n),"POST /api/admin/mesh/peers":()=>Up(n),"DELETE /api/admin/mesh/peers":()=>Wp(n),"POST /api/admin/mesh/toggle":()=>Gp(n),"GET /api/admin/files":()=>$p(t),"GET /api/admin/files/read":()=>jp(t),"PUT /api/admin/files":()=>Op(n),"POST /api/admin/files/skill":()=>Np(n),"DELETE /api/admin/files/skill":()=>Dp(n),"POST /api/admin/business/orgchart":()=>su(n),"DELETE /api/admin/business/orgchart":()=>iu(n),"POST /api/admin/business/project":()=>lu(n),"DELETE /api/admin/business/project":()=>pu(n),"POST /api/admin/business/client":()=>cu(n),"DELETE /api/admin/business/client":()=>du(n),"POST /api/admin/business/contact":()=>uu(n),"DELETE /api/admin/business/contact":()=>mu(n),"POST /api/admin/boards":()=>fu(n),"DELETE /api/admin/boards":()=>hu(n),"POST /api/admin/boards/columns":()=>gu(n),"DELETE /api/admin/boards/columns":()=>xu(n),"POST /api/admin/notifications":()=>_u(n),"POST /api/admin/wiki/curator":()=>ku(n),"POST /api/admin/screen":()=>Eu(n),"POST /api/admin/wiki-notes":()=>Su(n),"GET /api/admin/wiki-notes/list":()=>Ke("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>Tu(n),"POST /api/admin/mesh/health":()=>wu(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){Xa(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Xa(e,200,i)}catch(n){Xa(e,400,{error:n.message||"admin op failed"})}}function Xa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function yp(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 wp(t){let e=Je(process.cwd(),t);if(!ea(e))return[];let a=[];for(let n of vp(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ps(Je(e,n.name),"utf-8")))}catch{}return a}function Ja(){let t=Je(process.cwd(),"agentx.json");return ea(t)?JSON.parse(Ps(t,"utf-8")):null}function kp(){let t=Ja();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})),c=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}},d=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:gr(k.local),ntfy:_o(t.channels?.ntfy)},S=[];try{S=wp(".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:bo(t),whatsappTriage:As(t),crons:l,webhooks:c,mesh:p,daemonUrl:d,nodeName:t.node?.name,business:g,boards:T,notifications:b,screen:Yr(t.screen),wikiNotes:wo(t.wikiNotes),actions:S,wikiCurator:Bs(t)}}function _p(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 Sp(){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 Ep(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 Tp(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 Ap(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(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Cp(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=Hs(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 d={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(d.model=o),s&&(d.systemPrompt=s.slice(0,400)),p.agents[e]=d,`added agent "${e}"`}),c=Je(i,"CLAUDE.md");if(!ea(c))try{xp(i,{recursive:!0}),$s(c,`# ${a}
5640
5640
 
5641
5641
  ${s||"You are "+a+"."}
5642
- `)}catch{}return{summary:l}}function Ep(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=js(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"&&Bt(o,a.wikiAbsorb),`updated agent "${e}"`});return{summary:n}}function Tp(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 Ap(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 Cp(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}=Va(),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}=Va(),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}=Va(),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 Va(){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=Ja()?.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 Ka(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Mp(t){let e=Ka(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Fe(ot(e));return{agentId:e,...a}}function Rp(t){let e=Ka(t,"agent").trim(),a=Ka(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Lt(ot(e),a)}function Lp(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=Pt(ot(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=$t(ot(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function $p(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=jt(ot(e),a);return{summary:`removed skill "${a}"`,...n}}function jp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=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(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Op(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(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Np(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 c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var $s=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Dp(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(!$s.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(d=>d.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Hp(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"&&$s.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 qp(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 zp(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 Fp(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 Up(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 Wp(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 Gp(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 Xp(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 Kp(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 Jp(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 Vp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-SFHWPWCA.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 Yp(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 Qp(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 Zp(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 eu(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 tu(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(ea(n))try{fp(n,r)}catch{}Ms(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 js(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function au(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(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function nu(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 ru(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 ou(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 su(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 iu(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 lu(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 cu(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 du(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 c=l.boards.findIndex(d=>d.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let d=l.boards[c];return l.boards[c]={...d,...p,columns:d.columns,labels:d.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function pu(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 uu(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(d=>d.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(d=>d.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function mu(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 fu(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 hu(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 gu(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 xu(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 Os(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function bu(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=Os(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function vu(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=fr(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=yo(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 yu(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=>bo(n,e));return{summary:a}}async function wu(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 ku(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}}yt();import{resolve as Eu}from"path";function Ns(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 Ip(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=Hs(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"&&Bt(o,a.wikiAbsorb),`updated agent "${e}"`});return{summary:n}}function Mp(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 Rp(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 Lp(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}=Va(),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}=Va(),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 Pp(t,e){try{let{url:a,headers:n}=Va(),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 Va(){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 st(t){let a=Ja()?.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 Ka(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function $p(t){let e=Ka(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Fe(st(e));return{agentId:e,...a}}function jp(t){let e=Ka(t,"agent").trim(),a=Ka(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Lt(st(e),a)}function Op(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=Pt(st(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Np(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=$t(st(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Dp(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=jt(st(e),a);return{summary:`removed skill "${a}"`,...n}}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)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=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(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Bp(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(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function qp(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 c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Ds=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function zp(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(!Ds.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(d=>d.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Fp(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"&&Ds.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 Up(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 Wp(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 Gp(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 Xp(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 Jp(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 Vp(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 Yp(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 Qp(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 Zp(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 eu(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-73UEBYV4.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 tu(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 au(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 nu(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 ru(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 ou(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(i){throw new Error(`Invalid JSON: ${i.message}`)}let n=Qn.safeParse(Zn(a)),r=n.success?er(n.data):[];if(r.length)throw new Error(r.join(" "));let o=Je(process.cwd(),"agentx.json"),s=`${o}.bak.${Date.now()}`;if(ea(o))try{bp(o,s)}catch{}$s(o,JSON.stringify(a,null,2)+`
5643
+ `,"utf-8");try{let l=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${l}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:s}}function Hs(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function su(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(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function iu(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 lu(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 cu(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 du(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 pu(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 uu(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 mu(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 fu(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 c=l.boards.findIndex(d=>d.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let d=l.boards[c];return l.boards[c]={...d,...p,columns:d.columns,labels:d.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function hu(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 gu(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(d=>d.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(d=>d.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function xu(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 bu(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 vu(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 yu(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 wu(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 Bs(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function ku(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=Bs(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function _u(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=xr(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=So(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 Su(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=>ko(n,e));return{summary:a}}async function Eu(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Qr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Tu(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}}yt();import{resolve as Iu}from"path";function qs(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:_u,scripts:`${e}<script>${Su}</script>`})}var _u=`
5698
+ </section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Au,scripts:`${e}<script>${Cu}</script>`})}var Au=`
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; }`,Su=`
5802
+ details[open] summary { margin-bottom: 8px; }`,Cu=`
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 Hs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ns({peers:a,localToken:n}))}async function Bs(t,e,a){try{let n=t.method==="GET"?void 0:await $u(t),r=Tu(),o={"GET /api/admin/graph/state":()=>Au(r),"POST /api/admin/graph/classifications/approve":()=>Cu(r,n),"POST /api/admin/graph/classifications/reject":()=>Iu(r,n),"POST /api/admin/graph/nodes":()=>Mu(r,n),"PATCH /api/admin/graph/nodes":()=>Ru(r,n),"DELETE /api/admin/graph/nodes":()=>Lu(r,n),"PUT /api/admin/graph/schema":()=>Pu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Ya(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Ya(e,200,l)}catch(n){Ya(e,400,{error:n?.message||"graph op failed"})}}function Tu(){let t=X(),e=Eu(process.cwd(),t.graph.baseDir);return new Qn({baseDir:e})}function Au(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 Cu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=qs(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=Qa(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=qs(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function qs(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 Mu(t,e){let a=Ds(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Ds(String(e.parentId)):null,o=Qa({[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 Ru(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Qa({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Lu(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 Qa(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 Ds(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Ya(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $u(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 zs=`
6022
+ `;function Fs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qs({peers:a,localToken:n}))}async function Us(t,e,a){try{let n=t.method==="GET"?void 0:await Du(t),r=Mu(),o={"GET /api/admin/graph/state":()=>Ru(r),"POST /api/admin/graph/classifications/approve":()=>Lu(r,n),"POST /api/admin/graph/classifications/reject":()=>Pu(r,n),"POST /api/admin/graph/nodes":()=>$u(r,n),"PATCH /api/admin/graph/nodes":()=>ju(r,n),"DELETE /api/admin/graph/nodes":()=>Ou(r,n),"PUT /api/admin/graph/schema":()=>Nu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Ya(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Ya(e,200,l)}catch(n){Ya(e,400,{error:n?.message||"graph op failed"})}}function Mu(){let t=X(),e=Iu(process.cwd(),t.graph.baseDir);return new tr({baseDir:e})}function Ru(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 Lu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ws(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=Qa(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Pu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ws(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Ws(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 $u(t,e){let a=zs(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?zs(String(e.parentId)):null,o=Qa({[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 ju(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Qa({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ou(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Nu(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 Qa(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 zs(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Ya(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Du(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 Gs=`
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>
@@ -6044,12 +6044,14 @@ refresh();
6044
6044
  <label>Nudges per step before you are told it is blocked<input type="number" min="0" step="1" name="maxNudges" required></label>
6045
6045
  <label>Step kinds you approve once, when the plan is made (separated by commas)<input type="text" name="approveKinds" placeholder="message" autocomplete="off"></label>
6046
6046
  <label>Agents that may not open a plan (separated by commas)<input type="text" name="plansOffFor" autocomplete="off"></label>
6047
+ <label>Kinds of work an agent must plan before it starts (separated by commas; empty for none)<input type="text" name="planForWork" placeholder="code" autocomplete="off"></label>
6048
+ <label>Work estimated over this many minutes needs a plan (0: never)<input type="number" min="0" step="1" name="planOverMinutes" required></label>
6047
6049
  <label>Checks agents may use to close a loop (separated by commas)<input type="text" name="checkKinds" placeholder="url, issue, git-ancestor, reply" autocomplete="off"></label>
6048
6050
  <label>Run each loop's check every this many minutes<input type="number" min="1" step="1" name="checkEveryMinutes" required></label>
6049
6051
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6050
6052
  </form>
6051
6053
  </details>
6052
- </section>`,Fs=`
6054
+ </section>`,Xs=`
6053
6055
  .apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
6054
6056
  .apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
6055
6057
  .apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
@@ -6083,7 +6085,7 @@ refresh();
6083
6085
  .apv__loop .is-failed, .apv__loop .is-unverified { color: var(--ax-amber-ink); }
6084
6086
  .apv__loop .is-verified { color: var(--ax-ok, inherit); }
6085
6087
  .apv__stalled { color: var(--ax-err); }
6086
- `,Us=`
6088
+ `,Ks=`
6087
6089
  (function(){
6088
6090
  var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
6089
6091
  function $(id){ return document.getElementById(id); }
@@ -6114,11 +6116,18 @@ function plan(p){
6114
6116
  (extra ? '<small>' + esc(extra) + '</small>' : '') + '</li>';
6115
6117
  }).join('') + '</ol>';
6116
6118
  }
6119
+ function workLabel(work, minutes){ return [work || '', minutes != null ? 'about ' + Math.round(minutes) + ' min' : ''].filter(Boolean).join(', '); }
6117
6120
  // Who it is owed to, when it is due, what closes it, and why it is stalled (#1039).
6118
6121
  function loop(r){
6119
6122
  var l = r.loop, bits = [];
6120
6123
  if (l && l.promise && l.owedTo) bits.push('Promised to <b>' + esc(l.owedTo === 'owner' ? 'you' : agentName(l.owedTo)) + '</b>');
6121
6124
  if (l && l.dueAt) bits.push('Due ' + esc(when(l.dueAt)));
6125
+ // What the agent declared when it accepted (#1048).
6126
+ // A change after a refused accept shows the first declaration too.
6127
+ if (r.work || r.estimateMinutes != null) {
6128
+ var now = workLabel(r.work, r.estimateMinutes), first = workLabel(r.firstWork, r.firstEstimateMinutes);
6129
+ bits.push('Work: ' + esc(now) + (first && first !== now ? ' <small>(first declared: ' + esc(first) + ')</small>' : ''));
6130
+ }
6122
6131
  if (l && l.check) bits.push('Closes when ' + esc(l.check) + (l.verifyState ? ' <span class="is-' + esc(l.verifyState) + '">(' + esc(VERIFY[l.verifyState] || l.verifyState) + (l.verifyDetail ? ': ' + esc(l.verifyDetail) : '') + ')</span>' : ''));
6123
6132
  var stalled = r.stall ? '<p class="apv__loop apv__stalled">Stalled, waiting on ' + esc(r.stall.group === 'agent' ? agentName(r.stall.who) : r.stall.group === 'person' ? r.stall.who : 'you') + ': ' + esc(r.stall.why) + '</p>' : '';
6124
6133
  return (bits.length ? '<p class="apv__loop">' + bits.join(' \xB7 ') + '</p>' : '') + stalled;
@@ -6167,6 +6176,8 @@ function fill(s){
6167
6176
  f.maxNudges.value = p.maxNudges == null ? 3 : p.maxNudges;
6168
6177
  f.approveKinds.value = (p.approveKinds || []).join(', ');
6169
6178
  f.plansOffFor.value = (p.disabledAgents || []).join(', ');
6179
+ f.planForWork.value = (p.requireForWork || []).join(', ');
6180
+ f.planOverMinutes.value = p.requireOverMinutes == null ? 30 : p.requireOverMinutes;
6170
6181
  var c = s.checkers || {};
6171
6182
  f.checkKinds.value = (c.enabled || []).join(', ');
6172
6183
  f.checkEveryMinutes.value = c.checkEveryMinutes || 10;
@@ -6264,6 +6275,8 @@ $('req-form').addEventListener('submit', async function(ev){
6264
6275
  maxNudges: Number(f.maxNudges.value),
6265
6276
  approveKinds: f.approveKinds.value,
6266
6277
  plansOffFor: f.plansOffFor.value,
6278
+ planForWork: f.planForWork.value,
6279
+ planOverMinutes: Number(f.planOverMinutes.value),
6267
6280
  checkKinds: f.checkKinds.value,
6268
6281
  checkEveryMinutes: Number(f.checkEveryMinutes.value)
6269
6282
  };
@@ -6286,7 +6299,7 @@ function busy(){
6286
6299
  }
6287
6300
  setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
6288
6301
  })();
6289
- `;function Ws(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6302
+ `;function Js(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6290
6303
  <header class="apv__head">
6291
6304
  <div>
6292
6305
  <h1>Approvals</h1>
@@ -6308,7 +6321,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
6308
6321
  <ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
6309
6322
  <p id="apv-snoozed" class="apv__foot"></p>
6310
6323
 
6311
- ${zs}
6324
+ ${Gs}
6312
6325
 
6313
6326
  <details class="apv__settings" id="apv-settings">
6314
6327
  <summary>Settings: expiry, later, daily digest</summary>
@@ -6323,7 +6336,7 @@ ${zs}
6323
6336
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6324
6337
  </form>
6325
6338
  </details>
6326
- </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ju+Fs,scripts:`${e}<script>${Ou}</script><script>${Us}</script>`})}var ju=`
6339
+ </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Hu+Xs,scripts:`${e}<script>${Bu}</script><script>${Ks}</script>`})}var Hu=`
6327
6340
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
6328
6341
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
6329
6342
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -6380,7 +6393,7 @@ ${zs}
6380
6393
  @media (max-width: 560px) {
6381
6394
  .apv__acts .ax-btn { flex: 1 1 0; }
6382
6395
  }
6383
- `,Ou=`
6396
+ `,Bu=`
6384
6397
  (function(){
6385
6398
  var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
6386
6399
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
@@ -6604,7 +6617,7 @@ $('apv-form').addEventListener('submit', async function(ev){
6604
6617
  load();
6605
6618
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within, .apv__item[data-touched]')) load(); }, 60000);
6606
6619
  })();
6607
- `;import{existsSync as Nu,readFileSync as Du}from"fs";Sd();var xe="/api/admin/approvals/requests";function Gs(t){let e=rr(t);if(!Nu(e))return[];try{let a=JSON.parse(Du(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 st=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function ta(t,e,a,n){try{return await Hu(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Hu(t,e,a,n){if(t==="GET"&&e===xe){let o=ze(n),s=Gs(n.configPath),i=Ct(n.configPath),l=new Set(s.map(m=>m.id)),c={staleAfterHours:i.staleAfterHours,now:n.now??Date.now(),isAgent:m=>l.has(m)},p=o?o.listOpen().map(m=>Mr(m,o,Er(n),c)):[],d=Object.fromEntries(Tr.map(m=>[m,0]));for(let m of p)m.stall&&d[m.stall.group]++;return{status:200,body:{items:p,agents:s,settings:i,stalled:d}}}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),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",d=Gs(n.configPath).find(g=>g.id===p);if(r==="handoff"&&!d)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!Ct(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=d?.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 c=typeof a.evidence=="string"&&a.evidence.trim()?a.evidence.trim():typeof a.reason=="string"&&a.reason.trim()?a.reason.trim():"",p=s==="done"?l.closeWhen?`closed by owner: ${c||"checked by hand"}`:c||"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",p,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 m=a[d];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${d} must be a positive number`);return m}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=st(a.from),o.channels=st(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=st(a.approveKinds),i.disabledAgents=st(a.plansOffFor),Object.values(i).some(d=>d!==void 0)&&(o.plans=i);let l={},c=st(a.checkKinds);if(c){let d=c.filter(m=>!ka.includes(m));if(d.length)throw new Error(`unknown check ${d.join(", ")}: use ${ka.join(", ")}`);l.enabled=c}l.checkEveryMinutes=s("checkEveryMinutes"),Object.values(l).some(d=>d!==void 0)&&(o.checkers=l);let p=await Sr(o,{configPath:n.configPath,reload:n.reload});return p.success?{status:200,body:{ok:!0,settings:Ct(n.configPath)}}:{status:400,body:{error:p.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 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 qu(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 Xs(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Ws({peers:e,localToken:a}))}async function Ks(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=It(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:"",c=i.action;if(!l||!Bu.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Ie(s.configPath),d=await Mt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)",...qu(i)});return d.ok?(te(e,200,{ok:!0,message:d.message}),!0):(te(e,409,{error:d.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await aa(t),l=Rr(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={},c=d=>{let m=i[d];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${d} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let d=i.destination.trim();if(!d)l.destination=null;else{let m=oo(d);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await so(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}Ta();function Js(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."})+`
6620
+ `;import{existsSync as qu,readFileSync as zu}from"fs";Cd();var xe="/api/admin/approvals/requests";function Vs(t){let e=ir(t);if(!qu(e))return[];try{let a=JSON.parse(zu(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 Ve=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function ta(t,e,a,n){try{return await Fu(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Fu(t,e,a,n){if(t==="GET"&&e===xe){let o=ze(n),s=Vs(n.configPath),i=Ct(n.configPath),l=new Set(s.map(m=>m.id)),c={staleAfterHours:i.staleAfterHours,now:n.now??Date.now(),isAgent:m=>l.has(m)},p=o?o.listOpen().map(m=>Lr(m,o,Cr(n),c)):[],d=Object.fromEntries(Mr.map(m=>[m,0]));for(let m of p)m.stall&&d[m.stall.group]++;return{status:200,body:{items:p,agents:s,settings:i,stalled:d}}}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),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",d=Vs(n.configPath).find(g=>g.id===p);if(r==="handoff"&&!d)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!Ct(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=d?.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 c=typeof a.evidence=="string"&&a.evidence.trim()?a.evidence.trim():typeof a.reason=="string"&&a.reason.trim()?a.reason.trim():"",p=s==="done"?l.closeWhen?`closed by owner: ${c||"checked by hand"}`:c||"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",p,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 m=a[d];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${d} must be a positive number`);return m}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=Ve(a.from),o.channels=Ve(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}if(i.approveKinds=Ve(a.approveKinds),i.disabledAgents=Ve(a.plansOffFor),i.requireForWork=Ve(a.planForWork),a.planOverMinutes!==void 0){if(typeof a.planOverMinutes!="number"||!(a.planOverMinutes>=0))throw new Error("planOverMinutes must be a number, 0 or more");i.requireOverMinutes=a.planOverMinutes}Object.values(i).some(d=>d!==void 0)&&(o.plans=i);let l={},c=Ve(a.checkKinds);if(c){let d=c.filter(m=>!ka.includes(m));if(d.length)throw new Error(`unknown check ${d.join(", ")}: use ${ka.join(", ")}`);l.enabled=c}l.checkEveryMinutes=s("checkEveryMinutes"),Object.values(l).some(d=>d!==void 0)&&(o.checkers=l);let p=await Ar(o,{configPath:n.configPath,reload:n.reload});return p.success?{status:200,body:{ok:!0,settings:Ct(n.configPath)}}:{status:400,body:{error:p.error}}}return{status:404,body:{error:"Not found"}}}var Uu=["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 Wu(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 Ys(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Js({peers:e,localToken:a}))}async function Qs(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=It(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:"",c=i.action;if(!l||!Uu.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Ie(s.configPath),d=await Mt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)",...Wu(i)});return d.ok?(te(e,200,{ok:!0,message:d.message}),!0):(te(e,409,{error:d.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await aa(t),l=$r(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={},c=d=>{let m=i[d];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${d} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let d=i.destination.trim();if(!d)l.destination=null;else{let m=co(d);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await po(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}Ta();function Zs(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."})+`
6608
6621
  <div class="pp">
6609
6622
  <div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
6610
6623
  <section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
@@ -6617,7 +6630,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6617
6630
  </ol>
6618
6631
  </section>
6619
6632
  <ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
6620
- </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:zu,scripts:`${e}<script>${Fu}</script>`})}var zu=`
6633
+ </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Gu,scripts:`${e}<script>${Xu}</script>`})}var Gu=`
6621
6634
  .pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
6622
6635
  .pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
6623
6636
  .pp-msg.is-bad { color: var(--ax-red-ink); }
@@ -6658,7 +6671,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6658
6671
  .pp-text { overflow-wrap: anywhere; }
6659
6672
  .pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
6660
6673
  @media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
6661
- `,Fu=`
6674
+ `,Xu=`
6662
6675
  (function () {
6663
6676
  var list = document.getElementById('pp-list');
6664
6677
  var msg = document.getElementById('pp-msg');
@@ -6796,7 +6809,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6796
6809
  load();
6797
6810
  setInterval(load, 30000);
6798
6811
  })();
6799
- `;var Za="/api/admin/people";function Uu(t,e){let a=po(t,e);return a?{...e,answer:a}:e}function Wu(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 Gu(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&Wu(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:vt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Xu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Vs(t,e,a,n){if(a!=="/people"&&a!==Za&&!a.startsWith(`${Za}/`))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(Js({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=c=>n.members.devices(c).map(p=>Uu(n.root,p)),s=()=>Gu(n.people(),o());if(r==="GET"&&a===Za){let c=s();return be(e,200,{people:c,paired:c.reduce((p,d)=>p+d.machines.active+d.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(g=>g.id===i[1]);if(!c)return be(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),d=[],m=[];try{p&&(d=io(p,c.id))}catch{}try{p&&(m=Ht(p,c.id,20))}catch{}return be(e,200,{person:c,devices:o(c.id).sort(Xu),requests:d,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[,c,p]=l,d=n.members.byToken(p);if(!d||d.personId!==c)return be(e,404,{error:"no such machine for this person"}),!0;if(d.state==="removed")return be(e,409,{error:"this machine's access has already ended"}),!0;let m=mo({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 Qu}from"path";import{existsSync as Zu}from"fs";import em from"better-sqlite3";var Ys=new WeakSet;function Ku(t,e,a={}){if(Ys.has(t))return;Ys.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 c=i[l].bind(i);i[l]=(...p)=>{let d=r();try{return c(...p)}finally{let m=r()-d;m>=n&&e({sql:s,ms:m})}}}return i}}function Ju(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){Ku(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Ju(a)}`))}function Qs(t={}){let e=`<div class="ax-obs">
6812
+ `;var Za="/api/admin/people";function Ku(t,e){let a=ho(t,e);return a?{...e,answer:a}:e}function Ju(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 Vu(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&Ju(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:vt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Yu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function ei(t,e,a,n){if(a!=="/people"&&a!==Za&&!a.startsWith(`${Za}/`))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(Zs({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=c=>n.members.devices(c).map(p=>Ku(n.root,p)),s=()=>Vu(n.people(),o());if(r==="GET"&&a===Za){let c=s();return be(e,200,{people:c,paired:c.reduce((p,d)=>p+d.machines.active+d.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(g=>g.id===i[1]);if(!c)return be(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),d=[],m=[];try{p&&(d=uo(p,c.id))}catch{}try{p&&(m=Ht(p,c.id,20))}catch{}return be(e,200,{person:c,devices:o(c.id).sort(Yu),requests:d,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[,c,p]=l,d=n.members.byToken(p);if(!d||d.personId!==c)return be(e,404,{error:"no such machine for this person"}),!0;if(d.state==="removed")return be(e,409,{error:"this machine's access has already ended"}),!0;let m=xo({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 am}from"path";import{existsSync as nm}from"fs";import rm from"better-sqlite3";var ti=new WeakSet;function Qu(t,e,a={}){if(ti.has(t))return;ti.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 c=i[l].bind(i);i[l]=(...p)=>{let d=r();try{return c(...p)}finally{let m=r()-d;m>=n&&e({sql:s,ms:m})}}}return i}}function Zu(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){Qu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Zu(a)}`))}function ai(t={}){let e=`<div class="ax-obs">
6800
6813
  <header class="ax-obs__head">
6801
6814
  <h1>Health</h1>
6802
6815
  <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>
@@ -6918,7 +6931,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6918
6931
  </div>
6919
6932
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
6920
6933
  </section>
6921
- </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Vu,scripts:`<script>${Yu}</script>`})}var Vu=`
6934
+ </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:em,scripts:`<script>${tm}</script>`})}var em=`
6922
6935
  .ax-obs { padding: 16px 24px; }
6923
6936
  .ax-obs__head { margin-bottom: 16px; }
6924
6937
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -7035,7 +7048,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7035
7048
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
7036
7049
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
7037
7050
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
7038
- `,Yu=`
7051
+ `,tm=`
7039
7052
  (function(){
7040
7053
  var panes = document.querySelectorAll('.ax-obs__pane');
7041
7054
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -7419,7 +7432,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7419
7432
 
7420
7433
  load(current);
7421
7434
  })();
7422
- `;var ti={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 ai(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function en(t){let e=ti[ai(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 tm(){let t=Qu(process.cwd(),".agentx/db.sqlite");if(!Zu(t))return null;try{let e=new em(t,{readonly:!0,fileMustExist:!0});return Se(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function ni(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qs({peers:a}))}function am(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 ri(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=tm();if(!r)return ve(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=am(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
7435
+ `;var oi={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 si(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function en(t){let e=oi[si(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 om(){let t=am(process.cwd(),".agentx/db.sqlite");if(!nm(t))return null;try{let e=new rm(t,{readonly:!0,fileMustExist:!0});return Se(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function ii(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ai({peers:a}))}function sm(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 li(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=om();if(!r)return ve(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=sm(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
7423
7436
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
7424
7437
  FROM route_traces
7425
7438
  ${i.length?"WHERE "+i.join(" AND "):""}
@@ -7434,8 +7447,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7434
7447
  FROM task_history
7435
7448
  WHERE ${i.join(" AND ")}
7436
7449
  ORDER BY started_at DESC LIMIT @limit
7437
- `,d=r.db.prepare(c).all(l).map(m=>({...m,plain:oi(m.error)}));return ve(e,200,{rows:d}),!0}if(n==="summary"||n==="overview")return ve(e,200,nm(r.db)),!0;if(n==="activity")return ve(e,200,rm(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Zs(i.searchParams.get("range"));return ve(e,200,ei(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Zs(i.searchParams.get("range")),c=ei(r.db,l),p=om(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return 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 oi(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(`
7438
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function nm(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),d=x=>p.length?p[Math.min(p.length-1,Math.floor(p.length*x))].duration_ms:0,m=d(.5),g=d(.95),b=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((x,A)=>x+en(A),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((x,A)=>x+en(A),0),T=t.prepare(`
7450
+ `,d=r.db.prepare(c).all(l).map(m=>({...m,plain:ci(m.error)}));return ve(e,200,{rows:d}),!0}if(n==="summary"||n==="overview")return ve(e,200,im(r.db)),!0;if(n==="activity")return ve(e,200,lm(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=ni(i.searchParams.get("range"));return ve(e,200,ri(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=ni(i.searchParams.get("range")),c=ri(r.db,l),p=cm(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return 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 ci(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(`
7451
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function im(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),d=x=>p.length?p[Math.min(p.length-1,Math.floor(p.length*x))].duration_ms:0,m=d(.5),g=d(.95),b=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((x,A)=>x+en(A),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((x,A)=>x+en(A),0),T=t.prepare(`
7439
7452
  SELECT agent_id,
7440
7453
  COUNT(*) AS tasks,
7441
7454
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -7458,7 +7471,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7458
7471
  FROM task_history
7459
7472
  WHERE status='error' AND started_at >= ?
7460
7473
  ORDER BY started_at DESC LIMIT 5
7461
- `).all(o).map(x=>({...x,plain:oi(x.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:g,spendToday:b,spendDelta:b-S,idleAgentCount:v.length},perAgent:T,perChannel:h,idleAgents:v,recentErrors:E}}function rm(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(`
7474
+ `).all(o).map(x=>({...x,plain:ci(x.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:g,spendToday:b,spendDelta:b-S,idleAgentCount:v.length},perAgent:T,perChannel:h,idleAgents:v,recentErrors:E}}function lm(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(`
7462
7475
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
7463
7476
  COUNT(*) AS tasks,
7464
7477
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -7485,7 +7498,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7485
7498
  WHERE started_at >= @since
7486
7499
  GROUP BY agent_id
7487
7500
  ORDER BY tasks_24h DESC, tasks_7d DESC
7488
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Zs(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 ei(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7501
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function ni(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 ri(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7489
7502
  SELECT day, agent_id, model,
7490
7503
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
7491
7504
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -7493,10 +7506,10 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7493
7506
  FROM usage_daily
7494
7507
  ${a}
7495
7508
  ORDER BY day
7496
- `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,d=0,m=0,g=0,k=0,b=0,S=0,T={},h={};for(let _ of n){let R=en(_),j=ai(_.model),$=ti[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),de=(_.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);d+=R,_.day>=s&&(p+=R,k+=_.tasks||0),_.day>=i&&_.day<s&&(S+=R,b+=_.tasks||0),_.day===r&&(l+=R),_.day===o&&(c+=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+=de,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+=de,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+=de,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:c,spend7d:p,spend30d:d,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 om(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+`
7509
+ `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,d=0,m=0,g=0,k=0,b=0,S=0,T={},h={};for(let _ of n){let R=en(_),j=si(_.model),$=oi[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),de=(_.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);d+=R,_.day>=s&&(p+=R,k+=_.tasks||0),_.day>=i&&_.day<s&&(S+=R,b+=_.tasks||0),_.day===r&&(l+=R),_.day===o&&(c+=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+=de,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+=de,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+=de,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:c,spend7d:p,spend30d:d,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 cm(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+`
7497
7510
  `+a.join(`
7498
7511
  `)+`
7499
- `}import{resolve as sm}from"path";import{existsSync as im}from"fs";import lm from"better-sqlite3";function cm(){let t=sm(process.cwd(),".agentx/intent/ledger.sqlite");if(!im(t))return null;try{let e=new lm(t,{readonly:!0,fileMustExist:!0});return Se(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-si>6e4&&(si=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var si=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function dm(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 ii(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=cm();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=dm(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let d=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 ${d} 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 ${d}`).get({since:s}).n,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${d} GROUP BY source ORDER BY n DESC`).all({since:s}),h=r.db.prepare(`
7512
+ `}import{resolve as dm}from"path";import{existsSync as pm}from"fs";import um from"better-sqlite3";function mm(){let t=dm(process.cwd(),".agentx/intent/ledger.sqlite");if(!pm(t))return null;try{let e=new um(t,{readonly:!0,fileMustExist:!0});return Se(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-di>6e4&&(di=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var di=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function fm(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 pi(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=mm();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=fm(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let d=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 ${d} 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 ${d}`).get({since:s}).n,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${d} GROUP BY source ORDER BY n DESC`).all({since:s}),h=r.db.prepare(`
7500
7513
  SELECT COUNT(*) AS n FROM intent_decisions d
7501
7514
  LEFT JOIN intent_resolutions r
7502
7515
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
@@ -7523,7 +7536,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7523
7536
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7524
7537
  WHERE ${d.join(" AND ")}
7525
7538
  ORDER BY d.decided_at DESC LIMIT @limit
7526
- `;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 li(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7539
+ `;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 ui(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7527
7540
  <header class="ax-led__head">
7528
7541
  <h1>Intent ledger</h1>
7529
7542
  <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>
@@ -7728,7 +7741,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7728
7741
  }
7729
7742
  load();
7730
7743
  })();
7731
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function ci(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7744
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function mi(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7732
7745
  <header class="ax-cost__head">
7733
7746
  <div>
7734
7747
  <h1>Cost</h1>
@@ -8301,7 +8314,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8301
8314
  load();
8302
8315
  setInterval(load, 30000);
8303
8316
  })();
8304
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function di(t={}){let e=`<div class="ax-pj__root">
8317
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function fi(t={}){let e=`<div class="ax-pj__root">
8305
8318
  <aside class="ax-pj__list">
8306
8319
  <header>
8307
8320
  <h2>Projects</h2>
@@ -8328,7 +8341,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8328
8341
  </header>
8329
8342
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
8330
8343
  </section>
8331
- </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:pm,scripts:`<script>${um}</script>`})}var pm=`
8344
+ </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:hm,scripts:`<script>${gm}</script>`})}var hm=`
8332
8345
  .ax-pj__root {
8333
8346
  display: grid;
8334
8347
  grid-template-columns: 360px 1fr;
@@ -8515,7 +8528,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8515
8528
  }
8516
8529
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
8517
8530
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
8518
- `,um=`
8531
+ `,gm=`
8519
8532
  (function(){
8520
8533
  const $ = (sel) => document.querySelector(sel);
8521
8534
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -9165,9 +9178,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
9165
9178
  load();
9166
9179
  });
9167
9180
  })();
9168
- `;import{resolve as on,join as Cm}from"path";import{existsSync as sn,readdirSync as Im,readFileSync as Mm}from"fs";import Rm from"better-sqlite3";var ui=String.raw`[\w.-]+(?:/[\w.-]+)+`,mm=new RegExp(`^(?:chat:)?(${ui}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),fm=new RegExp(`^\\[(?:GitLab|GitHub) (${ui}) `);function pi(t){if(!t)return null;let e=t.match(mm);return e?e[1]:null}function tn(t){if(!t)return null;let e=t.trimStart().match(fm);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():pi(typeof n?.chatId=="string"?n.chatId:null)??pi(e)??tn(a)}function hm(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 gm=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,xm=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,bm=t=>/^issue/i.test(t)?"issue":"mr";function vm(t){let e=t.subject.match(gm)??t.inputPreview.trimStart().match(xm);return e?{kind:bm(e[1]),n:Number(e[2])}:null}function ym(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 mi(t){if(!hm(t.projectId))return[];let e=vm(t);return e?[e]:ym(t.inputPreview)}var wm=6e4,km=5*6e4,_m=40,fi=6,hi=new Map;function gi(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 mi(n)){let s=ra(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=_m)return[...e.values()]}}return[...e.values()]}async function xi(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ra(s.project,s.ref),l=hi.get(i);l&&n-l.at<(s.github?km:wm)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=fi)await Promise.all(o.slice(s,s+fi).map(async i=>{let l=ra(i.project,i.ref),c=null;try{c=i.github?await Em(i,e,a):await Sm(i,e,a)}catch{}hi.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function bi(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 Sm(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 bi(`${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 Em(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 bi(`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}Un();var an=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function vi(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=xt(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=an(o.from,80);if(s){a.callback={from:s,status:an(o.status,20)??"done"};let i=an(o.peer,80);i&&(a.callback.peer=i)}}return a}Un();Ta();var yi={kind:"agentx",id:"agentx",name:"AgentX"},nn={kind:"person",id:"unknown",name:"Unknown"},Tm=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),wi=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 Am(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 ki(t){let e=s=>({kind:"person",id:`person:${s}`,name:Jn(t.people,s)}),a=(s,i)=>i||Tm.has(s)?yi:{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)??Yn(t.people,s)?.id;if(i)return e(i);let l=xt(s),c=l?.channel??t.channel;if(Fn(s)==="human")return wi(s?.senderUsername)?a(c,!1):nn;let p=!!Pe(n.senderAgentId)||wa(l?l.sender:s?.sender);return c==="desktop"&&!p?nn:a(c,p)}let r=Am(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Vn(t.people,t.channel,r);return o?e(o.id):wa(r.name)?yi:zn.has(t.channel)&&!wi(r.username)?nn:a(t.channel,!1)}function ln(){let t=on(process.cwd(),".agentx/intent/ledger.sqlite");if(!sn(t))return null;try{let e=new Rm(t,{readonly:!0,fileMustExist:!0});return Se(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-_i>6e4&&(_i=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var _i=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 Lm(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 Ti(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 Ai(t,e,a){return pr(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 $m(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&&!rn(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!rn(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Om(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!rn(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",d=Si(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:d}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),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:Si(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 jm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Om(t,e){let a=jm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Si(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function rn(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 Ci(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}
9181
+ `;import{resolve as on,join as Lm}from"path";import{existsSync as sn,readdirSync as Pm,readFileSync as $m}from"fs";import jm from"better-sqlite3";var gi=String.raw`[\w.-]+(?:/[\w.-]+)+`,xm=new RegExp(`^(?:chat:)?(${gi}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),bm=new RegExp(`^\\[(?:GitLab|GitHub) (${gi}) `);function hi(t){if(!t)return null;let e=t.match(xm);return e?e[1]:null}function tn(t){if(!t)return null;let e=t.trimStart().match(bm);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():hi(typeof n?.chatId=="string"?n.chatId:null)??hi(e)??tn(a)}function vm(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 ym=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,wm=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,km=t=>/^issue/i.test(t)?"issue":"mr";function _m(t){let e=t.subject.match(ym)??t.inputPreview.trimStart().match(wm);return e?{kind:km(e[1]),n:Number(e[2])}:null}function Sm(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 xi(t){if(!vm(t.projectId))return[];let e=_m(t);return e?[e]:Sm(t.inputPreview)}var Em=6e4,Tm=5*6e4,Am=40,bi=6,vi=new Map;function yi(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 xi(n)){let s=ra(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Am)return[...e.values()]}}return[...e.values()]}async function wi(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ra(s.project,s.ref),l=vi.get(i);l&&n-l.at<(s.github?Tm:Em)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=bi)await Promise.all(o.slice(s,s+bi).map(async i=>{let l=ra(i.project,i.ref),c=null;try{c=i.github?await Im(i,e,a):await Cm(i,e,a)}catch{}vi.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function ki(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 Cm(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 ki(`${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 Im(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 ki(`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}Un();var an=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function _i(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=xt(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=an(o.from,80);if(s){a.callback={from:s,status:an(o.status,20)??"done"};let i=an(o.peer,80);i&&(a.callback.peer=i)}}return a}Un();Ta();var Si={kind:"agentx",id:"agentx",name:"AgentX"},nn={kind:"person",id:"unknown",name:"Unknown"},Mm=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Ei=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 Rm(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 Ti(t){let e=s=>({kind:"person",id:`person:${s}`,name:Jn(t.people,s)}),a=(s,i)=>i||Mm.has(s)?Si:{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)??Yn(t.people,s)?.id;if(i)return e(i);let l=xt(s),c=l?.channel??t.channel;if(Fn(s)==="human")return Ei(s?.senderUsername)?a(c,!1):nn;let p=!!Pe(n.senderAgentId)||wa(l?l.sender:s?.sender);return c==="desktop"&&!p?nn:a(c,p)}let r=Rm(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Vn(t.people,t.channel,r);return o?e(o.id):wa(r.name)?Si:zn.has(t.channel)&&!Ei(r.username)?nn:a(t.channel,!1)}function ln(){let t=on(process.cwd(),".agentx/intent/ledger.sqlite");if(!sn(t))return null;try{let e=new jm(t,{readonly:!0,fileMustExist:!0});return Se(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ai>6e4&&(Ai=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Ai=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 Om(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 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 Nm(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 Ri(t,e,a){return fr(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 Dm(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&&!rn(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!rn(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Bm(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!rn(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",d=Ci(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:d}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),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:Ci(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 Hm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Bm(t,e){let a=Hm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Ci(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function rn(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 Li(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}
9169
9182
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
9170
- ${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 Nm(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 Ii(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
9183
+ ${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 qm(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 Pi(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
9171
9184
  SELECT id, ts, source, project, subject, intent, raw_json
9172
9185
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
9173
9186
  `).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(`
@@ -9176,9 +9189,9 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
9176
9189
  `).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(`
9177
9190
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
9178
9191
  FROM intent_resolutions WHERE decision_event_id IN (${A})
9179
- `).all(L);for(let j of R)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,c=new Map,p=new Map,d=new Map,m=[],g=e?.business?.projects??[],k=e?.business?.contactMap??[],b=Ia(e?.business??{}),S=e?.people??[];for(let x of o){let A=null;try{A=JSON.parse(x.raw_json)}catch{}let L=Ai(x.source,A,k),_=Ci(x.source,A),R=vi(A),j=x.project??na(A,x.subject,_),$=null,O=null;L?($=L.client,O=L.project||`${L.client}/_chat`):j&&($=St(j,g),O=j);let W=Lm(x.source,x.intent||"",A),de=$e[W]||{label:W,color:"#6b7280"};p.has(W)||p.set(W,{id:W,label:de.label,color:de.color});let Q=ki({source:x.source,channel:W,raw:A,people:S,channelLabel:N=>$e[N]?.label??N}),oe="__system",Z,F=$m(x.source,x.intent||"",A);if(F){oe=F.id,Z=F.kind;let N=L?.displayName||F.name;(!d.has(F.id)||L?.displayName)&&d.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else d.has("__system")||d.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 bd=`${x.id}|${N.decided_by}`,ht=i.get(bd),Dn=N.decided_at,Hn=ht?.resolved_at??null,va=Hn===null,vd=ht?.duration_ms??(va?n-Dn:0),yd=va?"active":ht?.status==="error"||ht?.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:Ti(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.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:Nm(x.subject),intent:x.intent||"",startedAt:Dn,resolvedAt:Hn,duration:vd,active:va,outcome:yd,tokens:0,inputPreview:_,system:Pm(N.agent_id,e),...R,starter:Q})}}let T=[...l.values()].map(x=>({...x,projects:[...c.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=[...d.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 cn(t){let e=ln();if(!e)return null;try{return Ii(e.db,Ri(),t)}finally{e.close()}}function Mi(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let d of p.clients){let m=e.get(d.id);if(!m)e.set(d.id,{...d,projects:[...d.projects]});else{let g=Array.from(new Set([...m.projects,...d.projects])).sort();e.set(d.id,{...m,projects:g})}}for(let d of p.agents)a.has(d.id)||a.set(d.id,d);for(let d of p.channels)n.has(d.id)||n.set(d.id,d);for(let d of p.initiators)r.has(d.id)||r.set(d.id,d);for(let d of p.dispatches){let m=Dm(d);if(m.clientId!==d.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Ti(m.clientId),projects:[]}),m.projectId!==d.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:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function Dm(t){if(t.clientId!=="unmapped")return t;let e=tn(t.inputPreview);if(!e)return t;let a=we?.business?.projects??[];return{...t,projectId:e,clientId:St(e,a)}}async function oa(t){let e=we?.channels?.gitlab,a=await xi(gi(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 Ri(){return we&&{...we,people:rt(we.people)}}function Li(t){we=t}async function Pi(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=ln();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=$i(parseInt(r.searchParams.get("hours")||"6",10));ye(e,200,await oa(Ii(n.db,Ri(),o)))}catch(r){ye(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Hm=5e3;async function dn(t,e,a,n=cn){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
9192
+ `).all(L);for(let j of R)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,c=new Map,p=new Map,d=new Map,m=[],g=e?.business?.projects??[],k=e?.business?.contactMap??[],b=Ia(e?.business??{}),S=e?.people??[];for(let x of o){let A=null;try{A=JSON.parse(x.raw_json)}catch{}let L=Ri(x.source,A,k),_=Li(x.source,A),R=_i(A),j=x.project??na(A,x.subject,_),$=null,O=null;L?($=L.client,O=L.project||`${L.client}/_chat`):j&&($=St(j,g),O=j);let W=Om(x.source,x.intent||"",A),de=$e[W]||{label:W,color:"#6b7280"};p.has(W)||p.set(W,{id:W,label:de.label,color:de.color});let Q=Ti({source:x.source,channel:W,raw:A,people:S,channelLabel:N=>$e[N]?.label??N}),oe="__system",Z,F=Dm(x.source,x.intent||"",A);if(F){oe=F.id,Z=F.kind;let N=L?.displayName||F.name;(!d.has(F.id)||L?.displayName)&&d.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else d.has("__system")||d.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 kd=`${x.id}|${N.decided_by}`,ht=i.get(kd),Dn=N.decided_at,Hn=ht?.resolved_at??null,va=Hn===null,_d=ht?.duration_ms??(va?n-Dn:0),Sd=va?"active":ht?.status==="error"||ht?.status==="fail"?"error":"completed",ee,at;if($)ee=$,at=O;else{let ya=b.get(N.agent_id);ya?(ee=ya,at=`${ya}/_${x.source}`):(ee="unmapped",at=`unmapped/_${x.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:Mi(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(at),m.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:at,channelId:W,initiatorId:oe,initiatorKind:Z,subject:qm(x.subject),intent:x.intent||"",startedAt:Dn,resolvedAt:Hn,duration:_d,active:va,outcome:Sd,tokens:0,inputPreview:_,system:Nm(N.agent_id,e),...R,starter:Q})}}let T=[...l.values()].map(x=>({...x,projects:[...c.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=[...d.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 cn(t){let e=ln();if(!e)return null;try{return Pi(e.db,ji(),t)}finally{e.close()}}function $i(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let d of p.clients){let m=e.get(d.id);if(!m)e.set(d.id,{...d,projects:[...d.projects]});else{let g=Array.from(new Set([...m.projects,...d.projects])).sort();e.set(d.id,{...m,projects:g})}}for(let d of p.agents)a.has(d.id)||a.set(d.id,d);for(let d of p.channels)n.has(d.id)||n.set(d.id,d);for(let d of p.initiators)r.has(d.id)||r.set(d.id,d);for(let d of p.dispatches){let m=zm(d);if(m.clientId!==d.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Mi(m.clientId),projects:[]}),m.projectId!==d.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:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function zm(t){if(t.clientId!=="unmapped")return t;let e=tn(t.inputPreview);if(!e)return t;let a=we?.business?.projects??[];return{...t,projectId:e,clientId:St(e,a)}}async function oa(t){let e=we?.channels?.gitlab,a=await wi(yi(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 ji(){return we&&{...we,people:ot(we.people)}}function Oi(t){we=t}async function Ni(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=ln();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=Di(parseInt(r.searchParams.get("hours")||"6",10));ye(e,200,await oa(Pi(n.db,ji(),o)))}catch(r){ye(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Fm=5e3;async function dn(t,e,a,n=cn){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
9180
9193
 
9181
- `);let r=new URL(t.url||"/","http://_"),o=$i(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
9194
+ `);let r=new URL(t.url||"/","http://_"),o=Di(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
9182
9195
 
9183
9196
  `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),d=p&&await oa(p);if(s)break;d?(e.write(`event: snapshot
9184
9197
  `),e.write(`data: ${JSON.stringify(d)}
@@ -9189,7 +9202,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
9189
9202
  `)}catch(p){e.write(`event: error
9190
9203
  data: ${JSON.stringify({error:p?.message??String(p)})}
9191
9204
 
9192
- `)}let c=Date.now();for(;!s&&Date.now()-c<Hm;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function $i(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=on(process.cwd(),".agentx/task-history",t,n);if(!sn(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=on(process.cwd(),".agentx/task-history",t,o);return sn(s)?Ei(s,e,a):null}return Ei(r,e,a)}function Ei(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(Mm(Cm(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function ji(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=ln();if(!l)return ye(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return 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 d=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let g=Ci(c.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=Bm(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=Ia(we?.business??{}),f={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Ai(c.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(c.project||na(m,c.subject,g)){let y=c.project||na(m,c.subject,g);f={client:St(y,T),project:y,via:c.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(p.agent_id){let y=u.get(p.agent_id);y&&(f={client:y,project:`${y}/_${c.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:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:d?.resolved_at??null,durationMs:d?.duration_ms??null,input:k,response:b,transcriptLen:S,resolutionStatus:d?.status??null,resultSummary:d?.result_summary??null,attribution:f})}catch(c){ye(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Um,readFileSync as Wm}from"fs";import{resolve as Ni}from"path";yt();function Oi(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=qm.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:zm,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>${Fm}</script>`})}var qm=`
9205
+ `)}let c=Date.now();for(;!s&&Date.now()-c<Fm;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Di(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Um(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=on(process.cwd(),".agentx/task-history",t,n);if(!sn(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=on(process.cwd(),".agentx/task-history",t,o);return sn(s)?Ii(s,e,a):null}return Ii(r,e,a)}function Ii(t,e,a){let n=null,r=1/0;for(let o of Pm(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse($m(Lm(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function Hi(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=ln();if(!l)return ye(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return 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 d=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let g=Li(c.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=Um(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=Ia(we?.business??{}),f={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Ri(c.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(c.project||na(m,c.subject,g)){let y=c.project||na(m,c.subject,g);f={client:St(y,T),project:y,via:c.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(p.agent_id){let y=u.get(p.agent_id);y&&(f={client:y,project:`${y}/_${c.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:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:d?.resolved_at??null,durationMs:d?.duration_ms??null,input:k,response:b,transcriptLen:S,resolutionStatus:d?.status??null,resultSummary:d?.result_summary??null,attribution:f})}catch(c){ye(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Km,readFileSync as Jm}from"fs";import{resolve as qi}from"path";yt();function Bi(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=Wm.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:Gm,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>${Xm}</script>`})}var Wm=`
9193
9206
  <!-- Breadcrumb -->
9194
9207
  <div class="ax-crumb">
9195
9208
  <a href="/admin">Settings</a>
@@ -9787,7 +9800,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
9787
9800
  </div>
9788
9801
  </div>
9789
9802
  </div>
9790
- `,zm=`
9803
+ `,Gm=`
9791
9804
  /* Agent-specific layout + legacy styles for bits the migration left in
9792
9805
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
9793
9806
  * primitives live in components.css.ts. */
@@ -9906,7 +9919,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
9906
9919
 
9907
9920
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
9908
9921
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
9909
- `,Fm=`
9922
+ `,Xm=`
9910
9923
  const $ = (id) => document.getElementById(id);
9911
9924
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
9912
9925
 
@@ -10765,15 +10778,15 @@ document.addEventListener('keydown', (e) => {
10765
10778
  /* ===== Boot ===== */
10766
10779
  initOptsToggles();
10767
10780
  loadAgent();
10768
- `;function Di(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oi({agentId:a,peers:n,localToken:r}))}async function Hi(t,e,a){try{let n=t.method==="GET"?void 0:await ff(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]||"",c=`${t.method} ${l}`,d={"GET ":()=>it(i),"PATCH ":()=>Gm(i,n),"PATCH capability":()=>Jm(i,n),"POST mcp":()=>Xm(i,n),"DELETE mcp":()=>Km(i,n),"GET identity":()=>Vm(i),"GET identity/file":()=>Ym(i,String(o.path||"")),"PUT identity/file":()=>Qm(i,n),"GET skills":()=>Zm(i),"POST skills":()=>ef(i,n),"DELETE skills":()=>tf(i,n),"GET skills/tree":()=>af(i,String(o.slug||"")),"GET skills/file":()=>nf(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>rf(i,n),"GET skills/deps":()=>of(i,String(o.slug||"")),"POST skills/install":()=>sf(i,n,t),"POST skills/deps":()=>lf(i,n,t),"GET channels":()=>cf(i),"GET activity":()=>df(i,t),"GET handovers":()=>pf(i),"POST handovers":()=>uf(i,n),"DELETE handovers":()=>mf(n)}[c];if(!d){sa(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await d();sa(e,200,m)}catch(n){sa(e,400,{error:n?.message||"agent op failed"})}}function Bi(){let t=Ni(process.cwd(),"agentx.json");return Um(t)?JSON.parse(Wm(t,"utf-8")):null}function V(t){let e=Bi();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 it(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 Gm(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"&&(Bt(r.agents[t],e.wikiAbsorb),a.wikiAbsorb=e.wikiAbsorb),`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:it(t)}}function Xm(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:it(t)}}function Km(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:it(t)}}function Jm(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:it(t)}}function Vm(t){let{def:e}=V(t);return Fe(e.workspace)}function Ym(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Lt(a.workspace,e)}function Qm(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return Pt(n.workspace,a,String(e?.content??""))}function Zm(t){let{def:e}=V(t),a=Fe(e.workspace);return{skills:a.skills,workspace:a.workspace}}function ef(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,{title:e?.title,content:e?.content})}function tf(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return jt(n.workspace,a)}function af(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Wr(a.workspace,e),r=Ot(a.workspace,e);return{slug:e,tree:n,deps:r}}function nf(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Gr(n.workspace,e,a)}function rf(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 Xr(r.workspace,a,n,String(e?.content??""))}function of(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Ot(a.workspace,e)}async function sf(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=qi(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(`
10769
- `);return zi(a,r,s,`install-${n}:${Date.now()}`)}async function lf(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=qi(e?.worker),{def:o}=V(t),s=Ot(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=Ni(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(`
10770
- `);return zi(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function qi(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 zi(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}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function cf(t){let e=Bi(),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 df(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 pn(){return new Zn}function pf(t){let e=pn(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function uf(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,c=pn().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function mf(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:pn().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 ff(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 Fi=[{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 un(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(je)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10781
+ `;function zi(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bi({agentId:a,peers:n,localToken:r}))}async function Fi(t,e,a){try{let n=t.method==="GET"?void 0:await bf(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]||"",c=`${t.method} ${l}`,d={"GET ":()=>it(i),"PATCH ":()=>Vm(i,n),"PATCH capability":()=>Zm(i,n),"POST mcp":()=>Ym(i,n),"DELETE mcp":()=>Qm(i,n),"GET identity":()=>ef(i),"GET identity/file":()=>tf(i,String(o.path||"")),"PUT identity/file":()=>af(i,n),"GET skills":()=>nf(i),"POST skills":()=>rf(i,n),"DELETE skills":()=>of(i,n),"GET skills/tree":()=>sf(i,String(o.slug||"")),"GET skills/file":()=>lf(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>cf(i,n),"GET skills/deps":()=>df(i,String(o.slug||"")),"POST skills/install":()=>pf(i,n,t),"POST skills/deps":()=>uf(i,n,t),"GET channels":()=>mf(i),"GET activity":()=>ff(i,t),"GET handovers":()=>hf(i),"POST handovers":()=>gf(i,n),"DELETE handovers":()=>xf(n)}[c];if(!d){sa(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await d();sa(e,200,m)}catch(n){sa(e,400,{error:n?.message||"agent op failed"})}}function Ui(){let t=qi(process.cwd(),"agentx.json");return Km(t)?JSON.parse(Jm(t,"utf-8")):null}function V(t){let e=Ui();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 it(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 Vm(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"&&(Bt(r.agents[t],e.wikiAbsorb),a.wikiAbsorb=e.wikiAbsorb),`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:it(t)}}function Ym(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:it(t)}}function Qm(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:it(t)}}function Zm(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:it(t)}}function ef(t){let{def:e}=V(t);return Fe(e.workspace)}function tf(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Lt(a.workspace,e)}function af(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return Pt(n.workspace,a,String(e?.content??""))}function nf(t){let{def:e}=V(t),a=Fe(e.workspace);return{skills:a.skills,workspace:a.workspace}}function rf(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,{title:e?.title,content:e?.content})}function of(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return jt(n.workspace,a)}function sf(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Kr(a.workspace,e),r=Ot(a.workspace,e);return{slug:e,tree:n,deps:r}}function lf(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Jr(n.workspace,e,a)}function cf(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 Vr(r.workspace,a,n,String(e?.content??""))}function df(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Ot(a.workspace,e)}async function pf(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=Wi(e?.worker),{def:o}=V(t),s=lo(o.tier),i=s?.addSkillCommand(n,o.workspace);if(!s||!i)throw new Error(`agent "${t}" runs on ${o.tier}, which does not use skills`);let l=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: ${i}`,`Skills should land under ${s.skillDirs(o.workspace)[0]}/. Report what was installed and any errors.`].join(`
10782
+ `);return Gi(a,r,l,`install-${n}:${Date.now()}`)}async function uf(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Wi(e?.worker),{def:o}=V(t),s=Ot(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=qi(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(`
10783
+ `);return Gi(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Wi(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 Gi(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}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function mf(t){let e=Ui(),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 ff(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 pn(){return new ar}function hf(t){let e=pn(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function gf(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,c=pn().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function xf(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:pn().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 bf(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 Xi=[{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 un(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(je)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10771
10784
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
10772
10785
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
10773
10786
  <section id="statstrip" class="ax-statstrip"></section>
10774
10787
  <main id="grid" class="ax-live__body"></main>
10775
10788
  </div>
10776
- `;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:hf,scripts:e+`<script>${gf}</script>`,headExtras:`<script>
10789
+ `;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:vf,scripts:e+`<script>${yf}</script>`,headExtras:`<script>
10777
10790
  // rightExtras for the topbar are injected at runtime \u2014 they reference
10778
10791
  // IDs (#ts, #conn-dot) that the script below addresses directly.
10779
10792
  document.addEventListener('DOMContentLoaded', () => {
@@ -10784,7 +10797,7 @@ loadAgent();
10784
10797
  extras.innerHTML = ${JSON.stringify(a)};
10785
10798
  right.insertBefore(extras, right.firstChild);
10786
10799
  });
10787
- </script>`})}var hf=`
10800
+ </script>`})}var vf=`
10788
10801
  /* --- Page frame --- */
10789
10802
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
10790
10803
 
@@ -11005,7 +11018,7 @@ loadAgent();
11005
11018
  border-top-color: var(--ax-accent); border-radius: 50%;
11006
11019
  animation: ax-spin 800ms linear infinite; display: inline-block;
11007
11020
  }
11008
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,gf=`
11021
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,yf=`
11009
11022
  'use strict';
11010
11023
 
11011
11024
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -11652,7 +11665,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11652
11665
  });
11653
11666
  }
11654
11667
 
11655
- `;var Ui=`
11668
+ `;var Ki=`
11656
11669
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
11657
11670
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
11658
11671
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -11826,7 +11839,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11826
11839
  .mx-summary{max-width:56vw}
11827
11840
  }
11828
11841
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
11829
- `;var Wi=`<script>
11842
+ `;var Ji=`<script>
11830
11843
  window.MX=(function(){
11831
11844
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
11832
11845
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -11935,7 +11948,7 @@ window.MX=(function(){
11935
11948
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
11936
11949
  setHealth:setHealth,get:get};
11937
11950
  })();
11938
- </script>`;var Gi=`<script>
11951
+ </script>`;var Vi=`<script>
11939
11952
  window.MXD=(function(){
11940
11953
  function el(id){return document.getElementById(id)}
11941
11954
  function tz(){return -new Date().getTimezoneOffset()}
@@ -12149,7 +12162,7 @@ window.MXD=(function(){
12149
12162
 
12150
12163
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
12151
12164
  })();
12152
- </script>`;var Xi=`<script>
12165
+ </script>`;var Yi=`<script>
12153
12166
  (function(){
12154
12167
  var LANES=[
12155
12168
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -12465,7 +12478,7 @@ window.MXD=(function(){
12465
12478
  window.addEventListener('scroll',hideTip,{passive:true});
12466
12479
  load();
12467
12480
  })();
12468
- </script>`;var Ki=`<script>
12481
+ </script>`;var Qi=`<script>
12469
12482
  (function(){
12470
12483
  var showAll=document.getElementById('mx-show-all'),expanded=false;
12471
12484
  var esc=MX.esc;
@@ -12643,7 +12656,7 @@ window.MXD=(function(){
12643
12656
  }
12644
12657
  load();setInterval(load,5000);
12645
12658
  })();
12646
- </script>`;var Ji=`
12659
+ </script>`;var Zi=`
12647
12660
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
12648
12661
  .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}
12649
12662
  .mx-rt-wrap > .mx-empty{border:0}
@@ -12684,7 +12697,7 @@ window.MXD=(function(){
12684
12697
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
12685
12698
  .mx-rt-name{max-width:100%}
12686
12699
  }
12687
- `,Vi=`<script>
12700
+ `,el=`<script>
12688
12701
  (function(){
12689
12702
  var root=document.getElementById('mx-routines');
12690
12703
  var bar=document.getElementById('mx-rt-filter');
@@ -12811,7 +12824,7 @@ window.MXD=(function(){
12811
12824
  syncBar();
12812
12825
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
12813
12826
  })();
12814
- </script>`;var Yi=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Qi=`<script>
12827
+ </script>`;var tl=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],al=`<script>
12815
12828
  (function(){
12816
12829
  var root=document.getElementById('mx-feed');
12817
12830
  if(!root)return;
@@ -12886,12 +12899,12 @@ window.MXD=(function(){
12886
12899
  }
12887
12900
  load();setInterval(load,5000);
12888
12901
  })();
12889
- </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 xf=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],bf=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],vf=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Zi(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."})+Nt([{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">
12902
+ </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 wf=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],kf=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],_f=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function nl(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."})+Nt([{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">
12890
12903
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
12891
- ${bf.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("")}
12904
+ ${kf.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("")}
12892
12905
  </div>
12893
12906
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
12894
- ${vf.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12907
+ ${_f.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12895
12908
  </div>
12896
12909
  </div>
12897
12910
  <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">
@@ -12944,7 +12957,7 @@ window.MXD=(function(){
12944
12957
  <section class="mx-section" aria-labelledby="mx-routines-title">
12945
12958
  ${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>')}
12946
12959
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
12947
- ${xf.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12960
+ ${wf.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12948
12961
  </div>
12949
12962
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
12950
12963
  </section>
@@ -12952,7 +12965,7 @@ window.MXD=(function(){
12952
12965
  <section class="mx-section" aria-labelledby="mx-feed-title">
12953
12966
  ${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>')}
12954
12967
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
12955
- ${Yi.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12968
+ ${tl.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12956
12969
  </div>
12957
12970
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
12958
12971
  </section>
@@ -12985,7 +12998,7 @@ window.MXD=(function(){
12985
12998
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
12986
12999
  </header>
12987
13000
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
12988
- </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ui+Ji,scripts:Wi+yf+Gi+Xi+Vi+Ki+Qi})}var yf=`<script>
13001
+ </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ki+Zi,scripts:Ji+Sf+Vi+Yi+el+Qi+al})}var Sf=`<script>
12989
13002
  (function(){
12990
13003
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
12991
13004
  var range=document.getElementById('mx-range');
@@ -13013,10 +13026,10 @@ window.MXD=(function(){
13013
13026
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
13014
13027
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
13015
13028
  })();
13016
- </script>`;function el(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."})+`
13029
+ </script>`;function rl(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."})+`
13017
13030
  <div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
13018
13031
  <ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
13019
- <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:wf,scripts:`<script>${kf}</script>`})}var wf=`
13032
+ <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:Ef,scripts:`<script>${Tf}</script>`})}var Ef=`
13020
13033
  .gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
13021
13034
  .gm-empty { color: var(--ax-text-2); }
13022
13035
  .gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
@@ -13034,7 +13047,7 @@ window.MXD=(function(){
13034
13047
  .gm-msg { min-height: 1.4em; margin: 8px 0 0; }
13035
13048
  .gm-msg.is-bad { color: var(--ax-red-ink); }
13036
13049
  .gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
13037
- `,kf=`
13050
+ `,Tf=`
13038
13051
  (function () {
13039
13052
  var list = document.getElementById('gm-list');
13040
13053
  var msg = document.getElementById('gm-msg');
@@ -13081,7 +13094,7 @@ window.MXD=(function(){
13081
13094
  load();
13082
13095
  setInterval(load, 30000);
13083
13096
  })();
13084
- `;async function tl(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return _f(s,e.days)}function _f(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,d=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);c+=T.rotations.total,p+=T.rotations.tokenSum||0,d+=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:c,byReason:[...s.entries()].map(([S,T])=>({reason:S,count:T})).sort((S,T)=>T.count-S.count),tokenSum:p,tokenSamples:d,maxTokens:m},retention:{traces:g,tracesWithSteps:k}}}async function al(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 nl(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Sf(s,e.day)}function Sf(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function rl(t={}){let e=`
13097
+ `;async function ol(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Af(s,e.days)}function Af(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,d=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);c+=T.rotations.total,p+=T.rotations.tokenSum||0,d+=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:c,byReason:[...s.entries()].map(([S,T])=>({reason:S,count:T})).sort((S,T)=>T.count-S.count),tokenSum:p,tokenSamples:d,maxTokens:m},retention:{traces:g,tracesWithSteps:k}}}async function sl(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 il(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Cf(s,e.day)}function Cf(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function ll(t={}){let e=`
13085
13098
  <select id="boardPicker" title="Switch board"></select>
13086
13099
  <div class="search">
13087
13100
  <span class="icon">\u2315</span>
@@ -13182,7 +13195,7 @@ window.MXD=(function(){
13182
13195
  </footer>
13183
13196
  </div>
13184
13197
  </div>
13185
- <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:Ef,scripts:`<script>${Tf}</script>`,headExtras:`<script>
13198
+ <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:If,scripts:`<script>${Mf}</script>`,headExtras:`<script>
13186
13199
  // The boards page has its own connection dot + wants body height:100%
13187
13200
  // for the full-viewport kanban layout. Inject the dot into the topbar
13188
13201
  // and override body height at runtime so the shared shell doesn't
@@ -13198,7 +13211,7 @@ window.MXD=(function(){
13198
13211
  right.insertBefore(dot, right.firstChild);
13199
13212
  }
13200
13213
  });
13201
- </script>`})}var Ef=`
13214
+ </script>`})}var If=`
13202
13215
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
13203
13216
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
13204
13217
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -13451,7 +13464,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
13451
13464
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
13452
13465
  .draft-box .draft-row .hint.err { color: var(--red); }
13453
13466
  .draft-box .draft-row .hint.ok { color: var(--green); }
13454
- `,Tf=`
13467
+ `,Mf=`
13455
13468
  'use strict';
13456
13469
  const state = {
13457
13470
  boards: [], current: null, items: {},
@@ -14504,9 +14517,9 @@ function appendEvents(events) {
14504
14517
  }
14505
14518
 
14506
14519
  loadBoards().catch(e => toast('Init failed: ' + e.message));
14507
- `;function ol(t={}){let a=`<h1>Plain-English glossary</h1>
14520
+ `;function cl(t={}){let a=`<h1>Plain-English glossary</h1>
14508
14521
  <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>
14509
- ${Fi.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:Af})}var Af=`
14522
+ ${Xi.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:Rf})}var Rf=`
14510
14523
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
14511
14524
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
14512
14525
  .lead {
@@ -14536,7 +14549,7 @@ article.term .alias {
14536
14549
  }
14537
14550
  article.term p {
14538
14551
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
14539
- }`;function sl(t={}){let e=`<div class="ax-wf__root">
14552
+ }`;function dl(t={}){let e=`<div class="ax-wf__root">
14540
14553
  <aside class="ax-wf__list">
14541
14554
  <header>
14542
14555
  <h2>Workflows</h2>
@@ -14634,7 +14647,7 @@ article.term p {
14634
14647
  </aside>
14635
14648
  </div>
14636
14649
 
14637
- <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:Cf,scripts:`<script>${z({workflowHealth:dr})}${If}</script>`})}var Cf=`
14650
+ <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:Lf,scripts:`<script>${z({workflowHealth:mr})}${Pf}</script>`})}var Lf=`
14638
14651
  .ax-wf__root {
14639
14652
  display: grid;
14640
14653
  grid-template-columns: 340px 1fr;
@@ -15052,7 +15065,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15052
15065
  font-size: 12px; z-index: 50;
15053
15066
  }
15054
15067
  .hint { color: var(--ax-muted); font-size: 11px; }
15055
- `,If=`
15068
+ `,Pf=`
15056
15069
  (() => {
15057
15070
  const $ = (sel) => document.querySelector(sel)
15058
15071
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -15938,7 +15951,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15938
15951
  setInterval(refresh, 15000)
15939
15952
  })
15940
15953
  })();
15941
- `;function il(t={}){let e=`<div class="ax-proc__root">
15954
+ `;function pl(t={}){let e=`<div class="ax-proc__root">
15942
15955
  <header class="ax-proc__header">
15943
15956
  <h1>Procedures</h1>
15944
15957
  <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>
@@ -15982,7 +15995,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15982
15995
  <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>
15983
15996
  <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>
15984
15997
  </section>
15985
- </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Mf,scripts:`<script>${Rf}</script>`})}var Mf=`
15998
+ </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:$f,scripts:`<script>${jf}</script>`})}var $f=`
15986
15999
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
15987
16000
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
15988
16001
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -16008,7 +16021,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16008
16021
  .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); }
16009
16022
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
16010
16023
  .ax-proc__link:hover { text-decoration: underline; }
16011
- `,Rf=`
16024
+ `,jf=`
16012
16025
  (function(){
16013
16026
  function $(sel){ return document.querySelector(sel) }
16014
16027
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -16108,7 +16121,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16108
16121
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
16109
16122
  else bootAll()
16110
16123
  })();
16111
- `;function ll(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
16124
+ `;function ul(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
16112
16125
  data-task-id="${H(t.taskId)}"
16113
16126
  data-agent-id="${H(t.agentId)}"
16114
16127
  data-node-url="${H(t.nodeUrl)}"
@@ -16151,7 +16164,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16151
16164
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
16152
16165
  </div>
16153
16166
  </footer>
16154
- </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Lf,scripts:`<script>${Pf}</script>`})}var Lf=`
16167
+ </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Of,scripts:`<script>${Nf}</script>`})}var Of=`
16155
16168
  /* The shell gives <main> no padding, so page content butted straight against
16156
16169
  the sticky topbar. Breathe. */
16157
16170
  .ax-task-page {
@@ -16293,7 +16306,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16293
16306
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
16294
16307
  }
16295
16308
 
16296
- `,Pf=`
16309
+ `,Nf=`
16297
16310
  (function () {
16298
16311
  var root = document.querySelector('.ax-task-page');
16299
16312
  if (!root) return;
@@ -16678,7 +16691,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16678
16691
  });
16679
16692
 
16680
16693
  })();
16681
- `;function cl(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16694
+ `;function ml(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16682
16695
  data-agent-id="${H(t.agentId)}"
16683
16696
  data-agent-name="${H(e)}"
16684
16697
  data-node-url="${H(t.nodeUrl)}">
@@ -16707,7 +16720,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16707
16720
  <div class="ax-history__list" id="hist-list">
16708
16721
  <div class="ax-history__empty">loading\u2026</div>
16709
16722
  </div>
16710
- </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:$f,scripts:`<script>${jf}</script>`})}var $f=`
16723
+ </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Df,scripts:`<script>${Hf}</script>`})}var Df=`
16711
16724
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
16712
16725
  flush against the sticky topbar. */
16713
16726
  .ax-history {
@@ -16759,7 +16772,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16759
16772
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
16760
16773
  }
16761
16774
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
16762
- `,jf=`
16775
+ `,Hf=`
16763
16776
  (function () {
16764
16777
  var root = document.querySelector('.ax-history');
16765
16778
  if (!root) return;
@@ -16859,11 +16872,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16859
16872
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
16860
16873
  });
16861
16874
  })();
16862
- `;function pl(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=>dl(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Nf(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,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:c})}):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 c=a.layouts.save(s,l);return P(e,200,{layout:c})}catch(c){return P(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ve(t,e,l=>{let c=Aa.safeParse(l);if(!c.success)return P(e,200,{ok:!1,issues:c.error.issues.map(d=>({path:d.path.join("."),message:d.message}))});let p=Ca(c.data).map(d=>({path:"",message:d}));return P(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?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,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ve(t,e,p=>dl(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var Of=["mesh"];function dl(t,e,a,n){let r=Aa.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=Ca(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,c=e.store.get(n.id);if(c)for(let p of Of)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,d=!!p||/yaml round-trip failed/.test(c);return P(t,d?409:500,{error:d?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:d?"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 Nf(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",d=a.runs.list({workflowId:c,limit:l});if(!p)return P(e,200,{runs:d});let m=d.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,c=>{let p=c?.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 Df(t,e,a,l);let c=a.runs.get(l);return c?P(e,200,{run:c}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function Df(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)}
16875
+ `;function hl(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 Ye(t,e,l=>fl(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:qf(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?Ye(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:c})}):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"])?Ye(t,e,l=>{try{let c=a.layouts.save(s,l);return P(e,200,{layout:c})}catch(c){return P(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ye(t,e,l=>{let c=Aa.safeParse(l);if(!c.success)return P(e,200,{ok:!1,issues:c.error.issues.map(d=>({path:d.path.join("."),message:d.message}))});let p=Ca(c.data).map(d=>({path:"",message:d}));return P(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?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,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ye(t,e,p=>fl(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var Bf=["mesh"];function fl(t,e,a,n){let r=Aa.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=Ca(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,c=e.store.get(n.id);if(c)for(let p of Bf)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,d=!!p||/yaml round-trip failed/.test(c);return P(t,d?409:500,{error:d?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:d?"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 qf(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",d=a.runs.list({workflowId:c,limit:l});if(!p)return P(e,200,{runs:d});let m=d.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 Ye(t,e,c=>{let p=c?.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 zf(t,e,a,l);let c=a.runs.get(l);return c?P(e,200,{run:c}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function zf(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)}
16863
16876
 
16864
16877
  `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=d=>{if(!o)try{e.write(`data: ${JSON.stringify(d)}
16865
16878
 
16866
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let d=a.runs.get(n);d&&d.updatedAt!==c&&(c=d.updatedAt,i(d))},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 Mh}from"fs";import{createRequire as Rh}from"module";var ul=4e3;async function ml(t,e,a,n,r){if(n==="GET"&&a==="/api/app/desk")return lt(e,200,await r.board());if(n!=="POST"||a!=="/api/app/desk/reply")return!1;let o;try{o=await qe(t)}catch(c){return lt(e,400,{error:c.message})}let s=typeof o.id=="string"?o.id.trim():"",i=typeof o.text=="string"?o.text.trim():"";if(!s||!i)return lt(e,400,{error:"id and text are required"});if(i.length>ul)return lt(e,400,{error:`the answer is longer than ${ul} characters`});let l=await r.reply(s,i);return lt(e,l.status,l.body)}function lt(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Gn();var hl=50,Hf=280;async function gl(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(hl))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return fl(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return fl(e,404,{error:"not found"})}function xl(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 Tt();let r=bt();return r?new gr(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:mn(typeof n.summary=="string"?n.summary:"",Hf),by:typeof n.agentId=="string"?mn(n.agentId,100):null,node:mn(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,hl)}function mn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function fl(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var qf="operator",zf=50,bl=4,vl=500;function Ff(t){let e={channel:"app",chatId:t.chatId,sender:qf,...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 yl(t,e,a,n){let{path:r,body:o}=Ff(e),s="",i=!1,l=[],c=new Map,p=(d,m,g)=>{let k=d!=="done",b=i?{text:_t(m,k),artifacts:[]}:kt(m,pe.perMessage,k),{cleanText:S,ui:T}=d==="done"?Et(b.text):{cleanText:b.text,ui:void 0},h=i?void 0:fn(T);return{status:d,text:S,tools:l,files:b.artifacts,...h?{ui:h}:{},...g?{error:g}:{}}};try{let d=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(!d.ok||!d.body){let m=await d.json().then(g=>g?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${d.status}.`)}for await(let m of Wf(d.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<zf){let k={name:String(g.name||"tool").slice(0,80),...g.arg?{arg:String(g.arg).slice(0,80)}:{}};l.push(k),g.id&&c.set(String(g.id),k)}else if(m.event==="tool"&&g.status==="result"&&g.error===!0&&c.has(String(g.id)))c.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,Uf(g.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(d){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${d?.message||d}`)}}function Uf(t){let e=String(t||"The agent could not answer.");return er(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function fn(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,bl).map(s=>s.slice(0,vl));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,bl).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,vl)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Wf(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,`
16879
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let d=a.runs.get(n);d&&d.updatedAt!==c&&(c=d.updatedAt,i(d))},2e3);return!0}function Ye(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 $h}from"fs";import{createRequire as jh}from"module";var gl=4e3;async function xl(t,e,a,n,r){if(n==="GET"&&a==="/api/app/desk")return lt(e,200,await r.board());if(n!=="POST"||a!=="/api/app/desk/reply")return!1;let o;try{o=await qe(t)}catch(c){return lt(e,400,{error:c.message})}let s=typeof o.id=="string"?o.id.trim():"",i=typeof o.text=="string"?o.text.trim():"";if(!s||!i)return lt(e,400,{error:"id and text are required"});if(i.length>gl)return lt(e,400,{error:`the answer is longer than ${gl} characters`});let l=await r.reply(s,i);return lt(e,l.status,l.body)}function lt(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Gn();var vl=50,Ff=280;async function yl(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=Uf(await o.recent(vl))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return bl(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return bl(e,404,{error:"not found"})}function wl(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 Tt();let r=bt();return r?new vr(r):null}}}function Uf(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:mn(typeof n.summary=="string"?n.summary:"",Ff),by:typeof n.agentId=="string"?mn(n.agentId,100):null,node:mn(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,vl)}function mn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function bl(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Wf="operator",Gf=50,kl=4,_l=500;function Xf(t){let e={channel:"app",chatId:t.chatId,sender:Wf,...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 Sl(t,e,a,n){let{path:r,body:o}=Xf(e),s="",i=!1,l=[],c=new Map,p=(d,m,g)=>{let k=d!=="done",b=i?{text:_t(m,k),artifacts:[]}:kt(m,pe.perMessage,k),{cleanText:S,ui:T}=d==="done"?Et(b.text):{cleanText:b.text,ui:void 0},h=i?void 0:fn(T);return{status:d,text:S,tools:l,files:b.artifacts,...h?{ui:h}:{},...g?{error:g}:{}}};try{let d=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(!d.ok||!d.body){let m=await d.json().then(g=>g?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${d.status}.`)}for await(let m of Jf(d.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<Gf){let k={name:String(g.name||"tool").slice(0,80),...g.arg?{arg:String(g.arg).slice(0,80)}:{}};l.push(k),g.id&&c.set(String(g.id),k)}else if(m.event==="tool"&&g.status==="result"&&g.error===!0&&c.has(String(g.id)))c.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,Kf(g.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(d){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${d?.message||d}`)}}function Kf(t){let e=String(t||"The agent could not answer.");return nr(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function fn(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,kl).map(s=>s.slice(0,_l));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,kl).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,_l)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Jf(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,`
16867
16880
  `);let s;for(;(s=n.indexOf(`
16868
16881
 
16869
16882
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
@@ -16873,17 +16886,17 @@ data: ${JSON.stringify(s)}
16873
16886
 
16874
16887
  `)},r=setInterval(()=>{a()&&e.write(`: ping
16875
16888
 
16876
- `)},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 kl(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=Gf(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:hn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function hn(t,e=120){for(let a of t.split(`
16877
- `)){let n=_l(a);if(n)return gn(n,e)}return""}function Gf(t,e=120){let a=t.split(`
16878
- `).map(_l).filter(Boolean);return a.length?gn(a[a.length-1],e):""}function _l(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function gn(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 ca(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var wl=140;function da(t,e,a,n,r){let o=a==="error"?`Could not answer: ${hn(r||"",wl-18)||"something went wrong."}`:hn(n,wl)||"Answered.";return{deviceId:t,title:gn(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var El=8e3,Kf=/^[A-Za-z0-9_.:-]{1,64}$/,Oe=new Map,xn=new Map,yn=new la;function Tl(){return yn}async function Al(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??yn;if(n==="GET"&&a==="/api/app/agents")return B(e,200,{nodes:await Cl(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:kl(r.id,Yf(),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 d=Oe.get(p.id);return B(e,200,{...p,running:!!d,...d?{partial:{text:d.text,tools:d.tools,...d.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")||""),d=p&&Oe.get(p.id);if(!p||!d)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Il(e);let{id:m,title:g,node:k,nodeName:b,agent:S,agentName:T}=p;return e.write(bn("conversation",{id:m,title:g,node:k,nodeName:b,agent:S,agentName:T})),e.write(bn("resume",{text:d.text,tools:d.tools,...d.plain?{plain:!0}:{}})),d.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return B(e,404,{error:"not found"});let c;try{c=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(c.conversationId??""));if(!p)return B(e,404,{error:"no such conversation"});let d=Oe.get(p.id);return d?(d.ac.abort(),vn(p,o,r.name),B(e,200,{stopped:!0})):await vn(p,o,r.name)?B(e,200,{stopped:!0}):B(e,404,{error:"nothing is running in this conversation"})}return await Vf(e,c,r,i,o),!0}function Jf(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(d=>Ye(d.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(d=>{let m=Array.isArray(d.runningTasks)?d.runningTasks.length:0;return{id:d.id,name:d.name||d.id,busy:m>0||(d.active??0)>0,running:m,...d.color?{color:d.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 Cl(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Jf(e.nodes,t.daemon,a)}async function Vf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>El){B(t,400,{error:`message must be 1\u2013${El} 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(!Kf.test(b)){B(t,400,{error:"pick an agent"});return}let S=(await Cl(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:c,node:p,nodeName:d,agent:m,agentName:g}=s;xn.set(l,{id:l,deviceId:a.id,title:c,agent:m,...g?{agentName:g}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Il(t),t.write(bn("conversation",{id:l,title:c,node:p,nodeName:d,agent:m,agentName:g})),i.attach(t);try{let k=e.spoken===!0,b=await yl(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.`,vn(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??yn).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&ca(h)&&r.notifyFinish(da(a.id,s,b.status,b.text,b.error)).catch(()=>{})}finally{Oe.delete(l),xn.delete(l),i.finish()}}function Yf(){let t=[];for(let[e,a]of xn){let n=Oe.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Il(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function bn(t,e){return`event: ${t}
16889
+ `)},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 Tl(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=Vf(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:hn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function hn(t,e=120){for(let a of t.split(`
16890
+ `)){let n=Al(a);if(n)return gn(n,e)}return""}function Vf(t,e=120){let a=t.split(`
16891
+ `).map(Al).filter(Boolean);return a.length?gn(a[a.length-1],e):""}function Al(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function gn(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 ca(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var El=140;function da(t,e,a,n,r){let o=a==="error"?`Could not answer: ${hn(r||"",El-18)||"something went wrong."}`:hn(n,El)||"Answered.";return{deviceId:t,title:gn(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var Il=8e3,Qf=/^[A-Za-z0-9_.:-]{1,64}$/,Oe=new Map,xn=new Map,yn=new la;function Ml(){return yn}async function Rl(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??yn;if(n==="GET"&&a==="/api/app/agents")return B(e,200,{nodes:await Ll(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:Tl(r.id,th(),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 d=Oe.get(p.id);return B(e,200,{...p,running:!!d,...d?{partial:{text:d.text,tools:d.tools,...d.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")||""),d=p&&Oe.get(p.id);if(!p||!d)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Pl(e);let{id:m,title:g,node:k,nodeName:b,agent:S,agentName:T}=p;return e.write(bn("conversation",{id:m,title:g,node:k,nodeName:b,agent:S,agentName:T})),e.write(bn("resume",{text:d.text,tools:d.tools,...d.plain?{plain:!0}:{}})),d.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return B(e,404,{error:"not found"});let c;try{c=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(c.conversationId??""));if(!p)return B(e,404,{error:"no such conversation"});let d=Oe.get(p.id);return d?(d.ac.abort(),vn(p,o,r.name),B(e,200,{stopped:!0})):await vn(p,o,r.name)?B(e,200,{stopped:!0}):B(e,404,{error:"nothing is running in this conversation"})}return await eh(e,c,r,i,o),!0}function Zf(t,e,a){let n=Qe(e.url),r=new Set,o=[];for(let s of t){let i=Qe(s.url),l=a.find(d=>Qe(d.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(d=>{let m=Array.isArray(d.runningTasks)?d.runningTasks.length:0;return{id:d.id,name:d.name||d.id,busy:m>0||(d.active??0)>0,running:m,...d.color?{color:d.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 Ll(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Zf(e.nodes,t.daemon,a)}async function eh(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Il){B(t,400,{error:`message must be 1\u2013${Il} 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(!Qf.test(b)){B(t,400,{error:"pick an agent"});return}let S=(await Ll(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:c,node:p,nodeName:d,agent:m,agentName:g}=s;xn.set(l,{id:l,deviceId:a.id,title:c,agent:m,...g?{agentName:g}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Pl(t),t.write(bn("conversation",{id:l,title:c,node:p,nodeName:d,agent:m,agentName:g})),i.attach(t);try{let k=e.spoken===!0,b=await Sl(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.`,vn(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??yn).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&ca(h)&&r.notifyFinish(da(a.id,s,b.status,b.text,b.error)).catch(()=>{})}finally{Oe.delete(l),xn.delete(l),i.finish()}}function th(){let t=[];for(let[e,a]of xn){let n=Oe.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Pl(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function bn(t,e){return`event: ${t}
16879
16892
  data: ${JSON.stringify(e)}
16880
16893
 
16881
- `}async function vn(t,e,a){try{let n=Ye(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.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 Qf}from"stream";var Zf=/^\/api\/app\/files\/([^/]+)$/,eh=15e3;async function Rl(t,e,a,n,r,o){let s=Zf.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 c=i.getFile(r.id,l);if(!c)return Ne(e,404,{error:"no such file"});let p=await th(c.node,o);if(!p)return Ne(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let d=new AbortController;e.on("close",()=>d.abort());let m=setTimeout(()=>d.abort(),eh),g;try{let h=new URLSearchParams({agent:c.agent,file:c.path});g=await fetch(`${p.url}${Lr}?${h}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:d.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 d.abort(),Ne(e,413,{error:"the file is too large"});let b=g.headers.get("content-range");if(e.writeHead(g.status,{...Pr(c.mime,c.name,c.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=Qf.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 th(t,e){if(t==="local")return{url:Ml(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Ml(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Ml(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 Pl=8e3;async function $l(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(!zr(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=qr(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Y(e,k.status,{error:k.error});let b=await Ce(t,Br.bytes);if(!b)return Y(e,413,{error:Fr()});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 Ll(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 c=l.get(r.id,String(s?.conversationId??""));if(!c)return Y(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Pl):"";if(!p.trim())return Y(e,400,{error:"text is required"});if(!nh(c.messages,p))return Y(e,404,{error:"no such answer in this conversation"});let d=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:d,...c.node!=="local"?{peer:c.node}:{}};return Ll(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Ll(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(ah(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 ah(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function nh(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Pl&&a.content.startsWith(e)))}var rh=new Set(["ring","offer","answer","ice","hangup"]),Qe=/^[A-Za-z0-9_-]{4,64}$/,oh=128*1024,sh=24,ih=2*1024*1024,De=new Map;async function Ol(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 c=await l.json(),p=at(r.nodeName),d=(Array.isArray(c.peers)?c.peers:[]).filter(g=>at(String(g?.name??""))!==p),m=(Array.isArray(c.agents)?c.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:c.iceServers??[],peers:d,agents:m,camera:c.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,oh);if(!l)return M(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=ch(c,r.nodeName);if(typeof p=="string")return M(e,400,{error:p});let d=Nl(p.to);if(d&&p.kind==="ring"){let m=await He(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:d});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)?dh(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 c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!Qe.test(p))return M(e,400,{error:"callId is required"});let d=typeof c?.note=="string"?c.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:d},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 jl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Qe.test(c))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 d=typeof l.note=="string"?l.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/stream`,{seconds:p,note:d});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 jl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Qe.test(c))return M(e,400,{error:"callId is required"});let p=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(c)}`);if(p.status>=300)return M(e,p.status,{error:p.body.error});let d=(Array.isArray(p.body.watch?.replies)?p.body.watch.replies:[]).find(b=>b&&b.at===l.at);if(!d||typeof d.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(p.body.watch.agentId??""),g=JSON.stringify([c,d.at,m,d.text]),k=De.get(g);return k?(De.delete(g),De.set(g,k),Dl(e,k.type,k.bytes)):lh(e,o,s,{agent:m,text:d.text},(b,S)=>{if(!(S.length>ih))for(De.set(g,{type:b,bytes:S});De.size>sh;)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 c=(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:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return 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 c=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return M(e,404,{error:"not found"})}function Nl(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 jl(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 lh(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),Dl(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 Dl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function ch(t,e){let a=String(t?.kind??"");if(!rh.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:")&&!Nl(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 dh(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 ph,readFileSync as uh,renameSync as mh,writeFileSync as fh}from"fs";import{dirname as hh,isAbsolute as gh,resolve as xh}from"path";import{randomBytes as bh}from"crypto";var Hl=60,Bl=500,vh=200,Fl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,yh=/^[A-Za-z0-9_-]{8,64}$/,wh=/^[A-Za-z0-9._-]{1,64}$/;function Ul(t,e){return gh(e)?e:xh(t,e)}function ql(t){return`${t}_${bh(6).toString("hex")}`}function zl(){return{places:[],rules:[],seen:[]}}function Wl(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>Hl)return{ok:!1,error:`Keep the name under ${Hl} 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 Gl(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!Fl.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>Bl)return{ok:!1,error:`Keep it under ${Bl} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!wh.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 Xl(t){let e=typeof t.id=="string"?t.id:"";if(!yh.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!Fl.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(uh(this.path,"utf-8"));return!e||typeof e!="object"?zl():{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 zl()}}write(e){ph(hh(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;fh(a,JSON.stringify(e,null,2)+`
16882
- `,{mode:384}),mh(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:ql("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:ql("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(-vh);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(c=>c.placeId===o.id&&c.on===e.transition&&c.enabled&&!(c.lastFiredAt&&Date.parse(c.lastFiredAt)>r-i));for(let c of l)c.lastFiredAt=new Date(r).toISOString(),c.repeat||(c.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(c=>({...c}))}:{status:"no-rules"}}return this.write(n),s}};Kn();function kh(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function _h(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(`
16883
- `)}async function Kl(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=kh(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,_h(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16894
+ `}async function vn(t,e,a){try{let n=Qe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Qe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Qe(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 Qe(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 ah}from"stream";var nh=/^\/api\/app\/files\/([^/]+)$/,rh=15e3;async function jl(t,e,a,n,r,o){let s=nh.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 c=i.getFile(r.id,l);if(!c)return Ne(e,404,{error:"no such file"});let p=await oh(c.node,o);if(!p)return Ne(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let d=new AbortController;e.on("close",()=>d.abort());let m=setTimeout(()=>d.abort(),rh),g;try{let h=new URLSearchParams({agent:c.agent,file:c.path});g=await fetch(`${p.url}${jr}?${h}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:d.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 d.abort(),Ne(e,413,{error:"the file is too large"});let b=g.headers.get("content-range");if(e.writeHead(g.status,{...Or(c.mime,c.name,c.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=ah.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 oh(t,e){if(t==="local")return{url:$l(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=$l(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function $l(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 Nl=8e3;async function Dl(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(!Wr(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Ur(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Y(e,k.status,{error:k.error});let b=await Ce(t,Fr.bytes);if(!b)return Y(e,413,{error:Gr()});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 Ol(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 c=l.get(r.id,String(s?.conversationId??""));if(!c)return Y(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Nl):"";if(!p.trim())return Y(e,400,{error:"text is required"});if(!ih(c.messages,p))return Y(e,404,{error:"no such answer in this conversation"});let d=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:d,...c.node!=="local"?{peer:c.node}:{}};return Ol(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Ol(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(sh(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 sh(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function ih(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Nl&&a.content.startsWith(e)))}var lh=new Set(["ring","offer","answer","ice","hangup"]),Ze=/^[A-Za-z0-9_-]{4,64}$/,ch=128*1024,dh=24,ph=2*1024*1024,De=new Map;async function Bl(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 c=await l.json(),p=nt(r.nodeName),d=(Array.isArray(c.peers)?c.peers:[]).filter(g=>nt(String(g?.name??""))!==p),m=(Array.isArray(c.agents)?c.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:c.iceServers??[],peers:d,agents:m,camera:c.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,ch);if(!l)return M(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=mh(c,r.nodeName);if(typeof p=="string")return M(e,400,{error:p});let d=ql(p.to);if(d&&p.kind==="ring"){let m=await He(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:d});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 Ze.test(l)?fh(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 c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!Ze.test(p))return M(e,400,{error:"callId is required"});let d=typeof c?.note=="string"?c.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:d},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 Hl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ze.test(c))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 d=typeof l.note=="string"?l.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/stream`,{seconds:p,note:d});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 Hl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ze.test(c))return M(e,400,{error:"callId is required"});let p=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(c)}`);if(p.status>=300)return M(e,p.status,{error:p.body.error});let d=(Array.isArray(p.body.watch?.replies)?p.body.watch.replies:[]).find(b=>b&&b.at===l.at);if(!d||typeof d.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(p.body.watch.agentId??""),g=JSON.stringify([c,d.at,m,d.text]),k=De.get(g);return k?(De.delete(g),De.set(g,k),zl(e,k.type,k.bytes)):uh(e,o,s,{agent:m,text:d.text},(b,S)=>{if(!(S.length>ph))for(De.set(g,{type:b,bytes:S});De.size>dh;)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 c=(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:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return 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(!Ze.test(l))return M(e,400,{error:"callId is required"});let c=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return M(e,404,{error:"not found"})}function ql(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 Hl(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 uh(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),zl(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 zl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function mh(t,e){let a=String(t?.kind??"");if(!lh.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Ze.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:")&&!ql(r))return"to must be bot:<agent id> for an agent";if(nt(r)===nt(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 fh(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 hh,readFileSync as gh,renameSync as xh,writeFileSync as bh}from"fs";import{dirname as vh,isAbsolute as yh,resolve as wh}from"path";import{randomBytes as kh}from"crypto";var Fl=60,Ul=500,_h=200,Xl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Sh=/^[A-Za-z0-9_-]{8,64}$/,Eh=/^[A-Za-z0-9._-]{1,64}$/;function Kl(t,e){return yh(e)?e:wh(t,e)}function Wl(t){return`${t}_${kh(6).toString("hex")}`}function Gl(){return{places:[],rules:[],seen:[]}}function Jl(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>Fl)return{ok:!1,error:`Keep the name under ${Fl} 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 Vl(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!Xl.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>Ul)return{ok:!1,error:`Keep it under ${Ul} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Eh.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 Yl(t){let e=typeof t.id=="string"?t.id:"";if(!Sh.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!Xl.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(gh(this.path,"utf-8"));return!e||typeof e!="object"?Gl():{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 Gl()}}write(e){hh(vh(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;bh(a,JSON.stringify(e,null,2)+`
16895
+ `,{mode:384}),xh(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:Wl("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:Wl("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(-_h);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(c=>c.placeId===o.id&&c.on===e.transition&&c.enabled&&!(c.lastFiredAt&&Date.parse(c.lastFiredAt)>r-i));for(let c of l)c.lastFiredAt=new Date(r).toISOString(),c.repeat||(c.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(c=>({...c}))}:{status:"no-rules"}}return this.write(n),s}};Kn();function Th(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function Ah(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(`
16896
+ `)}async function Ql(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=Th(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,Ah(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16884
16897
 
16885
- (${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 Jl(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}
16886
- ${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?{[Xn]: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 Vl(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Ql(t,e,a.slice(15),n,o,r)}async function Yl(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Ql(t,e,a.slice(11),n,r,null)}async function Ql(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=Xl(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?Kl(o.id,l.place,l.rules,i.value.time,r.fire).catch(c=>r.log(`[places] delivery failed: ${c?.message||c}`)):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=Wl(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=Gl(s,p=>i.has(p));if(!l.ok)return q(e,400,{error:l.error});let c=r.store.addRule(l.value,r.limits);return c.ok?q(e,200,{ok:!0,rule:c.rule}):q(e,409,{error:c.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 Zl(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new pa(Ul(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function ec(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 tc=`
16898
+ (${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 Zl(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}
16899
+ ${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?{[Xn]: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 ec(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:ac(t,e,a.slice(15),n,o,r)}async function tc(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:ac(t,e,a.slice(11),n,r,null)}async function ac(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=Yl(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?Ql(o.id,l.place,l.rules,i.value.time,r.fire).catch(c=>r.log(`[places] delivery failed: ${c?.message||c}`)):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=Jl(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=Vl(s,p=>i.has(p));if(!l.ok)return q(e,400,{error:l.error});let c=r.store.addRule(l.value,r.limits);return c.ok?q(e,200,{ok:!0,rule:c.rule}):q(e,409,{error:c.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 nc(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new pa(Kl(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function rc(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 oc=`
16887
16900
  :root {
16888
16901
  --ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
16889
16902
  --ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
@@ -16897,7 +16910,7 @@ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15
16897
16910
  --ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
16898
16911
  --phone-bubble: #1d2f52; --phone-green: #3dbe74;
16899
16912
  }
16900
- `,ac=`
16913
+ `,sc=`
16901
16914
  [hidden] { display: none !important; }
16902
16915
  main > .sw-peek[hidden] { display: block !important; }
16903
16916
  main > #panel-chat.sw-peek[hidden] { display: flex !important; }
@@ -17003,7 +17016,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
17003
17016
  @media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
17004
17017
  @media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
17005
17018
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
17006
- `;var nc=`
17019
+ `;var ic=`
17007
17020
  window.AXSheet = function (sheet, onClose) {
17008
17021
  var handle = document.createElement('button');
17009
17022
  handle.type = 'button'; handle.className = 'sheet-handle';
@@ -17032,7 +17045,7 @@ window.AXSheet = function (sheet, onClose) {
17032
17045
  handle.addEventListener('pointercancel', reset);
17033
17046
  sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
17034
17047
  };
17035
- `;var rc=`
17048
+ `;var lc=`
17036
17049
  (function () {
17037
17050
  var fleetPanel = document.getElementById('panel-fleet');
17038
17051
  var activityPanel = document.getElementById('panel-activity');
@@ -17328,7 +17341,7 @@ window.AXSheet = function (sheet, onClose) {
17328
17341
  setInterval(refresh, 15000);
17329
17342
  refresh();
17330
17343
  })();
17331
- `;var oc=`
17344
+ `;var cc=`
17332
17345
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
17333
17346
  .fx-head h2 { margin: 4px 0 0; }
17334
17347
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -17393,7 +17406,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17393
17406
  .fx-opt em { font-style: normal; font-size: 12px; color: var(--ax-ok); white-space: nowrap; }
17394
17407
  .fx-error:empty { display: none; }
17395
17408
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
17396
- `;var sc=`
17409
+ `;var dc=`
17397
17410
  (function () {
17398
17411
  var panel = document.getElementById('panel-desk');
17399
17412
  var ax = window.AXAsk;
@@ -17525,7 +17538,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17525
17538
  setInterval(refresh, 15000);
17526
17539
  refresh();
17527
17540
  })();
17528
- `;var ic=`
17541
+ `;var pc=`
17529
17542
  .dk-figures { margin: 0 0 4px; line-height: 1.5; }
17530
17543
  .dk-cols {
17531
17544
  position: sticky; top: 0; z-index: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px;
@@ -17542,7 +17555,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17542
17555
  .dk-opt { width: 100%; min-height: 48px; padding: 8px 14px; text-align: left; border-radius: var(--ax-radius-sm); overflow-wrap: anywhere; }
17543
17556
  .dk-opt small { display: block; margin-top: 2px; font-weight: 400; color: var(--ax-text-2); }
17544
17557
  .dk-opt em { font-style: normal; font-weight: 400; color: var(--ax-text-2); }
17545
- `;var lc=`
17558
+ `;var uc=`
17546
17559
  (function () {
17547
17560
  var panel = document.getElementById('panel-alerts');
17548
17561
  if (!panel) return;
@@ -17753,7 +17766,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17753
17766
  refresh();
17754
17767
  loadRecent();
17755
17768
  })();
17756
- `;var cc=`
17769
+ `;var mc=`
17757
17770
  (function () {
17758
17771
  var panel = document.getElementById('panel-alerts');
17759
17772
  if (!panel) return;
@@ -17905,7 +17918,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17905
17918
  document.addEventListener('visibilitychange', function () { if (!document.hidden && state) load(); });
17906
17919
  load();
17907
17920
  })();
17908
- `,dc=`
17921
+ `,fc=`
17909
17922
  .pl-card { margin-top: 12px; }
17910
17923
  .pl-list { margin-top: 8px; }
17911
17924
  .pl-rules { list-style: none; margin: 6px 0 0; padding: 0; }
@@ -17924,7 +17937,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17924
17937
  .pl-check { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); }
17925
17938
  .pl-check input { width: 20px; height: 20px; }
17926
17939
  #pl-here { justify-self: start; }
17927
- `;function pc(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 uc=`
17940
+ `;function hc(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 gc=`
17928
17941
  (function () {
17929
17942
  var panel = document.getElementById('panel-alerts');
17930
17943
  if (!panel) return;
@@ -18037,7 +18050,7 @@ details[open] > summary::before { transform: rotate(90deg); }
18037
18050
  }
18038
18051
  load();
18039
18052
  })();
18040
- `;var mc=`
18053
+ `;var xc=`
18041
18054
  (function () {
18042
18055
  var panel = document.getElementById('panel-chat');
18043
18056
  var V = window.AXChatView;
@@ -18320,7 +18333,7 @@ details[open] > summary::before { transform: rotate(90deg); }
18320
18333
  var last = recall('ax-chat-conv');
18321
18334
  if (!fromHash() && last) openConversation(last);
18322
18335
  })();
18323
- `;var fc=`
18336
+ `;var bc=`
18324
18337
  window.AXChatView = (function () {
18325
18338
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
18326
18339
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -18601,7 +18614,7 @@ window.AXChatView = (function () {
18601
18614
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
18602
18615
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
18603
18616
  })();
18604
- `;var hc=`
18617
+ `;var vc=`
18605
18618
  window.AXChatSheets = function (o) {
18606
18619
  var V = o.V, picker = o.picker, hist = o.hist;
18607
18620
  function loadPicker() {
@@ -18647,7 +18660,7 @@ window.AXChatSheets = function (o) {
18647
18660
  });
18648
18661
  return { loadPicker: loadPicker, loadHistory: loadHistory };
18649
18662
  };
18650
- `;var gc=`
18663
+ `;var yc=`
18651
18664
  window.AXChatLog = function (o) {
18652
18665
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
18653
18666
  function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
@@ -18710,7 +18723,7 @@ window.AXChatLog = function (o) {
18710
18723
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
18711
18724
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
18712
18725
  };
18713
- `;var xc=`
18726
+ `;var wc=`
18714
18727
  (function () {
18715
18728
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
18716
18729
  var top = panel && panel.querySelector('.cx-top');
@@ -18860,7 +18873,7 @@ window.AXChatLog = function (o) {
18860
18873
  window.AXStrip = { poll: poll, update: update, banner: banner };
18861
18874
  poll();
18862
18875
  })();
18863
- `;var bc=`
18876
+ `;var kc=`
18864
18877
  .cs { margin: 0 -2px; }
18865
18878
  .cs[hidden] { display: none; }
18866
18879
  .cs-list {
@@ -18916,7 +18929,7 @@ window.AXChatLog = function (o) {
18916
18929
  @media (prefers-reduced-motion: reduce) {
18917
18930
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
18918
18931
  }
18919
- `;function vc(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 yc(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var wc=`
18932
+ `;function _c(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 Sc(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Ec=`
18920
18933
  body { height: 100dvh; }
18921
18934
  main { min-height: 0; }
18922
18935
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -19026,7 +19039,7 @@ main { min-height: 0; }
19026
19039
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
19027
19040
  }
19028
19041
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
19029
- `;var kc=`
19042
+ `;var Tc=`
19030
19043
  window.AXOrb = (function () {
19031
19044
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
19032
19045
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -19143,7 +19156,7 @@ window.AXOrb = (function () {
19143
19156
  }
19144
19157
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
19145
19158
  })();
19146
- `;var _c=`
19159
+ `;var Ac=`
19147
19160
  window.AXVoiceIO = (function () {
19148
19161
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
19149
19162
  var ac = null, playing = null;
@@ -19261,7 +19274,7 @@ window.AXVoiceIO = (function () {
19261
19274
 
19262
19275
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
19263
19276
  })();
19264
- `;var Sc=`
19277
+ `;var Cc=`
19265
19278
  (function () {
19266
19279
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
19267
19280
  if (!panel || !C || !IO || !O) return;
@@ -19474,7 +19487,7 @@ window.AXVoiceIO = (function () {
19474
19487
  idle();
19475
19488
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
19476
19489
  })();
19477
- `;var Ec=`
19490
+ `;var Ic=`
19478
19491
  .vx {
19479
19492
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
19480
19493
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -19510,7 +19523,7 @@ window.AXVoiceIO = (function () {
19510
19523
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
19511
19524
  .cx-typing-on .vx-row { gap: 16px; }
19512
19525
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
19513
- `;var Tc=`
19526
+ `;var Mc=`
19514
19527
  <main class="card">
19515
19528
  <h1>This phone isn't paired</h1>
19516
19529
  <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>
@@ -19524,7 +19537,7 @@ window.AXVoiceIO = (function () {
19524
19537
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
19525
19538
  </form>
19526
19539
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
19527
- </main>`,Ac=`
19540
+ </main>`,Rc=`
19528
19541
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
19529
19542
  .pair-form label { font-weight: 600; }
19530
19543
  .pair-form input {
@@ -19546,7 +19559,7 @@ window.AXVoiceIO = (function () {
19546
19559
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
19547
19560
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
19548
19561
  }
19549
- `,Cc=`
19562
+ `,Lc=`
19550
19563
  (function () {
19551
19564
  var form = document.getElementById('pair-form');
19552
19565
  var input = document.getElementById('pair-code');
@@ -19638,7 +19651,7 @@ window.AXVoiceIO = (function () {
19638
19651
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
19639
19652
  }
19640
19653
  })();
19641
- `;var Ic=`
19654
+ `;var Pc=`
19642
19655
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
19643
19656
  <video id="scan-video" playsinline muted autoplay></video>
19644
19657
  <div class="scan-frame" aria-hidden="true"></div>
@@ -19647,7 +19660,7 @@ window.AXVoiceIO = (function () {
19647
19660
  <button type="button" id="scan-close" class="scan-close">Close</button>
19648
19661
  </div>
19649
19662
  <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>
19650
- </div>`,Mc=`
19663
+ </div>`,$c=`
19651
19664
  .pair-form .scan-btn {
19652
19665
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
19653
19666
  }
@@ -19676,7 +19689,7 @@ window.AXVoiceIO = (function () {
19676
19689
  }
19677
19690
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
19678
19691
  body.scanning { overflow: hidden; }
19679
- `,Rc=`
19692
+ `,jc=`
19680
19693
  (function () {
19681
19694
  var openBtn = document.getElementById('scan-btn');
19682
19695
  var box = document.getElementById('scan');
@@ -19901,7 +19914,7 @@ body.scanning { overflow: hidden; }
19901
19914
  @keyframes cam-pulse { 50% { opacity: .3; } }
19902
19915
  @media (prefers-reduced-motion: reduce) { .cam-live.is-stream .cam-dot { animation: none; } }
19903
19916
  #cam-stream[aria-pressed="true"] { border-color: var(--ax-red); color: var(--ax-red-ink); }
19904
- `;var Lc='<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>',Pc=`
19917
+ `;var Oc='<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>',Nc=`
19905
19918
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
19906
19919
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
19907
19920
  <span class="cam-dot" aria-hidden="true"></span>
@@ -19930,7 +19943,7 @@ body.scanning { overflow: hidden; }
19930
19943
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
19931
19944
  </div>
19932
19945
  </div>
19933
- </div>`,$c=`
19946
+ </div>`,Dc=`
19934
19947
  (function () {
19935
19948
  var btn = document.getElementById('cam-btn');
19936
19949
  var sheet = document.getElementById('cam');
@@ -20404,7 +20417,7 @@ body.scanning { overflow: hidden; }
20404
20417
  });
20405
20418
  window.addEventListener('pagehide', function () { stop(); });
20406
20419
  })();
20407
- `;var jc=`
20420
+ `;var Hc=`
20408
20421
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
20409
20422
  <div class="cam-askbar-text">
20410
20423
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -20414,7 +20427,7 @@ body.scanning { overflow: hidden; }
20414
20427
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
20415
20428
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
20416
20429
  </div>
20417
- </div>`,Oc=`
20430
+ </div>`,Bc=`
20418
20431
  .cam-askbar[hidden] { display: none; }
20419
20432
  .cam-askbar {
20420
20433
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -20429,7 +20442,7 @@ body.scanning { overflow: hidden; }
20429
20442
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
20430
20443
  }
20431
20444
  .cam-askbar-no { background: transparent; color: #fff; }
20432
- `,Nc=`
20445
+ `,qc=`
20433
20446
  (function () {
20434
20447
  var bar = document.getElementById('cam-ask-bar');
20435
20448
  if (!bar) return;
@@ -20499,7 +20512,7 @@ body.scanning { overflow: hidden; }
20499
20512
  setInterval(poll, 5000);
20500
20513
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
20501
20514
  })();
20502
- `;function Dc(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 Hc(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 Bc(t){return t>=400?"send":"listen"}function qc(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var zc=`
20515
+ `;function zc(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 Fc(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 Uc(t){return t>=400?"send":"listen"}function Wc(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var Gc=`
20503
20516
  (function () {
20504
20517
  var main = document.querySelector('main');
20505
20518
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
@@ -20618,7 +20631,7 @@ body.scanning { overflow: hidden; }
20618
20631
  main.addEventListener('touchend', function () { end(false); });
20619
20632
  main.addEventListener('touchcancel', function () { end(true); });
20620
20633
  })();
20621
- `,Fc=`
20634
+ `,Xc=`
20622
20635
  main { position: relative; }
20623
20636
  main.sw-on { overflow: hidden; }
20624
20637
  .sw-on > [role=tabpanel] { will-change: transform; }
@@ -20629,8 +20642,8 @@ main > .sw-peek {
20629
20642
  }
20630
20643
  main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
20631
20644
  @media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
20632
- `;function Uc(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 Wc(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Gc(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Xc(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 kn=`
20633
- ${z({afterUnauthorized:Ko})}
20645
+ `;function Kc(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 Jc(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Vc(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Yc(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 kn=`
20646
+ ${z({afterUnauthorized:Qo})}
20634
20647
  var CACHE = 'agentx-app-v3';
20635
20648
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
20636
20649
  self.addEventListener('install', function (e) {
@@ -20721,7 +20734,7 @@ self.addEventListener('notificationclick', function (e) {
20721
20734
  return self.clients.openWindow(target);
20722
20735
  }));
20723
20736
  });
20724
- `;var Sh="<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 _n(t){return`<meta charset="utf-8">
20737
+ `;var Ch="<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 _n(t){return`<meta charset="utf-8">
20725
20738
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
20726
20739
  <meta name="theme-color" content="#2979FF">
20727
20740
  <meta name="referrer" content="no-referrer">
@@ -20732,41 +20745,41 @@ self.addEventListener('notificationclick', function (e) {
20732
20745
  <link rel="icon" type="image/png" href="/app/icon-192.png">
20733
20746
  <link rel="apple-touch-icon" href="/app/icon-192.png">
20734
20747
  <title>${t}</title>
20735
- ${Sh}
20736
- <style>${Ue}${tc}${Ch}</style>`}var Eh={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"},Kc=[{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 Jc(){let t=Kc.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="${Eh[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=Kc.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20748
+ ${Ch}
20749
+ <style>${Ue}${oc}${Lh}</style>`}var Ih={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"},Qc=[{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 Zc(){let t=Qc.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="${Ih[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=Qc.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20737
20750
  <h2>${a.label}</h2>
20738
20751
  <p class="soon">${a.soon}</p>
20739
20752
  </section>`).join("");return`<!doctype html>
20740
20753
  <html lang="en">
20741
- <head>${_n("AgentX")}<style>${Ih}${oc}${ic}${wc}${bc}${Ec}${wn}${Oc}${Fc}${dc}${ac}</style></head>
20754
+ <head>${_n("AgentX")}<style>${Ph}${cc}${pc}${Ec}${kc}${Ic}${wn}${Bc}${Xc}${fc}${sc}</style></head>
20742
20755
  <body>
20743
20756
  <header class="bar">
20744
20757
  <div>
20745
20758
  <h1>AgentX</h1>
20746
20759
  <p id="who" class="who">Connecting\u2026</p>
20747
20760
  </div>
20748
- <div class="bar-btns">${Lc}<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>
20761
+ <div class="bar-btns">${Oc}<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>
20749
20762
  </header>
20750
20763
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
20751
- ${jc}
20764
+ ${Hc}
20752
20765
  <main>${e}</main>
20753
20766
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
20754
- ${Pc}
20755
- <script>${Th}</script>
20756
- <script>${z({swipeMayStart:Uc,swipeAxis:Wc,swipeOffset:Gc,swipeLanding:Xc})}${zc}</script>
20757
- <script>${nc}</script>
20758
- <script>${rc}</script>
20759
- <script>${sc}</script>
20767
+ ${Nc}
20768
+ <script>${Mh}</script>
20769
+ <script>${z({swipeMayStart:Kc,swipeAxis:Jc,swipeOffset:Vc,swipeLanding:Yc})}${Gc}</script>
20770
+ <script>${ic}</script>
20760
20771
  <script>${lc}</script>
20761
- <script>${z({locationErrorText:pc})}${cc}</script>
20772
+ <script>${dc}</script>
20762
20773
  <script>${uc}</script>
20763
- <script>${z({markdownToHtml:Cr})}${fc}${gc}${hc}${mc}</script>
20764
- <script>${z({queueSpeech:vc,nextSpeech:yc})}${kc}${_c}${Sc}</script>
20765
- <script>${xc}</script>
20766
- <script>${z({cameraConstraints:Dc,shareClock:Hc,streamLabel:qc,talkRelease:Bc})}${$c}</script>
20767
- <script>${Nc}</script>
20774
+ <script>${z({locationErrorText:hc})}${mc}</script>
20775
+ <script>${gc}</script>
20776
+ <script>${z({markdownToHtml:Ir})}${bc}${yc}${vc}${xc}</script>
20777
+ <script>${z({queueSpeech:_c,nextSpeech:Sc})}${Tc}${Ac}${Cc}</script>
20778
+ <script>${wc}</script>
20779
+ <script>${z({cameraConstraints:zc,shareClock:Fc,streamLabel:Wc,talkRelease:Uc})}${Dc}</script>
20780
+ <script>${qc}</script>
20768
20781
  </body>
20769
- </html>`}function Vc(){return`<!doctype html>
20782
+ </html>`}function ed(){return`<!doctype html>
20770
20783
  <html lang="en">
20771
20784
  <head>${_n("Pair \xB7 AgentX")}</head>
20772
20785
  <body>
@@ -20774,17 +20787,17 @@ ${Pc}
20774
20787
  <h1>Pairing this phone\u2026</h1>
20775
20788
  <p id="msg" role="status">One moment.</p>
20776
20789
  </main>
20777
- <script>${Ah}</script>
20790
+ <script>${Rh}</script>
20778
20791
  </body>
20779
- </html>`}function Yc(){return`<!doctype html>
20792
+ </html>`}function td(){return`<!doctype html>
20780
20793
  <html lang="en">
20781
- <head>${_n("Not paired \xB7 AgentX")}<style>${Ac}${Mc}</style></head>
20782
- <body>${Tc}${Ic}
20783
- <script>${z({mayBounce:Jo,formatPairInput:Xt,parsePairScan:Vo})}</script>
20784
- <script>${Cc}</script>
20785
- <script>${Rc}</script>
20794
+ <head>${_n("Not paired \xB7 AgentX")}<style>${Rc}${$c}</style></head>
20795
+ <body>${Mc}${Pc}
20796
+ <script>${z({mayBounce:Zo,formatPairInput:Xt,parsePairScan:es})}</script>
20797
+ <script>${Lc}</script>
20798
+ <script>${jc}</script>
20786
20799
  </body>
20787
- </html>`}function Qc(){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 Th=`
20800
+ </html>`}function ad(){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 Mh=`
20788
20801
  (function () {
20789
20802
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
20790
20803
  function select(tab, focus, keepHash) {
@@ -20856,7 +20869,7 @@ ${Pc}
20856
20869
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
20857
20870
  }
20858
20871
  })();
20859
- `,Ah=`
20872
+ `,Rh=`
20860
20873
  (function () {
20861
20874
  var msg = document.getElementById('msg');
20862
20875
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -20873,7 +20886,7 @@ ${Pc}
20873
20886
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
20874
20887
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
20875
20888
  })();
20876
- `,Ch=`
20889
+ `,Lh=`
20877
20890
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
20878
20891
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
20879
20892
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -20885,7 +20898,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
20885
20898
  .card h1 { font-size: 22px; margin: 0 0 12px; }
20886
20899
  .muted { color: var(--ax-text-2); }
20887
20900
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
20888
- `,Ih=`
20901
+ `,Ph=`
20889
20902
  body { display: flex; flex-direction: column; }
20890
20903
  .bar {
20891
20904
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -20923,8 +20936,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20923
20936
  }
20924
20937
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
20925
20938
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
20926
- `;var ua="agentx_app",Lh=400*86400,Ph=new Rt,$h=new Re;async function Zc(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",Qc());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",kn);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",Vc());if(a==="/app/qr.js"){let i=jh();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=Sn(dt(t),o);return i?(e.setHeader("Set-Cookie",En(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 Ar(t,{codes:r.pairCodes??new At,limiter:r.pairLimiter??Ph,verify:l=>Sn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",En(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ee(e,i.status,i.body)}let s=Sn(Oh(t),o);if(!s){let i=dt(t);return(r.rejectLog??$h).record(a.slice(0,120),Ut(t,We(Tn(t,ua),o),i?We(i,o):null)),a==="/app"?fe(e,401,"text/html; charset=utf-8",Yc()):Ee(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Tn(t,ua);return i&&!dt(t)&&e.setHeader("Set-Cookie",En(i)),fe(e,200,"text/html; charset=utf-8",Jc())}return n==="GET"&&a==="/api/app/me"?Ee(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await xr(t,e,a,n,s.name,r.fleet)||r.desk&&await ml(t,e,a,n,r.desk)||r.push&&await br(t,e,a,n,s,r.push)||r.announce&&await gl(t,e,a,n,s,r.announce)||r.chat&&await Al(t,e,a,n,s,r.chat)||r.chat&&await Rl(t,e,a,n,s,r.chat)||r.voice&&await $l(t,e,a,n,s,r.voice)||r.camera&&await Ol(t,e,a,n,r.camera)||r.places&&await Vl(t,e,a,n,s,r.places)?!0:Ee(e,404,{error:"not found"})}var ct;function jh(){if(ct!==void 0)return ct;try{let t=Rh(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
20927
- `;ct=Buffer.concat([Buffer.from(a),Mh(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),ct=null}return ct}function Sn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ae(a,"app")?a:null}function En(t){return`${ua}=${t}; Path=/; Max-Age=${Lh}; HttpOnly; Secure; SameSite=Lax`}function Oh(t){return dt(t)??Tn(t,ua)}function dt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Tn(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 ed(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."})+`
20939
+ `;var ua="agentx_app",Oh=400*86400,Nh=new Rt,Dh=new Re;async function nd(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",ad());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",kn);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",ed());if(a==="/app/qr.js"){let i=Hh();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=Sn(dt(t),o);return i?(e.setHeader("Set-Cookie",En(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 Pr(t,{codes:r.pairCodes??new At,limiter:r.pairLimiter??Nh,verify:l=>Sn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",En(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ee(e,i.status,i.body)}let s=Sn(Bh(t),o);if(!s){let i=dt(t);return(r.rejectLog??Dh).record(a.slice(0,120),Ut(t,We(Tn(t,ua),o),i?We(i,o):null)),a==="/app"?fe(e,401,"text/html; charset=utf-8",td()):Ee(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Tn(t,ua);return i&&!dt(t)&&e.setHeader("Set-Cookie",En(i)),fe(e,200,"text/html; charset=utf-8",Zc())}return n==="GET"&&a==="/api/app/me"?Ee(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await yr(t,e,a,n,s.name,r.fleet)||r.desk&&await xl(t,e,a,n,r.desk)||r.push&&await wr(t,e,a,n,s,r.push)||r.announce&&await yl(t,e,a,n,s,r.announce)||r.chat&&await Rl(t,e,a,n,s,r.chat)||r.chat&&await jl(t,e,a,n,s,r.chat)||r.voice&&await Dl(t,e,a,n,s,r.voice)||r.camera&&await Bl(t,e,a,n,r.camera)||r.places&&await ec(t,e,a,n,s,r.places)?!0:Ee(e,404,{error:"not found"})}var ct;function Hh(){if(ct!==void 0)return ct;try{let t=jh(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
20940
+ `;ct=Buffer.concat([Buffer.from(a),$h(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),ct=null}return ct}function Sn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ae(a,"app")?a:null}function En(t){return`${ua}=${t}; Path=/; Max-Age=${Oh}; HttpOnly; Secure; SameSite=Lax`}function Bh(t){return dt(t)??Tn(t,ua)}function dt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Tn(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 rd(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."})+`
20928
20941
  <div class="pl-wrap">
20929
20942
  <div id="pl-msg" class="pl-msg" role="status" aria-live="polite"></div>
20930
20943
  <form id="pl-add" class="pl-form" autocomplete="off">
@@ -20936,7 +20949,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20936
20949
  <button type="submit" class="ax-btn ax-btn--primary">Add place</button>
20937
20950
  </form>
20938
20951
  <ol id="pl-list" class="pl-list" aria-label="Places"><li class="pl-empty">Loading\u2026</li></ol>
20939
- </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:Nh,scripts:`<script>${Dh}</script>`})}var Nh=`
20952
+ </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:qh,scripts:`<script>${zh}</script>`})}var qh=`
20940
20953
  .pl-wrap { max-width: 1040px; margin: 0 auto; padding: 0 24px 96px; box-sizing: border-box; }
20941
20954
  .pl-msg { min-height: 1.4em; margin: 8px 0 0; }
20942
20955
  .pl-msg.is-bad { color: var(--ax-red-ink); }
@@ -20959,7 +20972,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20959
20972
  .pl-rule-form { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
20960
20973
  .pl-rule-form input[name=text] { flex: 1 1 240px; }
20961
20974
  .pl-btns { margin-left: auto; display: flex; gap: 8px; }
20962
- `,Dh=`
20975
+ `,zh=`
20963
20976
  (function () {
20964
20977
  var list = document.getElementById('pl-list');
20965
20978
  var msg = document.getElementById('pl-msg');
@@ -21038,7 +21051,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
21038
21051
  });
21039
21052
  load();
21040
21053
  })();
21041
- `;import{randomBytes as td}from"crypto";var Be={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:pe.perMessage},Hh=/^[a-f0-9]{32}$/,Bh=/^c[a-z0-9]{8,32}$/,qh=/^#[0-9a-fA-F]{6}$/;function An(t){return Bh.test(t)}var pt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
21054
+ `;import{randomBytes as od}from"crypto";var Be={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:pe.perMessage},Fh=/^[a-f0-9]{32}$/,Uh=/^c[a-z0-9]{8,32}$/,Wh=/^#[0-9a-fA-F]{6}$/;function An(t){return Uh.test(t)}var pt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
21042
21055
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
21043
21056
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
21044
21057
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -21051,39 +21064,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
21051
21064
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
21052
21065
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
21053
21066
  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 (
21054
- key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return An(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)}${td(4).toString("hex")}`,{color:s,...i}=a,l=s&&qh.test(s)?s:void 0,c={id:o,title:Fh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
21055
- (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!An(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(zh);return{...ad(n),messages:r}}list(e,a=Be.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
21067
+ key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return An(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)}${od(4).toString("hex")}`,{color:s,...i}=a,l=s&&Wh.test(s)?s:void 0,c={id:o,title:Xh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
21068
+ (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!An(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(Gh);return{...sd(n),messages:r}}list(e,a=Be.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
21056
21069
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
21057
21070
  (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
21058
- 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{...ad(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){An(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,
21071
+ 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{...sd(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){An(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,
21059
21072
  substr(m.content, 1, 240) AS answer, m.status, m.at
21060
21073
  FROM app_chat_conversations c
21061
21074
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
21062
21075
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
21063
21076
  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)+`
21064
21077
 
21065
- [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=ir(g);if(!k||!g||g.length>pe.pathChars||g.includes("\0"))continue;let b=(g.split(/[\\/]/).pop()||g).slice(0,120);l.push({id:td(16).toString("hex"),name:b,mime:k.mime,kind:k.kind,path:g})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
21078
+ [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=dr(g);if(!k||!g||g.length>pe.pathChars||g.includes("\0"))continue;let b=(g.split(/[\\/]/).pop()||g).slice(0,120);l.push({id:od(16).toString("hex"),name:b,mime:k.mime,kind:k.kind,path:g})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
21066
21079
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,c.length?JSON.stringify(c):null,n.at),d=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
21067
21080
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)d.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
21068
21081
  (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
21069
- (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!Hh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
21082
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!Fh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
21070
21083
  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 = ?
21071
- 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 ad(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 zh(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 Fh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Uh=4e3,Cn=100,Wh=15,nd=t=>t.replace(/\/+$/,""),ma=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Uh){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,Cn);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??Wh)-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>=Cn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Cn}); 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||nd(l)!==nd(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=Gh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let d=c.row.status,m=!!this.deps.finishAlerts?.(s),g={status:d,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&ca(g)&&this.deps.notifyFinish(da(s,i,d,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Gh(t,e){let a=t.plain?{text:_t(t.text,!1),artifacts:[]}:kt(t.text,pe.perMessage,!1),{cleanText:n,ui:r}=Et(a.text),o=t.plain?void 0:fn(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Xh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Xh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Gn();var Kh=3,In=7,Mn=50,Rn=120,Jh=280,od=600,sd=36e5,Vh=24*sd;function id(t){let e=new Set;for(let a of t)for(let n of a.runningTasks??[])n.traceId&&e.add(n.traceId);return e}function ut(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 Yh(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:ut(e.title,Rn),...e.ask?{ask:ut(e.ask,od)}:{},...e.detail?{facts:ut(e.detail,Jh)}:{},...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 Qh={done:"Done",declined:"Declined",dropped:"Dropped"};function Zh(t,e,a){let{record:n,links:r}=e,o={key:`request:${n.id}`,kind:"request",node:t.node,nodeName:t.nodeName,title:Ir(n.text,Rn),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:ut(n.question,od)}:{},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??Kh)*sd;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:Qh[n.state]??n.state,...s?{evidence:s}:{},can:{answer:!1,later:!1,reply:!1}}}}}function eg(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 tg(t,e){return{key:`card:${e.id}`,kind:"card",column:"done",node:t.node,nodeName:t.nodeName,title:ut(e.title,Rn),ask:e.ask,agent:e.raised_by,askedAt:e.created_at,...e.decided_at?{changedAt:e.decided_at}:{},outcome:eg(e),...e.resolution?{evidence:e.resolution}:{},can:{answer:!1,later:!1,reply:!1}}}var ce=t=>t&&Date.parse(t)||0,rd=(t,e)=>t.map(a=>a[e]).filter(a=>!!ce(a)).sort((a,n)=>ce(a)-ce(n))[0];function ld(t){let e=[],a=[];for(let d of t.inbox){d.error&&a.push(`What waits on ${d.nodeName} could not be read: ${d.error}`);for(let m of d.items)e.push(Yh(d,m,d.node===t.node))}let n=new Set([...e.filter(d=>d.node===t.node).map(d=>d.key),...t.deferred??[]]),r=[],o=[],s=[];for(let d of t.requests??[]){let m=Zh(t,d,n);m&&{yours:e,agent:r,quiet:o,done:s}[m.column].push(m)}let i=t.now-(t.doneDays??In)*Vh;for(let d of t.cards)d.status!=="pending"&&ce(d.decided_at)>=i&&s.push(tg(t,d));r.sort((d,m)=>ce(m.changedAt)-ce(d.changedAt)),o.sort((d,m)=>ce(d.changedAt)-ce(m.changedAt)),s.sort((d,m)=>ce(m.changedAt)-ce(d.changedAt));let l=s.filter(d=>ce(d.changedAt)>=i).slice(0,Mn),c=rd(e,"askedAt"),p=rd(o,"changedAt");return{ts:fa(t.now),cards:[...e,...r,...o,...l],figures:{yours:{count:e.length,...c?{oldest:c}:{}},agent:{count:r.length},quiet:{count:o.length,...p?{oldest:p}:{}},done:{count:l.length}},errors:a}}function Ze(){let t=bt();return t&&Se(t,"dashboard"),t}function O_(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,mg(g,t))}catch(k){console.error(` Board "${g.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?mt(process.cwd(),t.workflows.dir):void 0,c=new tr(l?{baseDir:l}:void 0),p=new ar(l?{baseDir:l,nodeId:i}:{nodeId:i}),d=new nr(l?{baseDir:l}:void 0);Li(t),Ze(),Or({business:t.business?.enabled===!0});let m=ag(async(g,k)=>{try{await cg(g,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:d})}catch(b){w(k,500,{error:b.message||"internal error"})}});Rg(t).start(),m.listen(n,r,()=>{let g=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
21084
+ 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 sd(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 Gh(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 Xh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Kh=4e3,Cn=100,Jh=15,id=t=>t.replace(/\/+$/,""),ma=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,Cn);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??Jh)-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>=Cn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Cn}); 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||id(l)!==id(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=Vh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let d=c.row.status,m=!!this.deps.finishAlerts?.(s),g={status:d,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&ca(g)&&this.deps.notifyFinish(da(s,i,d,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Vh(t,e){let a=t.plain?{text:_t(t.text,!1),artifacts:[]}:kt(t.text,pe.perMessage,!1),{cleanText:n,ui:r}=Et(a.text),o=t.plain?void 0:fn(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Yh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Yh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Gn();var Qh=3,In=7,Mn=50,Rn=120,Zh=280,cd=600,dd=36e5,eg=24*dd;function pd(t){let e=new Set;for(let a of t)for(let n of a.runningTasks??[])n.traceId&&e.add(n.traceId);return e}function ut(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 tg(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:ut(e.title,Rn),...e.ask?{ask:ut(e.ask,cd)}:{},...e.detail?{facts:ut(e.detail,Zh)}:{},...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 ag={done:"Done",declined:"Declined",dropped:"Dropped"};function ng(t,e,a){let{record:n,links:r}=e,o={key:`request:${n.id}`,kind:"request",node:t.node,nodeName:t.nodeName,title:Rr(n.text,Rn),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:ut(n.question,cd)}:{},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??Qh)*dd;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:ag[n.state]??n.state,...s?{evidence:s}:{},can:{answer:!1,later:!1,reply:!1}}}}}function rg(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 og(t,e){return{key:`card:${e.id}`,kind:"card",column:"done",node:t.node,nodeName:t.nodeName,title:ut(e.title,Rn),ask:e.ask,agent:e.raised_by,askedAt:e.created_at,...e.decided_at?{changedAt:e.decided_at}:{},outcome:rg(e),...e.resolution?{evidence:e.resolution}:{},can:{answer:!1,later:!1,reply:!1}}}var ce=t=>t&&Date.parse(t)||0,ld=(t,e)=>t.map(a=>a[e]).filter(a=>!!ce(a)).sort((a,n)=>ce(a)-ce(n))[0];function ud(t){let e=[],a=[];for(let d of t.inbox){d.error&&a.push(`What waits on ${d.nodeName} could not be read: ${d.error}`);for(let m of d.items)e.push(tg(d,m,d.node===t.node))}let n=new Set([...e.filter(d=>d.node===t.node).map(d=>d.key),...t.deferred??[]]),r=[],o=[],s=[];for(let d of t.requests??[]){let m=ng(t,d,n);m&&{yours:e,agent:r,quiet:o,done:s}[m.column].push(m)}let i=t.now-(t.doneDays??In)*eg;for(let d of t.cards)d.status!=="pending"&&ce(d.decided_at)>=i&&s.push(og(t,d));r.sort((d,m)=>ce(m.changedAt)-ce(d.changedAt)),o.sort((d,m)=>ce(d.changedAt)-ce(m.changedAt)),s.sort((d,m)=>ce(m.changedAt)-ce(d.changedAt));let l=s.filter(d=>ce(d.changedAt)>=i).slice(0,Mn),c=ld(e,"askedAt"),p=ld(o,"changedAt");return{ts:fa(t.now),cards:[...e,...r,...o,...l],figures:{yours:{count:e.length,...c?{oldest:c}:{}},agent:{count:r.length},quiet:{count:o.length,...p?{oldest:p}:{}},done:{count:l.length}},errors:a}}function et(){let t=bt();return t&&Se(t,"dashboard"),t}function q_(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,xg(g,t))}catch(k){console.error(` Board "${g.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?mt(process.cwd(),t.workflows.dir):void 0,c=new rr(l?{baseDir:l}:void 0),p=new or(l?{baseDir:l,nodeId:i}:{nodeId:i}),d=new sr(l?{baseDir:l}:void 0);Oi(t),et(),Hr({business:t.business?.enabled===!0});let m=sg(async(g,k)=>{try{await mg(g,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:d})}catch(b){w(k,500,{error:b.message||"internal error"})}});jg(t).start(),m.listen(n,r,()=>{let g=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
21072
21085
  Live dashboard: http://${g}:${n}
21073
21086
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
21074
21087
  Kanban dashboard: http://${g}:${n}
21075
- `),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 lg=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 cg(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($r(t.headers)==="foreign"&&jr(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 ys(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>rt(a.config.people),members:dd(a.config.members.logRetentionDays),db:()=>Ze(),linkFor:(u,f)=>zo(u,f,{gitlab:a.config.channels.gitlab?.host})})||await Zc(t,e,r,o,{nodeName:a.config.node?.name,fleet:Nn(a.config),desk:Ig(a.config),push:On(a.config),announce:xl(a.config),chat:hd(a.config),voice:Lg(a.config),camera:Pg(a.config),places:cd(a.config),assetLinks:()=>ec(a.config)}))return;let s=o==="GET"?Ho(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"&&lg.has(r)&&go("page",r),o==="GET"&&r==="/"){let u=to();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(un({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rl({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(un({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(Mo({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Io({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(Eo({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=cr(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 lr(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(Zi({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ed({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(el({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(ol({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sl({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(il({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(eo({}));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(ll({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 c=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(c){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cl({agentId:decodeURIComponent(c[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"){ao(t,e);return}if(o==="POST"&&r==="/api/setup"){await no(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await ro(t,e);return}if(o==="GET"&&r==="/admin"){Rs(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Xs(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Hs(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}ni(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 Hg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await dn(t,e,r,v=>xd(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 _=ft(L.url.replace(/\/+$/,""),a.config);if(_){await ud(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=ft(u,a.config);if(!f){w(e,404,{error:`unknown peer: ${u}`});return}let v=(n.search||"").replace(/[?&]peer=[^&]*/g,E=>E.startsWith("?")?"?":"");await ud(t,e,f,r+(v==="?"?"":v));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await ri(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Bg(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-RTVGZP3X.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(li({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await ii(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ci({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(di({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 gg(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 Pi(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 ji(t,e,r))return;let p=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(p){Di(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 Ls(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,Hr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Ks(t,e,r,n);return}if(await Vs(t,e,r,{people:()=>rt(a.config.people),members:dd(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ze(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Bs(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Hi(t,e,r);return}if(r.startsWith("/api/admin/")){await Ps(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(ws);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=Ng("web/"+u);try{let v=await Dg(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 tl(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 nl(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 al(e,await Te(a.config),u,v)}catch(y){w(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){_g(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 Sg(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 Ag(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 Cg(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 jg(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let u=d[1];if(!Eg(t,e,[`agent:${u}`]))return;await Tg(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,Dr(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 xg(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 Yl(t,e,r,o,cd(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
21088
+ `),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 ug=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 mg(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(Nr(t.headers)==="foreign"&&Dr(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:()=>ot(a.config.people),members:fd(a.config.members.logRetentionDays),db:()=>et(),linkFor:(u,f)=>Go(u,f,{gitlab:a.config.channels.gitlab?.host})})||await nd(t,e,r,o,{nodeName:a.config.node?.name,fleet:Nn(a.config),desk:Pg(a.config),push:On(a.config),announce:wl(a.config),chat:vd(a.config),voice:Og(a.config),camera:Ng(a.config),places:md(a.config),assetLinks:()=>rc(a.config)}))return;let s=o==="GET"?Fo(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"&&ug.has(r)&&yo("page",r),o==="GET"&&r==="/"){let u=ro();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(un({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ll({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(un({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($o({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Po({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(Io({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=ur(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 pr(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(nl({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rd({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rl({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(cl({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(dl({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pl({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(no({}));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(ul({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 c=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(c){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ml({agentId:decodeURIComponent(c[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"){oo(t,e);return}if(o==="POST"&&r==="/api/setup"){await so(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await io(t,e);return}if(o==="GET"&&r==="/admin"){js(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Ys(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Fs(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}ii(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 Fg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await dn(t,e,r,v=>wd(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 _=ft(L.url.replace(/\/+$/,""),a.config);if(_){await gd(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=ft(u,a.config);if(!f){w(e,404,{error:`unknown peer: ${u}`});return}let v=(n.search||"").replace(/[?&]peer=[^&]*/g,E=>E.startsWith("?")?"?":"");await gd(t,e,f,r+(v==="?"?"":v));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await li(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Ug(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-5Y7QSXNQ.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(ui({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await pi(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mi({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fi({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 yg(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 Ni(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 Hi(t,e,r))return;let p=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(p){zi(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 Os(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,zr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Qs(t,e,r,n);return}if(await ei(t,e,r,{people:()=>ot(a.config.people),members:fd(a.config.members.logRetentionDays),root:process.cwd(),db:()=>et(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Us(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Fi(t,e,r);return}if(r.startsWith("/api/admin/")){await Ns(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(Es);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=qg("web/"+u);try{let v=await zg(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 tt(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 tt(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 ol(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 il(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 sl(e,await Te(a.config),u,v)}catch(y){w(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){Ag(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 Cg(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 Rg(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 Lg(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 Hg(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let u=d[1];if(!Ig(t,e,[`agent:${u}`]))return;await Mg(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,qr(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 wg(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 tc(t,e,r,o,md(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
21076
21089
 
21077
21090
  `)}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:de}=await j.read();if(W)break;O+=$.decode(de,{stream:!0});let Q;for(;(Q=O.indexOf(`
21078
21091
 
21079
21092
  `))>=0;){let oe=O.slice(0,Q);if(O=O.slice(Q+2),y.flag)break;try{e.write(oe+`
21080
21093
 
21081
- `)}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:sr([...y.values()],x=>E.get(x)),unreachable:f});return}if(r==="/api/workflows/required"){let u=()=>({settings:ko(),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 _o(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,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[]}})),_=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($=>ug($)):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")&&pl(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,v,y)=>{if(a.token)return!0;let E=Ma(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 pg(E,v,L,A),Ln({actor:Pn(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 dg(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}Ln({actor:Pn(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});Ln({actor:Pn(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 dg(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),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(h=>h.kind!=="closed"),d=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=d?await e.listAll({sinceDays:c,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=Bn(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 pg(t,e,a,n){let r=qn(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 ug(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:or(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function mg(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 Ur(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ln(t){try{let e=mt(process.cwd(),".agentx");md(e)||rg(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
21082
- `;ng(mt(e,"board-audit.jsonl"),a)}catch{}}function Pn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var fg=2e3;async function hg(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(),fg),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,c,p,d,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(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let T=await c.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(d&&d.ok){let h=await d.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,ur.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)&&kg(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 gg(t){if(ha)return ha;let e=mt(process.cwd(),".agentx/wiki");return ha=wo({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 xg(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 bg=3e3,vg=6e3,yg=5*6e4,jn=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(bg)),s=await Promise.all(o.map(async i=>{let l=await hg(i.url,i.token,AbortSignal.timeout(vg),e);return e?l:wg(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ga.delete(a));return ga.set(a,r),r}function wg(t,e,a=Date.now()){if(e.reachable&&!e.error)return jn.set(t,{node:e,at:a}),e;let n=jn.get(t);return!n||a-n.at>yg?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function N_(){jn.clear(),ga.clear()}function kg(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 _g(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,c)=>{n||e.write(`event: ${l}
21094
+ `)}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:cr([...y.values()],x=>E.get(x)),unreachable:f});return}if(r==="/api/workflows/required"){let u=()=>({settings:To(),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 Ao(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,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[]}})),_=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($=>gg($)):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")&&hl(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,v,y)=>{if(a.token)return!0;let E=Ma(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 hg(E,v,L,A),Ln({actor:Pn(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 fg(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}Ln({actor:Pn(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});Ln({actor:Pn(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 fg(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),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(h=>h.kind!=="closed"),d=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=d?await e.listAll({sinceDays:c,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=Bn(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 hg(t,e,a,n){let r=qn(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 gg(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:lr(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function xg(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 Xr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ln(t){try{let e=mt(process.cwd(),".agentx");xd(e)||lg(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
21095
+ `;ig(mt(e,"board-audit.jsonl"),a)}catch{}}function Pn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var bg=2e3;async function vg(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(),bg),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,c,p,d,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(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let T=await c.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(d&&d.ok){let h=await d.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,hr.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)&&Tg(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 yg(t){if(ha)return ha;let e=mt(process.cwd(),".agentx/wiki");return ha=Eo({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 wg(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 kg=3e3,_g=6e3,Sg=5*6e4,jn=new Map,ga=new Map;function tt(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(kg)),s=await Promise.all(o.map(async i=>{let l=await vg(i.url,i.token,AbortSignal.timeout(_g),e);return e?l:Eg(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ga.delete(a));return ga.set(a,r),r}function Eg(t,e,a=Date.now()){if(e.reachable&&!e.error)return jn.set(t,{node:e,at:a}),e;let n=jn.get(t);return!n||a-n.at>Sg?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function z_(){jn.clear(),ga.clear()}function Tg(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 Ag(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,c)=>{n||e.write(`event: ${l}
21083
21096
  data: ${JSON.stringify(c)}
21084
21097
 
21085
- `)},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 Sg(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),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,d;try{d=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(k){w(e,502,{error:k.message||"upstream connect failed"});return}if(!d.ok||!d.body){w(e,d.status||502,{error:`upstream HTTP ${d.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=d.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 Eg(t,e,a){let n=Ma(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 Tg(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 c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){w(e,502,{error:c.message||"upstream call failed"})}}async function Ag(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of e.config.dashboard.daemons)i.add(d.url.replace(/\/+$/,""));try{let d=await ba(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of d)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),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let d=await fetch(`${s}${p}`,{headers:c}),m=await d.text();t.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(d){w(t,502,{error:d.message||"upstream fetch failed"})}}async function Cg(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 fd(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function fd(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await ba(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function On(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 Tt(),{...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=yr(e.keysFile);return{store:()=>{let r=Ze();return r?new Vr(r):null},publicKey:()=>wr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function cd(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?Jl({url:a,token:U(t.dashboard,a),operatorKey:Ea(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}.`:On(t).reason;return Zl(t,process.cwd(),n,r)}function Nn(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 fd(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=It({root:process.cwd()}).items.map(pd)}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=ft(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(pd)}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(),d=await Mt({root:process.cwd()},r,o,{laterHours:p.laterHours,by:s,...i});return d.ok?{status:200,body:{ok:!0,message:d.message}}:{status:409,body:{error:d.error}}}let c=ft(l,t);if(!c)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let p=await fetch(`${c.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...c.token?{Authorization:`Bearer ${c.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 Ig(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=Nn(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);!l||!l.reachable||l.stale?i.push("The running tasks could not be read, so no request is shown as working now."):s=id(l.agents);let c=Date.now(),p=null;try{let k=ze(n);k&&(p=[...k.listOpen(),...k.listClosedSince(c-In*864e5,Mn)].map(b=>({record:b,links:k.links(b.id)})))}catch(k){i.push(`Requests could not be read: ${k.message}`)}let d=[];try{d=kr(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(_r(n.root).snoozed).filter(([,k])=>Date.parse(k)>c).map(([k])=>k)),g=ld({now:c,node:e,nodeName:t.node?.name||"this computer",inbox:r,requests:p,cards:d,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 $n=null;function dd(t){return $n?.days!==t&&($n={days:t,store:new wt(process.cwd(),Date.now,t)}),$n.store}function hd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Nn(t);return{store:()=>{let r=Ze();return r?new pt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:Ea(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(/\/+$/,"")),...Mg(t,e,a)}}function Mg(t,e,a){let n=On(t);return{finishAlerts:r=>{if(n.forward)return vr.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}
21086
- ${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 Rg(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=hd(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 c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.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:Tl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Lg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ze();return a?new pt(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Pg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function pd(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 $g=`
21098
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await tt(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 Cg(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),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,d;try{d=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(k){w(e,502,{error:k.message||"upstream connect failed"});return}if(!d.ok||!d.body){w(e,d.status||502,{error:`upstream HTTP ${d.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=d.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 Ig(t,e,a){let n=Ma(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 Mg(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 c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){w(e,502,{error:c.message||"upstream call failed"})}}async function Rg(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of e.config.dashboard.daemons)i.add(d.url.replace(/\/+$/,""));try{let d=await ba(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of d)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),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let d=await fetch(`${s}${p}`,{headers:c}),m=await d.text();t.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(d){w(t,502,{error:d.message||"upstream fetch failed"})}}async function Lg(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 bd(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function bd(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await ba(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function On(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 Tt(),{...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=_r(e.keysFile);return{store:()=>{let r=et();return r?new Zr(r):null},publicKey:()=>Sr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function md(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?Zl({url:a,token:U(t.dashboard,a),operatorKey:Ea(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}.`:On(t).reason;return nc(t,process.cwd(),n,r)}function Nn(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>tt(t,n),async nodePost(n,r,o){let s=await bd(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=It({root:process.cwd()}).items.map(hd)}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=ft(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(hd)}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(),d=await Mt({root:process.cwd()},r,o,{laterHours:p.laterHours,by:s,...i});return d.ok?{status:200,body:{ok:!0,message:d.message}}:{status:409,body:{error:d.error}}}let c=ft(l,t);if(!c)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let p=await fetch(`${c.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...c.token?{Authorization:`Bearer ${c.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 Pg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=Nn(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);!l||!l.reachable||l.stale?i.push("The running tasks could not be read, so no request is shown as working now."):s=pd(l.agents);let c=Date.now(),p=null;try{let k=ze(n);k&&(p=[...k.listOpen(),...k.listClosedSince(c-In*864e5,Mn)].map(b=>({record:b,links:k.links(b.id)})))}catch(k){i.push(`Requests could not be read: ${k.message}`)}let d=[];try{d=Er(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(Tr(n.root).snoozed).filter(([,k])=>Date.parse(k)>c).map(([k])=>k)),g=ud({now:c,node:e,nodeName:t.node?.name||"this computer",inbox:r,requests:p,cards:d,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 $n=null;function fd(t){return $n?.days!==t&&($n={days:t,store:new wt(process.cwd(),Date.now,t)}),$n.store}function vd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Nn(t);return{store:()=>{let r=et();return r?new pt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:Ea(process.cwd())??void 0},snapshot:()=>tt(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(/\/+$/,"")),...$g(t,e,a)}}function $g(t,e,a){let n=On(t);return{finishAlerts:r=>{if(n.forward)return kr.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}
21099
+ ${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 jg(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=vd(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 c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await tt(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:Ml(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Og(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=et();return a?new pt(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Ng(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function hd(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 Dg=`
21087
21100
  You are helping draft a new GitLab issue. Follow these conventions strictly.
21088
21101
 
21089
21102
  Title pattern:
@@ -21115,10 +21128,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
21115
21128
  Shape:
21116
21129
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
21117
21130
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
21118
- `;async function jg(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):
21131
+ `;async function Hg(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):
21119
21132
  - ${r.knownLabels.slice(0,60).join(`
21120
21133
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
21121
- `),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:$g}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),d=Og(p);if(!d||typeof d.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(d.labels)?d.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:d.title.trim(),description:(d.description||"").toString(),labels:m,assigneeUsername:typeof d.assigneeUsername=="string"?d.assigneeUsername:void 0,kind:typeof d.kind=="string"?d.kind:void 0,raw:p}}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 Ng(t){let e=ig(sg(import.meta.url));return mt(e,t)}async function Dg(t){return og(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 gd(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:gd(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 Hg(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 xd(r,a.config)))}async function xd(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=cn(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=ft(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let d=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return d.ok?{nodeId:i.name||i.url,snap:await d.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Mi(n)}async function Bg(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 d=process.env.HOME||"",m=[d&&`${d}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),g=m.find(k=>md(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}
21134
+ `),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:Dg}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),d=Bg(p);if(!d||typeof d.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(d.labels)?d.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:d.title.trim(),description:(d.description||"").toString(),labels:m,assigneeUsername:typeof d.assigneeUsername=="string"?d.assigneeUsername:void 0,kind:typeof d.kind=="string"?d.kind:void 0,raw:p}}function Bg(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 qg(t){let e=pg(dg(import.meta.url));return mt(e,t)}async function zg(t){return cg(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 yd(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:yd(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 Fg(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 wd(r,a.config)))}async function wd(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=cn(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=ft(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let d=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return d.ok?{nodeId:i.name||i.url,snap:await d.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return $i(n)}async function Ug(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 d=process.env.HOME||"",m=[d&&`${d}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),g=m.find(k=>xd(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}
21122
21135
 
21123
21136
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=d=>{i+=d.toString("utf8");let m;for(;(m=i.indexOf(`
21124
21137
  `))>=0;){let g=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
@@ -21126,5 +21139,5 @@ data: ${g.replace(/\n/g," ")}
21126
21139
 
21127
21140
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
21128
21141
 
21129
- `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function ud(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((d,m)=>{let g=[];t.on("data",k=>g.push(k)),t.on("end",()=>d(Buffer.concat(g))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let d=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await d.arrayBuffer());e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(d){w(e,502,{error:`proxy to peer failed: ${d?.message||d}`,target:r})}}function ft(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:gd(n),token:n.dashboardToken||n.token}:null}export{kg as applyAttachSessions,hg as fetchDaemonAgents,cg as handleBoardRequest,N_ as resetLiveCaches,Te as resolveNodeTargets,O_ as startBoardDashboard,wg as withLastGood};
21130
- //# sourceMappingURL=board-dashboard-4KIFLAFO.js.map
21142
+ `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function gd(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((d,m)=>{let g=[];t.on("data",k=>g.push(k)),t.on("end",()=>d(Buffer.concat(g))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let d=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await d.arrayBuffer());e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(d){w(e,502,{error:`proxy to peer failed: ${d?.message||d}`,target:r})}}function ft(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:yd(n),token:n.dashboardToken||n.token}:null}export{Tg as applyAttachSessions,vg as fetchDaemonAgents,mg as handleBoardRequest,z_ as resetLiveCaches,Te as resolveNodeTargets,q_ as startBoardDashboard,Eg as withLastGood};
21143
+ //# sourceMappingURL=board-dashboard-JY4YQ5TM.js.map