agentix-cli 0.151.0 → 0.152.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 (161) hide show
  1. package/dist/{App-WAWZFD66.js → App-NCB3Y5DS.js} +2 -2
  2. package/dist/{ChatApp-TRJIS3O4.js → ChatApp-HOWN5H7Y.js} +2 -2
  3. package/dist/{absorb-eval-CFWLHUTB.js → absorb-eval-JXRNSZII.js} +2 -2
  4. package/dist/agent-DMXUUMEU.js +2 -0
  5. package/dist/{board-dashboard-5V6RHW3E.js → board-dashboard-POWARL34.js} +402 -241
  6. package/dist/board-dashboard-POWARL34.js.map +1 -0
  7. package/dist/{chunk-X6C6U4GL.js → chunk-24QMHUU2.js} +5 -5
  8. package/dist/{chunk-X6C6U4GL.js.map → chunk-24QMHUU2.js.map} +1 -1
  9. package/dist/{chunk-ALE354ZC.js → chunk-7UH3DXAG.js} +2 -2
  10. package/dist/chunk-ADG6NBZY.js +862 -0
  11. package/dist/chunk-ADG6NBZY.js.map +1 -0
  12. package/dist/{chunk-IMITYHBT.js → chunk-CZEBLLZQ.js} +2 -2
  13. package/dist/{chunk-XD7HTMOP.js → chunk-DZUJP6L7.js} +2 -2
  14. package/dist/{chunk-TZZBGWLX.js → chunk-E4V5EADX.js} +6 -6
  15. package/dist/{chunk-XVJXXELY.js → chunk-GI5CY27P.js} +2 -2
  16. package/dist/{chunk-LVS5ESTS.js → chunk-HS7ATV4Z.js} +2 -2
  17. package/dist/{chunk-RGJZV5RY.js → chunk-ILZRO6SN.js} +2 -2
  18. package/dist/{chunk-UG2OF2EI.js → chunk-IVBCCSDR.js} +2 -2
  19. package/dist/{chunk-V3VWYIJ3.js → chunk-JDX7AYIB.js} +2 -2
  20. package/dist/{chunk-PUSBK2OQ.js → chunk-JHAQE46R.js} +46 -46
  21. package/dist/chunk-JHAQE46R.js.map +1 -0
  22. package/dist/chunk-JJOLZPUY.js +35 -0
  23. package/dist/chunk-JJOLZPUY.js.map +1 -0
  24. package/dist/{chunk-2PJKGZWP.js → chunk-JNG3P5V2.js} +2 -2
  25. package/dist/chunk-JNG3P5V2.js.map +1 -0
  26. package/dist/{chunk-2GJQDJBF.js → chunk-LDLRDBAD.js} +2 -2
  27. package/dist/{chunk-DJQIJF4R.js → chunk-LOTCKF22.js} +2 -2
  28. package/dist/{chunk-O7SYQXKS.js → chunk-MTBY46CL.js} +8 -8
  29. package/dist/{chunk-FGJNSYHM.js → chunk-P25TJ4XN.js} +3 -3
  30. package/dist/{chunk-6LFOX6Q5.js → chunk-P4EZJIQ4.js} +257 -256
  31. package/dist/chunk-P4EZJIQ4.js.map +1 -0
  32. package/dist/{chunk-X3T2GCSI.js → chunk-PC24JMEH.js} +2 -2
  33. package/dist/{chunk-EJTKLVIW.js → chunk-PGLTBNGZ.js} +2 -2
  34. package/dist/{chunk-4GXJMHSA.js → chunk-QSNKF5VD.js} +2 -2
  35. package/dist/{chunk-DFGANY25.js → chunk-R4R7EYY3.js} +2 -2
  36. package/dist/{chunk-Q5NLNLD5.js → chunk-RNAKP7WY.js} +2 -2
  37. package/dist/{chunk-L6IW6HWE.js → chunk-SQUTRMKH.js} +23 -20
  38. package/dist/chunk-SQUTRMKH.js.map +1 -0
  39. package/dist/{chunk-C5UTFHPB.js → chunk-TNZBQAUR.js} +2 -2
  40. package/dist/{chunk-Y5MFVVTM.js → chunk-U23LVMMZ.js} +2 -2
  41. package/dist/{chunk-YGDJV4ZZ.js → chunk-UFYKUC4E.js} +2 -2
  42. package/dist/{chunk-CTQ25CUL.js → chunk-VIZVF6KH.js} +2 -2
  43. package/dist/{chunk-ETBDN5WX.js → chunk-XE3CGJV4.js} +2 -2
  44. package/dist/{chunk-UALK4F3W.js → chunk-YBUCVI45.js} +2 -2
  45. package/dist/{chunk-DWXCZRBJ.js → chunk-YJZQRFET.js} +2 -2
  46. package/dist/cli.js +1 -1
  47. package/dist/{client-VT7GT3SK.js → client-6IOWB5AT.js} +2 -2
  48. package/dist/{compaction-FS6XNRLM.js → compaction-PFXWL4H7.js} +3 -3
  49. package/dist/{config-NZS2UTHI.js → config-SHIT5WJE.js} +2 -2
  50. package/dist/{config-mutate-LINLC354.js → config-mutate-6ACI5COM.js} +2 -2
  51. package/dist/config-mutator-LAEX6HOH.js +2 -0
  52. package/dist/{context-planner-3JDA7FNR.js → context-planner-DJB6CKY6.js} +2 -2
  53. package/dist/{contributions-67B3BYLV.js → contributions-N7K6LNL7.js} +2 -2
  54. package/dist/{doctor-FOKX4K2G.js → doctor-T7QAQRCJ.js} +2 -2
  55. package/dist/{follow-up-tool-JOIOYOON.js → follow-up-tool-HQ2GWF4K.js} +2 -2
  56. package/dist/{grants-QXF7N6SS.js → grants-HSLB62EG.js} +2 -2
  57. package/dist/heal-RGM7X2ZG.js +2 -0
  58. package/dist/hub-53IMEYGX.js +2 -0
  59. package/dist/index.d.ts +125 -6
  60. package/dist/index.js +1 -1
  61. package/dist/memory-extract-GHLBXV4H.js +2 -0
  62. package/dist/{program-XFZBG3EI.js → program-LSXONKPW.js} +225 -219
  63. package/dist/program-LSXONKPW.js.map +1 -0
  64. package/dist/{promote-WNYNTGKC.js → promote-626PE5VM.js} +2 -2
  65. package/dist/{providers-55NC2SFN.js → providers-BDJXGHEY.js} +2 -2
  66. package/dist/{query-ZU2DDCEH.js → query-GR3SOD6A.js} +2 -2
  67. package/dist/{query-settings-BXRIJWWO.js → query-settings-6XZHNFXE.js} +2 -2
  68. package/dist/{registry-7BITIEQ2.js → registry-SAY7ROZV.js} +2 -2
  69. package/dist/{request-planner-DLQP2NV6.js → request-planner-DWYXUVF4.js} +2 -2
  70. package/dist/{review-candidates-3BMHLIBW.js → review-candidates-GXWMKZKA.js} +2 -2
  71. package/dist/routing-TB6BBRH4.js +2 -0
  72. package/dist/schedule-tool-EI2SRMZM.js +2 -0
  73. package/dist/{scheduler-SYI5MZ3H.js → scheduler-VOZIMG5F.js} +2 -2
  74. package/dist/{seat-6JF7BYM7.js → seat-H6F6H55Y.js} +2 -2
  75. package/dist/{select-JT4I3JOH.js → select-OUBL6EMZ.js} +2 -2
  76. package/dist/{set-enabled-JRGFKA3S.js → set-enabled-NYJHFXHY.js} +2 -2
  77. package/dist/tool-FWATXW5Q.js +6 -0
  78. package/dist/tool-FWATXW5Q.js.map +1 -0
  79. package/dist/{tool-P6GVYNDO.js → tool-HXFGNBLS.js} +2 -2
  80. package/dist/wiki-PG5ZBOMH.js +2 -0
  81. package/dist/wiki-enrich-BIQZWJRB.js +2 -0
  82. package/package.json +1 -1
  83. package/dist/agent-6KCTPI7E.js +0 -2
  84. package/dist/board-dashboard-5V6RHW3E.js.map +0 -1
  85. package/dist/chunk-2PJKGZWP.js.map +0 -1
  86. package/dist/chunk-5I7NJMK6.js +0 -35
  87. package/dist/chunk-5I7NJMK6.js.map +0 -1
  88. package/dist/chunk-6LFOX6Q5.js.map +0 -1
  89. package/dist/chunk-CBML7UCP.js +0 -861
  90. package/dist/chunk-CBML7UCP.js.map +0 -1
  91. package/dist/chunk-L6IW6HWE.js.map +0 -1
  92. package/dist/chunk-PUSBK2OQ.js.map +0 -1
  93. package/dist/config-mutator-FUMSW5HD.js +0 -2
  94. package/dist/heal-U67X6NIN.js +0 -2
  95. package/dist/hub-QETWDYPD.js +0 -2
  96. package/dist/memory-extract-ATD6YLRK.js +0 -2
  97. package/dist/program-XFZBG3EI.js.map +0 -1
  98. package/dist/routing-FVZCQJ6T.js +0 -2
  99. package/dist/schedule-tool-TDVJHRQX.js +0 -2
  100. package/dist/tool-UDOUNWQT.js +0 -6
  101. package/dist/tool-UDOUNWQT.js.map +0 -1
  102. package/dist/wiki-MTZHDFHK.js +0 -2
  103. package/dist/wiki-enrich-CHR4RCRE.js +0 -2
  104. /package/dist/{App-WAWZFD66.js.map → App-NCB3Y5DS.js.map} +0 -0
  105. /package/dist/{ChatApp-TRJIS3O4.js.map → ChatApp-HOWN5H7Y.js.map} +0 -0
  106. /package/dist/{absorb-eval-CFWLHUTB.js.map → absorb-eval-JXRNSZII.js.map} +0 -0
  107. /package/dist/{agent-6KCTPI7E.js.map → agent-DMXUUMEU.js.map} +0 -0
  108. /package/dist/{chunk-ALE354ZC.js.map → chunk-7UH3DXAG.js.map} +0 -0
  109. /package/dist/{chunk-IMITYHBT.js.map → chunk-CZEBLLZQ.js.map} +0 -0
  110. /package/dist/{chunk-XD7HTMOP.js.map → chunk-DZUJP6L7.js.map} +0 -0
  111. /package/dist/{chunk-TZZBGWLX.js.map → chunk-E4V5EADX.js.map} +0 -0
  112. /package/dist/{chunk-XVJXXELY.js.map → chunk-GI5CY27P.js.map} +0 -0
  113. /package/dist/{chunk-LVS5ESTS.js.map → chunk-HS7ATV4Z.js.map} +0 -0
  114. /package/dist/{chunk-RGJZV5RY.js.map → chunk-ILZRO6SN.js.map} +0 -0
  115. /package/dist/{chunk-UG2OF2EI.js.map → chunk-IVBCCSDR.js.map} +0 -0
  116. /package/dist/{chunk-V3VWYIJ3.js.map → chunk-JDX7AYIB.js.map} +0 -0
  117. /package/dist/{chunk-2GJQDJBF.js.map → chunk-LDLRDBAD.js.map} +0 -0
  118. /package/dist/{chunk-DJQIJF4R.js.map → chunk-LOTCKF22.js.map} +0 -0
  119. /package/dist/{chunk-O7SYQXKS.js.map → chunk-MTBY46CL.js.map} +0 -0
  120. /package/dist/{chunk-FGJNSYHM.js.map → chunk-P25TJ4XN.js.map} +0 -0
  121. /package/dist/{chunk-X3T2GCSI.js.map → chunk-PC24JMEH.js.map} +0 -0
  122. /package/dist/{chunk-EJTKLVIW.js.map → chunk-PGLTBNGZ.js.map} +0 -0
  123. /package/dist/{chunk-4GXJMHSA.js.map → chunk-QSNKF5VD.js.map} +0 -0
  124. /package/dist/{chunk-DFGANY25.js.map → chunk-R4R7EYY3.js.map} +0 -0
  125. /package/dist/{chunk-Q5NLNLD5.js.map → chunk-RNAKP7WY.js.map} +0 -0
  126. /package/dist/{chunk-C5UTFHPB.js.map → chunk-TNZBQAUR.js.map} +0 -0
  127. /package/dist/{chunk-Y5MFVVTM.js.map → chunk-U23LVMMZ.js.map} +0 -0
  128. /package/dist/{chunk-YGDJV4ZZ.js.map → chunk-UFYKUC4E.js.map} +0 -0
  129. /package/dist/{chunk-CTQ25CUL.js.map → chunk-VIZVF6KH.js.map} +0 -0
  130. /package/dist/{chunk-ETBDN5WX.js.map → chunk-XE3CGJV4.js.map} +0 -0
  131. /package/dist/{chunk-UALK4F3W.js.map → chunk-YBUCVI45.js.map} +0 -0
  132. /package/dist/{chunk-DWXCZRBJ.js.map → chunk-YJZQRFET.js.map} +0 -0
  133. /package/dist/{client-VT7GT3SK.js.map → client-6IOWB5AT.js.map} +0 -0
  134. /package/dist/{compaction-FS6XNRLM.js.map → compaction-PFXWL4H7.js.map} +0 -0
  135. /package/dist/{config-NZS2UTHI.js.map → config-SHIT5WJE.js.map} +0 -0
  136. /package/dist/{config-mutate-LINLC354.js.map → config-mutate-6ACI5COM.js.map} +0 -0
  137. /package/dist/{config-mutator-FUMSW5HD.js.map → config-mutator-LAEX6HOH.js.map} +0 -0
  138. /package/dist/{context-planner-3JDA7FNR.js.map → context-planner-DJB6CKY6.js.map} +0 -0
  139. /package/dist/{contributions-67B3BYLV.js.map → contributions-N7K6LNL7.js.map} +0 -0
  140. /package/dist/{doctor-FOKX4K2G.js.map → doctor-T7QAQRCJ.js.map} +0 -0
  141. /package/dist/{follow-up-tool-JOIOYOON.js.map → follow-up-tool-HQ2GWF4K.js.map} +0 -0
  142. /package/dist/{grants-QXF7N6SS.js.map → grants-HSLB62EG.js.map} +0 -0
  143. /package/dist/{heal-U67X6NIN.js.map → heal-RGM7X2ZG.js.map} +0 -0
  144. /package/dist/{hub-QETWDYPD.js.map → hub-53IMEYGX.js.map} +0 -0
  145. /package/dist/{memory-extract-ATD6YLRK.js.map → memory-extract-GHLBXV4H.js.map} +0 -0
  146. /package/dist/{promote-WNYNTGKC.js.map → promote-626PE5VM.js.map} +0 -0
  147. /package/dist/{providers-55NC2SFN.js.map → providers-BDJXGHEY.js.map} +0 -0
  148. /package/dist/{query-ZU2DDCEH.js.map → query-GR3SOD6A.js.map} +0 -0
  149. /package/dist/{query-settings-BXRIJWWO.js.map → query-settings-6XZHNFXE.js.map} +0 -0
  150. /package/dist/{registry-7BITIEQ2.js.map → registry-SAY7ROZV.js.map} +0 -0
  151. /package/dist/{request-planner-DLQP2NV6.js.map → request-planner-DWYXUVF4.js.map} +0 -0
  152. /package/dist/{review-candidates-3BMHLIBW.js.map → review-candidates-GXWMKZKA.js.map} +0 -0
  153. /package/dist/{routing-FVZCQJ6T.js.map → routing-TB6BBRH4.js.map} +0 -0
  154. /package/dist/{schedule-tool-TDVJHRQX.js.map → schedule-tool-EI2SRMZM.js.map} +0 -0
  155. /package/dist/{scheduler-SYI5MZ3H.js.map → scheduler-VOZIMG5F.js.map} +0 -0
  156. /package/dist/{seat-6JF7BYM7.js.map → seat-H6F6H55Y.js.map} +0 -0
  157. /package/dist/{select-JT4I3JOH.js.map → select-OUBL6EMZ.js.map} +0 -0
  158. /package/dist/{set-enabled-JRGFKA3S.js.map → set-enabled-NYJHFXHY.js.map} +0 -0
  159. /package/dist/{tool-P6GVYNDO.js.map → tool-HXFGNBLS.js.map} +0 -0
  160. /package/dist/{wiki-MTZHDFHK.js.map → wiki-PG5ZBOMH.js.map} +0 -0
  161. /package/dist/{wiki-enrich-CHR4RCRE.js.map → wiki-enrich-BIQZWJRB.js.map} +0 -0
@@ -1,4 +1,4 @@
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-CBML7UCP.js";import{a as yo}from"./chunk-5NTWGUSJ.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-X3T2GCSI.js";import{a as Zr}from"./chunk-LNY6N73E.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 Jr,Aa as zr,B as Ct,C as Rr,Ca as Fr,D as ze,Da as Ur,E as Lr,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 xr,ab as Vr,bb as Ot,c as St,d as Ia,db as Yr,e as br,gb as Qr,i as Et,l as nt,n as vr,v as Mr}from"./chunk-PUSBK2OQ.js";import"./chunk-GTJIKXDB.js";import{h as hr,i as gr}from"./chunk-ALE354ZC.js";import{D as yr,F as wr,a as ur,j as mr,k as fr}from"./chunk-5I7NJMK6.js";import{a as H,b as Hr,c as Br,g as qr}from"./chunk-7LN4VKDU.js";import{a as pr}from"./chunk-IMLAPB7G.js";import{g as At}from"./chunk-LQE73AZR.js";import{b as Ar,c as Cr}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import{n as Ir}from"./chunk-X6C6U4GL.js";import"./chunk-LVS5ESTS.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ae,d as kr,e as Ma}from"./chunk-EMGB23H5.js";import{a as Sr,b as qe,d as Er,e as Tr,f as Tt}from"./chunk-YMX3QCV7.js";import{b as _r}from"./chunk-JWDJMFU6.js";import"./chunk-MNG2AMKZ.js";import"./chunk-CTQ25CUL.js";import"./chunk-KP7KDLZ2.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-YGDJV4ZZ.js";import"./chunk-MEFPXHQJ.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-5TTHN7DP.js";import"./chunk-XVJXXELY.js";import{a as ir}from"./chunk-ETBDN5WX.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-XD7HTMOP.js";import"./chunk-DWXCZRBJ.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import{g as tr}from"./chunk-DJQIJF4R.js";import"./chunk-WPNRDEHW.js";import"./chunk-Q5NLNLD5.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-L6IW6HWE.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">
1
+ import{A as xo,B as bo,C as vo,D as yo,H as wo,I as ko,M as Bt,N as To,O as Ao,P as Co,R as Io,S as Mo,a as oo,b as so,c as io,d as lo,j as co,k as po,l as uo,o as Ie,p as mo,q as fo,r as Ht,t as ho,z as go}from"./chunk-ADG6NBZY.js";import{a as _o}from"./chunk-5NTWGUSJ.js";import{a as So,b as Eo}from"./chunk-NZQBS7GN.js";import"./chunk-XVTD6I34.js";import"./chunk-QAWKN2N4.js";import"./chunk-MTX4UPNB.js";import{a as C}from"./chunk-PC24JMEH.js";import{a as eo}from"./chunk-LNY6N73E.js";import{a as ro}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 to,n as ao,o as no}from"./chunk-B2QYMUTD.js";import{$a as Vr,Aa as Fr,B as Ct,C as Lr,Ca as Ur,D as ze,Da as Wr,E as Pr,Ea as Gr,F as It,G as Mt,H as Rt,I as $r,L as jr,M as Or,Ma as Xr,N as Nr,Oa as Ce,Ta as Kr,U,V as Dr,Va as Fe,W as Hr,Wa as Lt,Xa as Pt,Ya as $t,Za as jt,_a as Jr,a as br,ab as Yr,bb as Ot,c as St,d as Ia,db as Qr,e as vr,gb as Zr,i as Et,l as rt,n as yr,v as Rr}from"./chunk-JHAQE46R.js";import"./chunk-GTJIKXDB.js";import{h as gr,i as xr}from"./chunk-7UH3DXAG.js";import{D as wr,F as kr,a as mr,j as fr,k as hr}from"./chunk-JJOLZPUY.js";import{a as H,b as Br,c as qr,g as zr}from"./chunk-7LN4VKDU.js";import{a as ur}from"./chunk-IMLAPB7G.js";import{g as At}from"./chunk-LQE73AZR.js";import{b as Cr,c as Ir}from"./chunk-2D3RYIDU.js";import"./chunk-MRIVENBY.js";import{o as Mr}from"./chunk-24QMHUU2.js";import"./chunk-HS7ATV4Z.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ae,d as _r,e as Ma}from"./chunk-EMGB23H5.js";import{a as Er,b as qe,d as Tr,e as Ar,f as Tt}from"./chunk-YMX3QCV7.js";import{b as Sr}from"./chunk-JWDJMFU6.js";import"./chunk-MNG2AMKZ.js";import"./chunk-VIZVF6KH.js";import"./chunk-KP7KDLZ2.js";import{F as cr,W as wt,X as kt,Y as _t,Z as pe,_ as pr,a as nr,f as rr,g as Aa,h as Ca,l as or,n as sr,o as ir,z as dr}from"./chunk-UFYKUC4E.js";import"./chunk-MEFPXHQJ.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-5TTHN7DP.js";import"./chunk-GI5CY27P.js";import{a as lr}from"./chunk-XE3CGJV4.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-DZUJP6L7.js";import"./chunk-YJZQRFET.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import{g as ar}from"./chunk-LOTCKF22.js";import"./chunk-WPNRDEHW.js";import"./chunk-RNAKP7WY.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-JNG3P5V2.js";import"./chunk-7I7IEX4S.js";import{F as ka,Ja as Zn,K as Pc,Ka as er,L as _a,La as X,M as Sa,Ma as tr,T as $c,Ua as yt,_ as Kn,a as qn,b as zn,ba as Ea,c as Mc,ea as Jn,ga as vt,ha as Vn,ja as Yn,la as Qn,pa as Ta,x as gt,y as Rc}from"./chunk-SQUTRMKH.js";import{a as Fn,b as xt,c as wa,d as Un,h as Wn}from"./chunk-BRK6M6LA.js";import{d as Gn,e as Lc,f as bt,n as Xn}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 Ro(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 Lo(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:Md,scripts:`<script>${z({decayOf:Ra,rankByDecay:Co})}const ICON = ${JSON.stringify(ie)};${Rd}</script>`})}var Md=`
88
+ </div>`,css:jc,scripts:`<script>${z({decayOf:Ra,rankByDecay:Ro})}const ICON = ${JSON.stringify(ie)};${Oc}</script>`})}var jc=`
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
- }`,Rd=String.raw`
364
+ }`,Oc=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 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">
779
+ })();`;function La(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,d),p.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let p=1;p<r.length;p++){let c=r[p].from-r[p-1].to;c<d&&(d=c,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function 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 Po(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 d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(b=>l.startedAt>=b.from&&l.startedAt<=b.to);if(d===-1)continue;let p=n[d],c=p.to-p.from||1,m=(l.startedAt-p.from)/c*100,g=Math.min(Math.max((l.durationMs||0)/c*100,1.2),100-m),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:d,track:0,left:m,width:g,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>Pa(l.runs.filter(c=>c.band===p))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Nc}from"crypto";import{readFileSync as Dc,statSync as Hc}from"fs";import{resolve as Bc,dirname as qc}from"path";import{fileURLToPath as zc}from"url";var $o=new Map;function zt(t){let e=$o.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=qc(zc(import.meta.url)),r=Bc(n,"web",t),o=Hc(r),s=o.size<8e6?Nc("sha1").update(Dc(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return $o.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>",Fc=[["agent","Agent",le.bot],["client","Client",le.user],["project","Project",le.folder],["channel","Channel",le.route],["person","Person",le.user],["node","Node",le.mesh]],jo={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 Oo(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">${Lo[e]}</p>
785
+ <p class="ac-sub" id="sub">${jo[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
- ${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("")}
802
+ ${Fc.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:Hd,scripts:`<script>${z({computeBands:La,packTracks:Pa,buildTimeline:Mo})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(Lo)};${Bd}</script>`})}var Hd=`
822
+ </div>`,css:Uc,scripts:`<script>${z({computeBands:La,packTracks:Pa,buildTimeline:Po})}const ICON = ${JSON.stringify(le)};const SUB = ${JSON.stringify(jo)};${Wc}</script>`})}var Uc=`
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
- `,Bd=String.raw`
908
+ `,Wc=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 $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=`
1027
+ `;function No(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:Gc,scripts:`<script src="${zt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Gc=`
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 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=kr(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
- 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=>!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
1048
+ `;import{createServer as pg}from"http";import{appendFileSync as ug,existsSync as kc,mkdirSync as mg}from"fs";import{readFile as fg}from"fs/promises";import{fileURLToPath as hg}from"url";import{dirname as gg,resolve as mt}from"path";Jn();function We(t,e){if(!t)return"absent";let a=_r(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=Do(t.headers["sec-fetch-mode"]),n.site=Do(t.headers["sec-fetch-site"]),n}function Do(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Jc}from"zlib";var Xc=[[[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",Ho=Math.hypot(ke.width,ke.height)/2/ke.width,Wt={full:.74,safe:.37/Ho,android:.29/Ho,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 Xc.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function Kc(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 Bo(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="${Kc(t,e)}"/></svg>`}var Vc=Ko($a),qo=Ko(ja),zo=new Map;function Ge(t){let e=zo.get(t);return e||(e=Xo({size:t,width:Wt.safe,background:"square"}),zo.set(t,e)),e}var Yc=Bo();function Go(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:Yc}:t==="/favicon.ico"?{type:"image/png",body:Uo(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:Uo(180)}:null}var Fo=new Map;function Uo(t){let e=Fo.get(t);return e||(e=Xo({size:t,width:Wt.full,background:"square"}),Fo.set(t,e)),e}function Xo(t){let{size:e}=t,a=t.background==="mac"?Wo(e,[Qc(e)]):null,n=Wo(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,d=n[l],p=s*r+1+i*4;for(let c=0;c<3;c++)o[p+c]=Math.round(qo[c]+(Vc[c]-qo[c])*d);o[p+3]=Math.round(255*(a?a[l]:1))}return Zc(e,o)}function Qc(t){let e=t/1024,a=100*e,n=924*e,r=185*e,o=[],s=[[n-r,a+r,-90],[n-r,n-r,0],[a+r,n-r,90],[a+r,a+r,180]];for(let[i,l,d]of s)for(let p=0;p<=12;p++){let c=(d+90*p/12)*Math.PI/180;o.push([i+r*Math.cos(c),l+r*Math.sin(c)])}return o}var Na=8;function Wo(t,e){let a=new Float32Array(t*t),n=[];for(let o of e)for(let s=0;s<o.length;s++){let[i,l]=o[s],[d,p]=o[(s+1)%o.length];l!==p&&n.push([i,l,d,p])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Na;s++){let i=o+(s+.5)/Na;r.length=0;for(let[l,d,p,c]of n)(i>=d&&i<c||i>=c&&i<d)&&r.push(l+(i-d)*(p-l)/(c-d));r.sort((l,d)=>l-d);for(let l=0;l+1<r.length;l+=2){let d=Math.max(0,r[l]),p=Math.min(t,r[l+1]);for(let c=Math.floor(d);c<p;c++){let m=Math.min(c+1,p)-Math.max(c,d);m>0&&(a[o*t+c]+=m/Na)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function Ko(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function Zc(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",Jc(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(tp(n)),Buffer.concat([a,n,r])}var ep=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 tp(t){let e=4294967295;for(let a of t)e=ep[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}yt();$c();var Gt=7,ap=["waiting_owner","needs_attention"],np={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=np[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 Jo(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 Vo(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):[],d=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${Sa.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
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 c=new Map;if(s&&p.length){let b=t.prepare(`SELECT l.ref, r.id, r.state, r.evidence FROM request_links l JOIN requests r ON r.id = l.request_id
1050
+ WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${p.map(()=>"?").join(",")})`).all(e,...p.map(S=>S.taskId));for(let S of b)c.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=p.map(b=>({...b,where:b.channel?{label:Xe(b.channel,b.chatId??""),url:a.linkFor?.(b.channel,b.chatId??"")??null}:null,request:c.get(b.taskId)??null})),g=new Set(m.map(b=>b.request?.id).filter(Boolean)),k=[...l.filter(b=>!ap.includes(b.state)),...d].filter(b=>!g.has(b.id));return{open:l,recent:d,runs:m,other:k}}Ta();Lc();var Yo={waiting:0,yours:0,ahead:null};function Qo(t,e,a={}){let n=Gn(t),r=new Map,o=[],s=new Map;for(let i of n){let l=`${i.agentId}\0${i.channel}\0${i.chatId}`,d=s.get(l)??0;s.set(l,d+1);let p=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};p.waiting++,i.person===e&&(p.yours++,p.ahead===null&&(p.ahead=d),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Xe(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:d})),r.set(i.agentId,p)}return{byAgent:r,mine:o}}var rp=4e3;function Zo(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 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=`
1052
+ GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-Gt*864e5).map(r=>r.agent_id)}function es(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 d=n.queue?.get(l)??Yo,p=s.get(l),c=p??i.get(l);if(!c)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:d};let m=o(c.person??null),g=c.status==="error"||c.status==="timeout",k=p?"working":g&&m==="you"?"blocked":"free",b=m==="you"&&c.channel!=="a2a",S=b&&c.channel;return{agentId:l,state:k,by:m,at:p?c.started_at:c.finished_at??c.started_at,text:p||b?c.message_preview??null:null,fullText:b&&p&&String(c.original_message??c.message_preview??"").slice(0,rp)||null,where:S?{label:Xe(c.channel,c.chat_id??""),url:n.linkFor?.(c.channel,c.chat_id??"")??null}:null,queue:d}})}function ts(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function as(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 ns(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 rs(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 os(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 ss(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 is(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 ls(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 ds=`
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
- `,is=`
1367
+ `,cs=`
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
- `,ls=`
1379
+ `,ps=`
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 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">
1383
+ `;var op="<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
- ${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=`
1393
+ ${op}
1394
+ <style>${Ue}${Vt}</style>`}function us(){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 ms=`
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 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>
1427
+ </header>`}var qa=Ha,za=Ba;function fs(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 hs(){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:tp,ageText:Fa,connectionNote:Kt,plainPreview:Jt,agentLine:ts,sentState:as,requestState:ns,summaryLine:rs,freedAgents:os})}${ss}</script>
1442
+ <script>${z({workState:sp,ageText:Fa,connectionNote:Kt,plainPreview:Jt,agentLine:rs,sentState:os,requestState:ss,summaryLine:is,freedAgents:ls})}${ds}</script>
1443
1443
  </body>
1444
- </html>`}function ms(){return`<!doctype html>
1444
+ </html>`}function gs(){return`<!doctype html>
1445
1445
  <html lang="en">
1446
- <head>${qa("Pair this machine \xB7 AgentX")}<style>${is}</style></head>
1446
+ <head>${qa("Pair this machine \xB7 AgentX")}<style>${cs}</style></head>
1447
1447
  <body>
1448
1448
  ${za("This machine is not paired yet")}
1449
1449
  <main class="narrow">
1450
- ${ps(0)}
1450
+ ${fs(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})}${ap}</script>
1467
+ <script>${z({formatPairInput:Xt})}${ip}</script>
1468
1468
  </body>
1469
- </html>`}function fs(){return`<!doctype html>
1469
+ </html>`}function xs(){return`<!doctype html>
1470
1470
  <html lang="en">
1471
- <head>${qa("Waiting for the owner \xB7 AgentX")}<style>${ls}</style></head>
1471
+ <head>${qa("Waiting for the owner \xB7 AgentX")}<style>${ps}</style></head>
1472
1472
  <body>
1473
1473
  ${za("This machine is paired")}
1474
1474
  <main class="narrow">
1475
- ${ps(1)}
1475
+ ${fs(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>${np}</script>
1482
+ <script>${lp}</script>
1483
1483
  </body>
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=`
1484
+ </html>`}function sp(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 ip=`
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
- `,np=`
1528
+ `,lp=`
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 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=`
1539
+ `;function bs(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 vs(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 ys(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",ot="Your project";function ws(){return JSON.stringify({id:"/member?client",name:`${ot} \xB7 AgentX`,short_name:ot,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 dp=`
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 vs(){return`<!doctype html>
1543
+ `;function ks(){return`<!doctype html>
1544
1544
  <html lang="en">
1545
- <head>${Ha(`${rt} \xB7 AgentX`,{manifest:Ua,appTitle:rt})}<style>${Ue}${Vt}${Yt}${rp}</style></head>
1545
+ <head>${Ha(`${ot} \xB7 AgentX`,{manifest:Ua,appTitle:ot})}<style>${Ue}${Vt}${Yt}${dp}</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>`,rt)}
1548
+ <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,ot)}
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:hs,clientRequestState:gs,clientSummary:xs})}${op}</script>
1560
+ <script>${z({ageText:Fa,connectionNote:Kt,plainPreview:Jt,clientSentState:bs,clientRequestState:vs,clientSummary:ys})}${cp}</script>
1561
1561
  </body>
1562
- </html>`}var op=`
1562
+ </html>`}var cp=`
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",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=`
1669
+ `;var Qt="agentx_member",pp=90*86400,up=new Rt,Ts=t=>t.replace(/^\[app\]/,"[member]"),mp=new Re(t=>console.log(Ts(t))),_s=new WeakMap;function fp(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return mp;let e=_s.get(t.log);return e||_s.set(t.log,e=new Re(a=>t.log(Ts(a)))),e}var Ss=null;function st(t,e=X){try{return Ss=e().people}catch{return Ss??t}}async function As(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??up,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return he(e,200,"application/manifest+json",us());if(a===Ua)return he(e,200,"application/manifest+json",ws());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),he(e,200,"text/javascript; charset=utf-8",ms);if(a==="/member/icon-192.png")return he(e,200,"image/png",Ge(192),"public, max-age=86400");if(a==="/member/icon-512.png")return he(e,200,"image/png",Ge(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let c=await xo(t,i);return c.status===200&&e.setHeader("Set-Cookie",Es(c.token)),c.status===429&&e.setHeader("Retry-After",String(c.retryAfter)),_e(e,c.status,c.body)}let l=vo(gp(t),i,go(t));if(!l.ok){if(l.status===401){let c=Wa(t);return fp(r).record(a.slice(0,120),Ut(t,We(Ga(t,Qt),o),c?We(c,o):null)),a==="/member"?he(e,401,"text/html; charset=utf-8",gs()):_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",xs()):_e(e,403,{error:l.error,waiting:!0})}let d=r.people().find(c=>c.id===l.personId),p=d?.role==="client";if(n==="GET"&&a==="/member"){let c=Ga(t,Qt);return c&&!Wa(t)&&e.setHeader("Set-Cookie",Es(c)),he(e,200,"text/html; charset=utf-8",p?ks():hs())}if(n==="GET"&&a==="/api/member/me")return _e(e,200,{person:l.personId,name:d?.name??l.personId,role:d?.role??"member",device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let c=r.db?.()??null;if(!c)return _e(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),g=Vo(c,l.personId,{now:m,linkFor:r.linkFor}),k=(T,h)=>{let u=h instanceof Error?h.message:String(h);/no such table/i.test(u)||r.log?.(`[member] ${T} failed: ${u}`)},b={byAgent:new Map,mine:[]};try{b=Qo(c,l.personId,{linkFor:r.linkFor})}catch(T){k("the line",T)}let S=[];if(p)return _e(e,200,{...hp(g),agents:S});try{let T=Zo(c,d??{id:l.personId},m);S=es(c,l.personId,T,{people:r.people(),linkFor:r.linkFor,queue:b.byAgent})}catch(T){k("agent cards",T)}return _e(e,200,{...g,agents:S,queued:b.mine})}return _e(e,404,{error:"not found"})}function hp(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 Es(t){return`${Qt}=${t}; Path=/; Max-Age=${pp}; HttpOnly; Secure; SameSite=Lax`}function gp(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))}Mc();var Cs='/*! 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 Os,writeFileSync as Ns,rmSync as bb,mkdirSync as kp,copyFileSync as _p,readdirSync as Sp}from"fs";import{resolve as Je}from"path";Rc();function Ms(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 Is=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Rs(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 Ls(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:Is(t?.chats),senders:Is(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 Ps(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 $s(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 js(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+bp()+to,css:yp,scripts:`${e}<script>${ao}
1670
+ ${no}
1671
+ ${xp}
1672
+ ${wp}</script>`})}var xp=`
1673
1673
  (function(){
1674
1674
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1675
1675
  async function voiceMissing() {
@@ -1763,8 +1763,8 @@ ${gp}</script>`})}var up=`
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 mp(){let t=Br().business?`<button data-tab="business">Business</button>
1767
- `:"";return fp.replace("__BUSINESS_TABS__",t)}var fp=`
1766
+ })();`;function bp(){let t=qr().business?`<button data-tab="business">Business</button>
1767
+ `:"";return vp.replace("__BUSINESS_TABS__",t)}var vp=`
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 @@ ${gp}</script>`})}var up=`
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
- `,hp=`
2462
+ `,yp=`
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
- `,gp=`
2670
+ `,wp=`
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 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:yr(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}
5639
+ `;function Ds(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(js({peers:a,localToken:n}))}async function Hs(t,e){let a=Ja();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Bs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Dp(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Ep(t),r={"GET /api/admin/state":()=>Ap(),"POST /api/admin/agents":()=>Pp(n),"PATCH /api/admin/agents":()=>$p(n),"DELETE /api/admin/agents":()=>jp(n),"POST /api/admin/agents/access":()=>Cp(n),"POST /api/admin/channels/telegram":()=>Op(n),"DELETE /api/admin/channels/telegram":()=>su(n),"POST /api/admin/channels/telegram/toggle":()=>iu(n),"POST /api/admin/crons":()=>lu(n),"DELETE /api/admin/crons":()=>du(n),"POST /api/admin/config/raw":()=>cu(n),"GET /api/admin/tokens":()=>Ip(),"POST /api/admin/tokens":()=>Mp(n),"DELETE /api/admin/tokens":()=>Rp(n),"POST /api/admin/agents/test":()=>Lp(n),"POST /api/admin/agents/integrations":()=>Up(n),"DELETE /api/admin/agents/integrations":()=>Wp(n),"PATCH /api/admin/agents/integrations":()=>Gp(n),"PATCH /api/admin/channels/telegram":()=>Np(n),"POST /api/admin/channels/slack":()=>Zp(n),"POST /api/admin/channels/slack/toggle":()=>eu(n),"POST /api/admin/channels/discord":()=>tu(n),"POST /api/admin/channels/discord/toggle":()=>au(n),"POST /api/admin/channels/gitlab":()=>nu(n),"POST /api/admin/channels/gitlab/toggle":()=>ru(n),"POST /api/admin/channels/request-status":()=>ko(n),"GET /api/admin/channels/whatsapp/state":()=>Ke("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Ke("/webrtc/history"),"POST /api/admin/actions":()=>_u(n),"DELETE /api/admin/actions":()=>Su(n),"POST /api/admin/actions/run":()=>Eu(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":()=>ou(n),"POST /api/admin/webhooks":()=>Xp(n),"PATCH /api/admin/webhooks":()=>Kp(n),"DELETE /api/admin/webhooks":()=>Qp(n),"POST /api/admin/whatsapp-triage":()=>Rs(n),"POST /api/admin/whatsapp-triage/rules":()=>Ls(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Ps(n),"DELETE /api/admin/whatsapp-triage/rules":()=>$s(n),"POST /api/admin/mesh/peers":()=>Jp(n),"DELETE /api/admin/mesh/peers":()=>Vp(n),"POST /api/admin/mesh/toggle":()=>Yp(n),"GET /api/admin/files":()=>Hp(t),"GET /api/admin/files/read":()=>Bp(t),"PUT /api/admin/files":()=>qp(n),"POST /api/admin/files/skill":()=>zp(n),"DELETE /api/admin/files/skill":()=>Fp(n),"POST /api/admin/business/orgchart":()=>pu(n),"DELETE /api/admin/business/orgchart":()=>uu(n),"POST /api/admin/business/project":()=>mu(n),"DELETE /api/admin/business/project":()=>gu(n),"POST /api/admin/business/client":()=>fu(n),"DELETE /api/admin/business/client":()=>hu(n),"POST /api/admin/business/contact":()=>xu(n),"DELETE /api/admin/business/contact":()=>bu(n),"POST /api/admin/boards":()=>vu(n),"DELETE /api/admin/boards":()=>yu(n),"POST /api/admin/boards/columns":()=>wu(n),"DELETE /api/admin/boards/columns":()=>ku(n),"POST /api/admin/notifications":()=>Cu(n),"POST /api/admin/wiki/curator":()=>Au(n),"POST /api/admin/screen":()=>Mu(n),"POST /api/admin/wiki-notes":()=>Iu(n),"GET /api/admin/wiki-notes/list":()=>Ke("/wiki/notes?status=all&limit=20"),"POST /api/admin/webhooks/triggers":()=>Ru(n),"POST /api/admin/mesh/health":()=>Tu(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 Ep(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 Tp(t){let e=Je(process.cwd(),t);if(!ea(e))return[];let a=[];for(let n of Sp(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Os(Je(e,n.name),"utf-8")))}catch{}return a}function Ja(){let t=Je(process.cwd(),"agentx.json");return ea(t)?JSON.parse(Os(t,"utf-8")):null}function Ap(){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})),d=Array.isArray(t.webhooks)?t.webhooks.map(h=>({id:h.id,source:h.source,agentId:h.agentId,secretEnv:h.secretEnv||"",description:h.description||"",enabled:h.enabled!==!1,triggers:h.triggers&&typeof h.triggers=="object"?h.triggers:{},defaultWorkflow:h.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(h=>({url:h.url,name:h.name,hasToken:!!h.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},c=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},g={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},k=t.notifications||{},b={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:wr(k.local),ntfy:To(t.channels?.ntfy)},S=[];try{S=Tp(".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:wo(t),whatsappTriage:Ms(t),crons:l,webhooks:d,mesh:p,daemonUrl:c,nodeName:t.node?.name,business:g,boards:T,notifications:b,screen:Qr(t.screen),wikiNotes:So(t.wikiNotes),actions:S,wikiCurator:Fs(t)}}function Cp(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 Ip(){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 Mp(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 Rp(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 Lp(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function Pp(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=zs(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=Je(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let c={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(c.model=o),s&&(c.systemPrompt=s.slice(0,400)),p.agents[e]=c,`added agent "${e}"`}),d=Je(i,"CLAUDE.md");if(!ea(d))try{kp(i,{recursive:!0}),Ns(d,`# ${a}
5640
5640
 
5641
5641
  ${s||"You are "+a+"."}
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-SYI5MZ3H.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=wr(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>
5642
+ `)}catch{}return{summary:l}}function $p(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=zs(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 jp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=C(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function Op(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=C(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Np(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 Dp(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 it(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 Hp(t){let e=Ka(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Fe(it(e));return{agentId:e,...a}}function Bp(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(it(e),a)}function qp(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(it(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function zp(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(it(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Fp(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(it(e),a);return{summary:`removed skill "${a}"`,...n}}function Up(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Wp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Gp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var qs=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Xp(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(!qs.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(c=>c.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Kp(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"&&qs.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 Jp(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=C(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function Vp(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=C(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function Yp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function Qp(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 Zp(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 eu(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 tu(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 au(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 nu(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 ru(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 ou(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-VOZIMG5F.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 su(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 iu(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 lu(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 du(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 cu(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=Zn.safeParse(er(a)),r=n.success?tr(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{_p(o,s)}catch{}Ns(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 zs(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function pu(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function uu(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 mu(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 fu(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 hu(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 gu(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 xu(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 bu(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 vu(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(c=>c.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let c=l.boards[d];return l.boards[d]={...c,...p,columns:c.columns,labels:c.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function yu(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 wu(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(c=>c.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let p=l.columns.findIndex(c=>c.id===a);return p>=0?(l.columns[p]={...l.columns[p],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function ku(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 _u(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 Su(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 Eu(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 Tu(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 Fs(t){let e=t?.wiki?.curator||{};return{enabled:e.enabled!==!1,agent:typeof e.agent=="string"?e.agent:""}}function Au(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=Fs(a);return`wiki.curator ${n.enabled?"on":"off"}, answered by ${n.agent||"the page owner"}`});return{summary:e}}async function Cu(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=kr(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=Ao(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 Iu(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=>Eo(n,e));return{summary:a}}async function Mu(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Zr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ru(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 $u}from"path";function Us(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:Au,scripts:`${e}<script>${Cu}</script>`})}var Au=`
5698
+ </section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Lu,scripts:`${e}<script>${Pu}</script>`})}var Lu=`
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; }`,Cu=`
5802
+ details[open] summary { margin-bottom: 8px; }`,Pu=`
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 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=`
6022
+ `;function Gs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Us({peers:a,localToken:n}))}async function Xs(t,e,a){try{let n=t.method==="GET"?void 0:await Fu(t),r=ju(),o={"GET /api/admin/graph/state":()=>Ou(r),"POST /api/admin/graph/classifications/approve":()=>Nu(r,n),"POST /api/admin/graph/classifications/reject":()=>Du(r,n),"POST /api/admin/graph/nodes":()=>Hu(r,n),"PATCH /api/admin/graph/nodes":()=>Bu(r,n),"DELETE /api/admin/graph/nodes":()=>qu(r,n),"PUT /api/admin/graph/schema":()=>zu(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 ju(){let t=X(),e=$u(process.cwd(),t.graph.baseDir);return new ar({baseDir:e})}function Ou(t){let e=X(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function Nu(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ks(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 Du(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Ks(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Ks(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 Hu(t,e){let a=Ws(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Ws(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 Bu(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 qu(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function zu(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 Ws(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 Fu(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 Js=`
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>
@@ -6051,7 +6051,7 @@ refresh();
6051
6051
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6052
6052
  </form>
6053
6053
  </details>
6054
- </section>`,Xs=`
6054
+ </section>`,Vs=`
6055
6055
  .apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
6056
6056
  .apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
6057
6057
  .apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
@@ -6085,7 +6085,7 @@ refresh();
6085
6085
  .apv__loop .is-failed, .apv__loop .is-unverified { color: var(--ax-amber-ink); }
6086
6086
  .apv__loop .is-verified { color: var(--ax-ok, inherit); }
6087
6087
  .apv__stalled { color: var(--ax-err); }
6088
- `,Ks=`
6088
+ `,Ys=`
6089
6089
  (function(){
6090
6090
  var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
6091
6091
  function $(id){ return document.getElementById(id); }
@@ -6144,8 +6144,10 @@ function item(r){
6144
6144
  '<div class="apv__meta"><span class="apv__state is-' + esc(r.state) + '">' + esc(STATE[r.state] || r.state) + '</span>' +
6145
6145
  '<span class="apv__with">With <b>' + esc(agentName(r.agentId)) + '</b></span>' +
6146
6146
  '<span>' + esc(when(r.createdAt)) + '</span><span>' + esc(r.channel) + '</span><code>' + esc(r.id) + '</code></div>' +
6147
- '<p class="apv__title" dir="auto">' + esc(r.summary) + '</p>' + why + loop(r) + plan(r.plan) +
6148
- more(r.loop && r.loop.promise ? 'What ' + agentName(r.agentId) + ' promised' : r.channel === 'voice' ? 'What you said' : 'What you asked', r.textHtml) +
6147
+ '<p class="apv__title" dir="auto">' + esc(r.summary) + '</p>' +
6148
+ (r.needed && r.state !== 'waiting_owner' ? '<p class="apv__rec apv__need" dir="auto"><b>Needed from you:</b> ' + esc(r.needed) + '</p>' : '') +
6149
+ why + loop(r) + plan(r.plan) +
6150
+ more(r.loop && r.loop.promise ? 'What ' + agentName(r.agentId) + ' promised' : 'You said', r.textHtml) +
6149
6151
  more('Your last reply', r.ownerNoteHtml) +
6150
6152
  (r.lastAnswer ? more('Last answer from ' + agentName(r.lastAnswer.agentId) + ' (' + when(r.lastAnswer.at) + ')', r.lastAnswer.html) : '') +
6151
6153
  '<div class="apv__reply">' +
@@ -6299,7 +6301,7 @@ function busy(){
6299
6301
  }
6300
6302
  setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
6301
6303
  })();
6302
- `;function Js(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6304
+ `;function Qs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6303
6305
  <header class="apv__head">
6304
6306
  <div>
6305
6307
  <h1>Approvals</h1>
@@ -6321,7 +6323,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
6321
6323
  <ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
6322
6324
  <p id="apv-snoozed" class="apv__foot"></p>
6323
6325
 
6324
- ${Gs}
6326
+ ${Js}
6325
6327
 
6326
6328
  <details class="apv__settings" id="apv-settings">
6327
6329
  <summary>Settings: expiry, later, daily digest</summary>
@@ -6336,7 +6338,7 @@ ${Gs}
6336
6338
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6337
6339
  </form>
6338
6340
  </details>
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=`
6341
+ </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Uu+Vs,scripts:`${e}<script>${Wu}</script><script>${Ys}</script>`})}var Uu=`
6340
6342
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
6341
6343
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
6342
6344
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -6393,7 +6395,7 @@ ${Gs}
6393
6395
  @media (max-width: 560px) {
6394
6396
  .apv__acts .ax-btn { flex: 1 1 0; }
6395
6397
  }
6396
- `,Bu=`
6398
+ `,Wu=`
6397
6399
  (function(){
6398
6400
  var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
6399
6401
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
@@ -6617,7 +6619,7 @@ $('apv-form').addEventListener('submit', async function(ev){
6617
6619
  load();
6618
6620
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within, .apv__item[data-touched]')) load(); }, 60000);
6619
6621
  })();
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=>fr(m,o,Lr(n),c)):[],d=Object.fromEntries(ur.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 Rr(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."})+`
6622
+ `;import{existsSync as Gu,readFileSync as Xu}from"fs";Pc();var xe="/api/admin/approvals/requests";function Zs(t){let e=lr(t);if(!Gu(e))return[];try{let a=JSON.parse(Xu(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 Ku(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Ku(t,e,a,n){if(t==="GET"&&e===xe){let o=ze(n),s=Zs(n.configPath),i=Ct(n.configPath),l=new Set(s.map(m=>m.id)),d={staleAfterHours:i.staleAfterHours,now:n.now??Date.now(),isAgent:m=>l.has(m)},p=o?o.listOpen().map(m=>hr(m,o,Pr(n),d)):[],c=Object.fromEntries(mr.map(m=>[m,0]));for(let m of p)m.stall&&c[m.stall.group]++;return{status:200,body:{items:p,agents:s,settings:i,stalled:c}}}let r=e===`${xe}/reply`?"reply":e===`${xe}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=ze(n),d=l?.get(o);if(!l||!d||d.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?d.agentId:typeof a.agentId=="string"?a.agentId:"",c=Zs(n.configPath).find(g=>g.id===p);if(r==="handoff"&&!c)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!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=c?.name??p;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${xe}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=ze(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=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: ${d||"checked by hand"}`:d||"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=c=>{let m=a[c];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${c} 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(c=>c!==void 0)&&(o.plans=i);let l={},d=Ve(a.checkKinds);if(d){let c=d.filter(m=>!ka.includes(m));if(c.length)throw new Error(`unknown check ${c.join(", ")}: use ${ka.join(", ")}`);l.enabled=d}l.checkEveryMinutes=s("checkEveryMinutes"),Object.values(l).some(c=>c!==void 0)&&(o.checkers=l);let p=await Lr(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 Ju=["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 Vu(t){let e=t.choice;return{...typeof e=="number"||typeof e=="string"&&e.trim()?{choice:typeof e=="string"?e.trim():e}:{},...typeof t.text=="string"&&t.text.trim()?{text:t.text}:{}}}function ei(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Qs({peers:e,localToken:a}))}async function ti(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:"",d=i.action;if(!l||!Ju.includes(d))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Ie(s.configPath),c=await Mt(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)",...Vu(i)});return c.ok?(te(e,200,{ok:!0,message:c.message}),!0):(te(e,409,{error:c.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await aa(t),l=jr(s,typeof i.key=="string"?i.key:"",!!Ie(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await aa(t),l={},d=c=>{let m=i[c];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${c} must be a positive number`);return m}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let c=i.destination.trim();if(!c)l.destination=null;else{let m=mo(c);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await fo(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 ai(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."})+`
6621
6623
  <div class="pp">
6622
6624
  <div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
6623
6625
  <section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
@@ -6630,7 +6632,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6630
6632
  </ol>
6631
6633
  </section>
6632
6634
  <ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
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=`
6635
+ </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Yu,scripts:`${e}<script>${Qu}</script>`})}var Yu=`
6634
6636
  .pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
6635
6637
  .pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
6636
6638
  .pp-msg.is-bad { color: var(--ax-red-ink); }
@@ -6671,7 +6673,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6671
6673
  .pp-text { overflow-wrap: anywhere; }
6672
6674
  .pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
6673
6675
  @media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
6674
- `,Xu=`
6676
+ `,Qu=`
6675
6677
  (function () {
6676
6678
  var list = document.getElementById('pp-list');
6677
6679
  var msg = document.getElementById('pp-msg');
@@ -6809,7 +6811,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6809
6811
  load();
6810
6812
  setInterval(load, 30000);
6811
6813
  })();
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">
6814
+ `;var Za="/api/admin/people";function Zu(t,e){let a=bo(t,e);return a?{...e,answer:a}:e}function em(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 tm(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&em(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 am=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function ni(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(ai({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return be(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=d=>n.members.devices(d).map(p=>Zu(n.root,p)),s=()=>tm(n.people(),o());if(r==="GET"&&a===Za){let d=s();return be(e,200,{people:d,paired:d.reduce((p,c)=>p+c.machines.active+c.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let d=s().find(g=>g.id===i[1]);if(!d)return be(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),c=[],m=[];try{p&&(c=ho(p,d.id))}catch{}try{p&&(m=Ht(p,d.id,20))}catch{}return be(e,200,{person:d,devices:o(d.id).sort(am),requests:c,runs:m,database:!!p}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,d,p]=l,c=n.members.byToken(p);if(!c||c.personId!==d)return be(e,404,{error:"no such machine for this person"}),!0;if(c.state==="removed")return be(e,409,{error:"this machine's access has already ended"}),!0;let m=yo({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 im}from"path";import{existsSync as lm}from"fs";import dm from"better-sqlite3";var ri=new WeakSet;function nm(t,e,a={}){if(ri.has(t))return;ri.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let d=i[l].bind(i);i[l]=(...p)=>{let c=r();try{return d(...p)}finally{let m=r()-c;m>=n&&e({sql:s,ms:m})}}}return i}}function rm(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){nm(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${rm(a)}`))}function oi(t={}){let e=`<div class="ax-obs">
6813
6815
  <header class="ax-obs__head">
6814
6816
  <h1>Health</h1>
6815
6817
  <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>
@@ -6931,7 +6933,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6931
6933
  </div>
6932
6934
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
6933
6935
  </section>
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=`
6936
+ </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:om,scripts:`<script>${sm}</script>`})}var om=`
6935
6937
  .ax-obs { padding: 16px 24px; }
6936
6938
  .ax-obs__head { margin-bottom: 16px; }
6937
6939
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -7048,7 +7050,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7048
7050
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
7049
7051
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
7050
7052
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
7051
- `,tm=`
7053
+ `,sm=`
7052
7054
  (function(){
7053
7055
  var panes = document.querySelectorAll('.ax-obs__pane');
7054
7056
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -7432,23 +7434,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7432
7434
 
7433
7435
  load(current);
7434
7436
  })();
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=`
7437
+ `;var li={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 di(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=li[di(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 cm(){let t=im(process.cwd(),".agentx/db.sqlite");if(!lm(t))return null;try{let e=new dm(t,{readonly:!0,fileMustExist:!0});return Se(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function ci(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oi({peers:a}))}function pm(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 pi(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=cm();if(!r)return ve(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=pm(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7436
7438
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
7437
7439
  FROM route_traces
7438
7440
  ${i.length?"WHERE "+i.join(" AND "):""}
7439
7441
  ORDER BY at DESC LIMIT @limit
7440
- `,p=r.db.prepare(c).all(l);return ve(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
7442
+ `,p=r.db.prepare(d).all(l);return ve(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7441
7443
  SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
7442
7444
  FROM rotations
7443
7445
  ${i.length?"WHERE "+i.join(" AND "):""}
7444
7446
  ORDER BY rotated_at DESC LIMIT @limit
7445
- `,p=r.db.prepare(c).all(l);return ve(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
7447
+ `,p=r.db.prepare(d).all(l);return ve(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
7446
7448
  SELECT started_at, agent_id, channel, message_preview, error
7447
7449
  FROM task_history
7448
7450
  WHERE ${i.join(" AND ")}
7449
7451
  ORDER BY started_at DESC LIMIT @limit
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(`
7452
+ `,c=r.db.prepare(d).all(l).map(m=>({...m,plain:ui(m.error)}));return ve(e,200,{rows:c}),!0}if(n==="summary"||n==="overview")return ve(e,200,um(r.db)),!0;if(n==="activity")return ve(e,200,mm(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=si(i.searchParams.get("range"));return ve(e,200,ii(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=si(i.searchParams.get("range")),d=ii(r.db,l),p=fm(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return ve(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function ui(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(`
7453
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function um(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),c=x=>p.length?p[Math.min(p.length-1,Math.floor(p.length*x))].duration_ms:0,m=c(.5),g=c(.95),b=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((x,A)=>x+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(`
7452
7454
  SELECT agent_id,
7453
7455
  COUNT(*) AS tasks,
7454
7456
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -7471,7 +7473,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7471
7473
  FROM task_history
7472
7474
  WHERE status='error' AND started_at >= ?
7473
7475
  ORDER BY started_at DESC LIMIT 5
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(`
7476
+ `).all(o).map(x=>({...x,plain:ui(x.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:m,p95DurationMs:g,spendToday:b,spendDelta:b-S,idleAgentCount:v.length},perAgent:T,perChannel:h,idleAgents:v,recentErrors:E}}function mm(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(`
7475
7477
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
7476
7478
  COUNT(*) AS tasks,
7477
7479
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -7498,7 +7500,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7498
7500
  WHERE started_at >= @since
7499
7501
  GROUP BY agent_id
7500
7502
  ORDER BY tasks_24h DESC, tasks_7d DESC
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(`
7503
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function si(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 ii(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7502
7504
  SELECT day, agent_id, model,
7503
7505
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
7504
7506
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -7506,37 +7508,37 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7506
7508
  FROM usage_daily
7507
7509
  ${a}
7508
7510
  ORDER BY day
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+`
7511
+ `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,c=0,m=0,g=0,k=0,b=0,S=0,T={},h={};for(let _ of n){let R=en(_),j=di(_.model),$=li[j],O=(_.tier2_input_tokens||0)/1e6*$.input*.5+(_.tier2_output_tokens||0)/1e6*$.output*.5+(_.tier2_cache_read_tokens||0)/1e6*$.cacheRead*.5+(_.tier2_cache_create_tokens||0)/1e6*$.cacheCreate*.5,W=(_.input_tokens||0)+(_.tier2_input_tokens||0),ce=(_.output_tokens||0)+(_.tier2_output_tokens||0),Q=(_.cache_read_tokens||0)+(_.tier2_cache_read_tokens||0),oe=(_.cache_create_tokens||0)+(_.tier2_cache_create_tokens||0);c+=R,_.day>=s&&(p+=R,k+=_.tasks||0),_.day>=i&&_.day<s&&(S+=R,b+=_.tasks||0),_.day===r&&(l+=R),_.day===o&&(d+=R),_.day===r&&(m+=O),_.day>=s&&(g+=O);let Z=T[_.day]||(T[_.day]={date:_.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=_.tasks||0,Z.input+=W,Z.output+=ce,Z.cacheRead+=Q,Z.cacheCreate+=oe,Z.cost+=R,Z.tier2+=O;let F=Z.agents[_.agent_id]||(Z.agents[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});F.tasks+=_.tasks||0,F.cost+=R,F.tier2+=O,F.input+=W,F.output+=ce,F.cacheRead+=Q,F.cacheCreate+=oe,_.model&&(F.model=_.model);let N=h[_.agent_id]||(h[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});N.tasks+=_.tasks||0,N.cost+=R,N.tier2+=O,N.input+=W,N.output+=ce,N.cacheRead+=Q,N.cacheCreate+=oe,_.model&&(N.model=_.model)}let u=Object.values(T).sort((_,R)=>_.date<R.date?-1:1),f=0,v=0,y=0,E=0,x=0,A=0;for(let _ of u)f+=_.tasks,v+=_.input,y+=_.output,E+=_.cacheRead,x+=_.cacheCreate,A+=_.cost;let L=Object.entries(h).map(([_,R])=>({agent_id:_,...R,tokens:R.input+R.output+R.cacheRead+R.cacheCreate})).sort((_,R)=>R.cost-_.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:c,tier2Today:m,tier2_7d:g,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:f,tokensRange:v+y+E+x,cacheHitRange:E+v>0?E/(E+v):0,costPerTaskRange:f>0?A/f:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:b>0?(k-b)/b:0},days:u,perAgent:L}}function fm(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+`
7510
7512
  `+a.join(`
7511
7513
  `)+`
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(`
7514
+ `}import{resolve as hm}from"path";import{existsSync as gm}from"fs";import xm from"better-sqlite3";function bm(){let t=hm(process.cwd(),".agentx/intent/ledger.sqlite");if(!gm(t))return null;try{let e=new xm(t,{readonly:!0,fileMustExist:!0});return Se(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-mi>6e4&&(mi=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var mi=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function vm(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 fi(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=bm();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=vm(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let c=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${c} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,b=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${c}`).get({since:s}).n,T=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${c} GROUP BY source ORDER BY n DESC`).all({since:s}),h=r.db.prepare(`
7513
7515
  SELECT COUNT(*) AS n FROM intent_decisions d
7514
7516
  LEFT JOIN intent_resolutions r
7515
7517
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7516
7518
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
7517
- `).get().n;return Le(e,200,{since:s??null,eventsBySource:g,totalDecisions:k,decisionsByOutcome:b,totalDivergences:S,divergencesBySource:T,inFlight:h}),!0}if(n==="events"){let d=[],m={limit:p};s!==void 0&&(d.push("ts >= @since"),m.since=s),i&&(d.push("source = @source"),m.source=i),l&&(d.push("project = @project"),m.project=l);let g=`
7519
+ `).get().n;return Le(e,200,{since:s??null,eventsBySource:g,totalDecisions:k,decisionsByOutcome:b,totalDivergences:S,divergencesBySource:T,inFlight:h}),!0}if(n==="events"){let c=[],m={limit:p};s!==void 0&&(c.push("ts >= @since"),m.since=s),i&&(c.push("source = @source"),m.source=i),l&&(c.push("project = @project"),m.project=l);let g=`
7518
7520
  SELECT id, ts, source, source_event_id, project, subject, intent
7519
7521
  FROM intent_events
7520
- ${d.length?"WHERE "+d.join(" AND "):""}
7522
+ ${c.length?"WHERE "+c.join(" AND "):""}
7521
7523
  ORDER BY ts DESC LIMIT @limit
7522
- `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="divergences"){let d=[],m={limit:p};s!==void 0&&(d.push("ts >= @since"),m.since=s),i&&(d.push("source = @source"),m.source=i);let g=`
7524
+ `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="divergences"){let c=[],m={limit:p};s!==void 0&&(c.push("ts >= @since"),m.since=s),i&&(c.push("source = @source"),m.source=i);let g=`
7523
7525
  SELECT ts, source, decided_by,
7524
7526
  legacy_agent_id, legacy_outcome, legacy_reason,
7525
7527
  ledger_agent_id, ledger_outcome, ledger_reason,
7526
7528
  event_id
7527
7529
  FROM intent_divergences
7528
- ${d.length?"WHERE "+d.join(" AND "):""}
7530
+ ${c.length?"WHERE "+c.join(" AND "):""}
7529
7531
  ORDER BY ts DESC LIMIT @limit
7530
- `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="active"){let d=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:p};i&&(d.push("e.source = @source"),m.source=i);let g=`
7532
+ `;return Le(e,200,{rows:r.db.prepare(g).all(m)}),!0}if(n==="active"){let c=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:p};i&&(c.push("e.source = @source"),m.source=i);let g=`
7531
7533
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
7532
7534
  d.decided_by, d.decided_at, d.agent_id, d.reason
7533
7535
  FROM intent_decisions d
7534
7536
  JOIN intent_events e ON e.id = d.event_id
7535
7537
  LEFT JOIN intent_resolutions r
7536
7538
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7537
- WHERE ${d.join(" AND ")}
7539
+ WHERE ${c.join(" AND ")}
7538
7540
  ORDER BY d.decided_at DESC LIMIT @limit
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">
7541
+ `;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 hi(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7540
7542
  <header class="ax-led__head">
7541
7543
  <h1>Intent ledger</h1>
7542
7544
  <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>
@@ -7741,7 +7743,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7741
7743
  }
7742
7744
  load();
7743
7745
  })();
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">
7746
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function gi(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7745
7747
  <header class="ax-cost__head">
7746
7748
  <div>
7747
7749
  <h1>Cost</h1>
@@ -8314,7 +8316,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8314
8316
  load();
8315
8317
  setInterval(load, 30000);
8316
8318
  })();
8317
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function fi(t={}){let e=`<div class="ax-pj__root">
8319
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function xi(t={}){let e=`<div class="ax-pj__root">
8318
8320
  <aside class="ax-pj__list">
8319
8321
  <header>
8320
8322
  <h2>Projects</h2>
@@ -8341,7 +8343,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8341
8343
  </header>
8342
8344
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
8343
8345
  </section>
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=`
8346
+ </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ym,scripts:`<script>${wm}</script>`})}var ym=`
8345
8347
  .ax-pj__root {
8346
8348
  display: grid;
8347
8349
  grid-template-columns: 360px 1fr;
@@ -8528,7 +8530,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8528
8530
  }
8529
8531
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
8530
8532
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
8531
- `,gm=`
8533
+ `,wm=`
8532
8534
  (function(){
8533
8535
  const $ = (sel) => document.querySelector(sel);
8534
8536
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -9178,9 +9180,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
9178
9180
  load();
9179
9181
  });
9180
9182
  })();
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 br(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}
9183
+ `;import{resolve as on,join as Nm}from"path";import{existsSync as sn,readdirSync as Dm,readFileSync as Hm}from"fs";import Bm from"better-sqlite3";var vi=String.raw`[\w.-]+(?:/[\w.-]+)+`,km=new RegExp(`^(?:chat:)?(${vi}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),_m=new RegExp(`^\\[(?:GitLab|GitHub) (${vi}) `);function bi(t){if(!t)return null;let e=t.match(km);return e?e[1]:null}function tn(t){if(!t)return null;let e=t.trimStart().match(_m);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():bi(typeof n?.chatId=="string"?n.chatId:null)??bi(e)??tn(a)}function Sm(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 Em=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Tm=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Am=t=>/^issue/i.test(t)?"issue":"mr";function Cm(t){let e=t.subject.match(Em)??t.inputPreview.trimStart().match(Tm);return e?{kind:Am(e[1]),n:Number(e[2])}:null}function Im(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 yi(t){if(!Sm(t.projectId))return[];let e=Cm(t);return e?[e]:Im(t.inputPreview)}var Mm=6e4,Rm=5*6e4,Lm=40,wi=6,ki=new Map;function _i(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 yi(n)){let s=ra(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Lm)return[...e.values()]}}return[...e.values()]}async function Si(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ra(s.project,s.ref),l=ki.get(i);l&&n-l.at<(s.github?Rm:Mm)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=wi)await Promise.all(o.slice(s,s+wi).map(async i=>{let l=ra(i.project,i.ref),d=null;try{d=i.github?await $m(i,e,a):await Pm(i,e,a)}catch{}ki.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function Ei(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 Pm(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 Ei(`${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 $m(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 Ei(`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}Wn();var an=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Ti(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}Wn();Ta();var Ai={kind:"agentx",id:"agentx",name:"AgentX"},nn={kind:"person",id:"unknown",name:"Unknown"},jm=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),Ci=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 Om(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=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 Ii(t){let e=s=>({kind:"person",id:`person:${s}`,name:Vn(t.people,s)}),a=(s,i)=>i||jm.has(s)?Ai:{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)??Qn(t.people,s)?.id;if(i)return e(i);let l=xt(s),d=l?.channel??t.channel;if(Un(s)==="human")return Ci(s?.senderUsername)?a(d,!1):nn;let p=!!Pe(n.senderAgentId)||wa(l?l.sender:s?.sender);return d==="desktop"&&!p?nn:a(d,p)}let r=Om(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Yn(t.people,t.channel,r);return o?e(o.id):wa(r.name)?Ai:Fn.has(t.channel)&&!Ci(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 Bm(t,{readonly:!0,fileMustExist:!0});return Se(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Mi>6e4&&(Mi=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Mi=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 qm(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 Pi(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 zm(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 $i(t,e,a){return vr(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 Fm(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:Wm(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!rn(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",c=Ri(p);return{id:d,name:l||i||d,avatar:J(l||i||d),kind:c}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:J(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:Ri(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 Um={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Wm(t,e){let a=Um[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Ri(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 ji(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}
9182
9184
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
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(`
9185
+ ${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 Gm(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 Oi(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
9184
9186
  SELECT id, ts, source, project, subject, intent, raw_json
9185
9187
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
9186
9188
  `).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(`
@@ -9189,12 +9191,12 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
9189
9191
  `).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(`
9190
9192
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
9191
9193
  FROM intent_resolutions WHERE decision_event_id IN (${A})
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
9194
+ `).all(L);for(let j of R)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,d=new Map,p=new Map,c=new Map,m=[],g=e?.business?.projects??[],k=e?.business?.contactMap??[],b=Ia(e?.business??{}),S=e?.people??[];for(let x of o){let A=null;try{A=JSON.parse(x.raw_json)}catch{}let L=$i(x.source,A,k),_=ji(x.source,A),R=Ti(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=qm(x.source,x.intent||"",A),ce=$e[W]||{label:W,color:"#6b7280"};p.has(W)||p.set(W,{id:W,label:ce.label,color:ce.color});let Q=Ii({source:x.source,channel:W,raw:A,people:S,channelLabel:N=>$e[N]?.label??N}),oe="__system",Z,F=Fm(x.source,x.intent||"",A);if(F){oe=F.id,Z=F.kind;let N=L?.displayName||F.name;(!c.has(F.id)||L?.displayName)&&c.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else c.has("__system")||c.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(x.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let Ac=`${x.id}|${N.decided_by}`,ht=i.get(Ac),Hn=N.decided_at,Bn=ht?.resolved_at??null,va=Bn===null,Cc=ht?.duration_ms??(va?n-Hn:0),Ic=va?"active":ht?.status==="error"||ht?.status==="fail"?"error":"completed",ee,nt;if($)ee=$,nt=O;else{let ya=b.get(N.agent_id);ya?(ee=ya,nt=`${ya}/_${x.source}`):(ee="unmapped",nt=`unmapped/_${x.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:Pi(ee),projects:[]}),d.has(ee)||d.set(ee,new Set),d.get(ee).add(nt),m.push({id:`${x.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:nt,channelId:W,initiatorId:oe,initiatorKind:Z,subject:Gm(x.subject),intent:x.intent||"",startedAt:Hn,resolvedAt:Bn,duration:Cc,active:va,outcome:Ic,tokens:0,inputPreview:_,system:zm(N.agent_id,e),...R,starter:Q})}}let T=[...l.values()].map(x=>({...x,projects:[...d.get(x.id)||[]].sort()})).sort((x,A)=>x.id.localeCompare(A.id)),h=[],u=new Set;if(e){let x=e.business??{},A=L=>{let _=x.orgChart?.[L]?.role,R=_?x.roles?.[_]?.title:void 0;return typeof R=="string"&&R.trim()?R.trim():void 0};for(let[L,_]of Object.entries(e.agents||{})){let R={id:L,name:_.name||L,tier:_.tier==="claude-code"?"lead":"worker",model:_.model||"",role:_.systemPrompt?_.systemPrompt.split(/[.\n]/)[0].slice(0,60):_.tier||"",title:A(L)};h.push(R),u.add(L)}}for(let x of m)u.has(x.agentId)||(h.push({id:x.agentId,name:x.agentId,tier:"worker",model:"",role:""}),u.add(x.agentId));h.sort((x,A)=>x.id.localeCompare(A.id));let f=[],v=new Set;for(let[x,A]of Object.entries($e))f.push({id:x,label:A.label,color:A.color}),v.add(x);for(let x of p.values())v.has(x.id)||f.push(x);let y=[...c.values()];y.find(x=>x.id==="__system")||y.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let E=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:T,agents:h,channels:f,initiators:y,dispatches:m,forges:{gitlab:typeof E=="string"?E:void 0,github:"https://github.com"}}}function dn(t){let e=ln();if(!e)return null;try{return Oi(e.db,Di(),t)}finally{e.close()}}function Ni(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let c of p.clients){let m=e.get(c.id);if(!m)e.set(c.id,{...c,projects:[...c.projects]});else{let g=Array.from(new Set([...m.projects,...c.projects])).sort();e.set(c.id,{...m,projects:g})}}for(let c of p.agents)a.has(c.id)||a.set(c.id,c);for(let c of p.channels)n.has(c.id)||n.set(c.id,c);for(let c of p.initiators)r.has(c.id)||r.set(c.id,c);for(let c of p.dispatches){let m=Xm(c);if(m.clientId!==c.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Pi(m.clientId),projects:[]}),m.projectId!==c.projectId){let g=e.get(m.clientId);g.projects.includes(m.projectId)||e.set(m.clientId,{...g,projects:[...g.projects,m.projectId].sort()})}o.push({...m,nodeId:d,id:`${d}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,p)=>d.id.localeCompare(p.id)),agents:[...a.values()].sort((d,p)=>d.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,p)=>p.startedAt-d.startedAt)}}function Xm(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 Si(_i(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 Di(){return we&&{...we,people:st(we.people)}}function Hi(t){we=t}async function Bi(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=qi(parseInt(r.searchParams.get("hours")||"6",10));ye(e,200,await oa(Oi(n.db,Di(),o)))}catch(r){ye(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Km=5e3;async function cn(t,e,a,n=dn){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
9193
9195
 
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
9196
+ `);let r=new URL(t.url||"/","http://_"),o=qi(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
9195
9197
 
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
9197
- `),e.write(`data: ${JSON.stringify(d)}
9198
+ `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),c=p&&await oa(p);if(s)break;c?(e.write(`event: snapshot
9199
+ `),e.write(`data: ${JSON.stringify(c)}
9198
9200
 
9199
9201
  `)):e.write(`event: error
9200
9202
  data: ${JSON.stringify({error:"ledger not available"})}
@@ -9202,7 +9204,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
9202
9204
  `)}catch(p){e.write(`event: error
9203
9205
  data: ${JSON.stringify({error:p?.message??String(p)})}
9204
9206
 
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=`
9207
+ `)}let d=Date.now();for(;!s&&Date.now()-d<Km;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function qi(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Jm(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)?Li(s,e,a):null}return Li(r,e,a)}function Li(t,e,a){let n=null,r=1/0;for(let o of Dm(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Hm(Nm(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function zi(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 d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return ye(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return ye(e,404,{error:"decision not found"}),!0;let c=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(d.raw_json)}catch{}let g=ji(d.source,m),k=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||g,b=null,S=null;if(p.agent_id){let y=Jm(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/_${d.source}`,via:"fallback"},v=$i(d.source,m,h);if(v)f={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(d.project||na(m,d.subject,g)){let y=d.project||na(m,d.subject,g);f={client:St(y,T),project:y,via:d.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(p.agent_id){let y=u.get(p.agent_id);y&&(f={client:y,project:`${y}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${y})`})}ye(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:c?.resolved_at??null,durationMs:c?.duration_ms??null,input:k,response:b,transcriptLen:S,resolutionStatus:c?.status??null,resultSummary:c?.result_summary??null,attribution:f})}catch(d){ye(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Zm,readFileSync as ef}from"fs";import{resolve as Ui}from"path";yt();function Fi(t){let e=t.agentId,a=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",n=`<script>window.AGENT_ID = ${JSON.stringify(e)};</script>`,r=Vm.replace(/__AGENT_ID__/g,H(e));return I({title:`AgentX \xB7 ${H(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${H(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Ym,headExtras:'<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">',scripts:`${n}${a}<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script><script>${Qm}</script>`})}var Vm=`
9206
9208
  <!-- Breadcrumb -->
9207
9209
  <div class="ax-crumb">
9208
9210
  <a href="/admin">Settings</a>
@@ -9800,7 +9802,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
9800
9802
  </div>
9801
9803
  </div>
9802
9804
  </div>
9803
- `,Gm=`
9805
+ `,Ym=`
9804
9806
  /* Agent-specific layout + legacy styles for bits the migration left in
9805
9807
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
9806
9808
  * primitives live in components.css.ts. */
@@ -9919,7 +9921,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
9919
9921
 
9920
9922
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
9921
9923
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
9922
- `,Xm=`
9924
+ `,Qm=`
9923
9925
  const $ = (id) => document.getElementById(id);
9924
9926
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
9925
9927
 
@@ -10778,15 +10780,15 @@ document.addEventListener('keydown', (e) => {
10778
10780
  /* ===== Boot ===== */
10779
10781
  initOptsToggles();
10780
10782
  loadAgent();
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>
10783
+ `;function Wi(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fi({agentId:a,peers:n,localToken:r}))}async function Gi(t,e,a){try{let n=t.method==="GET"?void 0:await _f(t),r=new URL(t.url||"/","http://localhost"),o=Object.fromEntries(r.searchParams),s=a.match(/^\/api\/admin\/agent\/([a-z0-9][a-z0-9_-]*)(?:\/(.+))?$/);if(!s){sa(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,c={"GET ":()=>lt(i),"PATCH ":()=>tf(i,n),"PATCH capability":()=>rf(i,n),"POST mcp":()=>af(i,n),"DELETE mcp":()=>nf(i,n),"GET identity":()=>of(i),"GET identity/file":()=>sf(i,String(o.path||"")),"PUT identity/file":()=>lf(i,n),"GET skills":()=>df(i),"POST skills":()=>cf(i,n),"DELETE skills":()=>pf(i,n),"GET skills/tree":()=>uf(i,String(o.slug||"")),"GET skills/file":()=>mf(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>ff(i,n),"GET skills/deps":()=>hf(i,String(o.slug||"")),"POST skills/install":()=>gf(i,n,t),"POST skills/deps":()=>xf(i,n,t),"GET channels":()=>bf(i),"GET activity":()=>vf(i,t),"GET handovers":()=>yf(i),"POST handovers":()=>wf(i,n),"DELETE handovers":()=>kf(n)}[d];if(!c){sa(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let m=await c();sa(e,200,m)}catch(n){sa(e,400,{error:n?.message||"agent op failed"})}}function Xi(){let t=Ui(process.cwd(),"agentx.json");return Zm(t)?JSON.parse(ef(t,"utf-8")):null}function V(t){let e=Xi();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 lt(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 tf(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:lt(t)}}function af(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:lt(t)}}function nf(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:lt(t)}}function rf(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:lt(t)}}function of(t){let{def:e}=V(t);return Fe(e.workspace)}function sf(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Lt(a.workspace,e)}function lf(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 df(t){let{def:e}=V(t),a=Fe(e.workspace);return{skills:a.skills,workspace:a.workspace}}function cf(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 pf(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 uf(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Jr(a.workspace,e),r=Ot(a.workspace,e);return{slug:e,tree:n,deps:r}}function mf(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Vr(n.workspace,e,a)}function ff(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 Yr(r.workspace,a,n,String(e?.content??""))}function hf(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Ot(a.workspace,e)}async function gf(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=Ki(e?.worker),{def:o}=V(t),s=uo(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(`
10784
+ `);return Ji(a,r,l,`install-${n}:${Date.now()}`)}async function xf(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Ki(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=Ui(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(`
10785
+ `);return Ji(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Ki(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 Ji(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),p;try{p=JSON.parse(d)}catch{p={content:d}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function bf(t){let e=Xi(),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 vf(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 nr}function yf(t){let e=pn(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function wf(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=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:d}}function kf(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 _f(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 Vi=[{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>
10784
10786
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
10785
10787
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
10786
10788
  <section id="statstrip" class="ax-statstrip"></section>
10787
10789
  <main id="grid" class="ax-live__body"></main>
10788
10790
  </div>
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>
10791
+ `;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:Sf,scripts:e+`<script>${Ef}</script>`,headExtras:`<script>
10790
10792
  // rightExtras for the topbar are injected at runtime \u2014 they reference
10791
10793
  // IDs (#ts, #conn-dot) that the script below addresses directly.
10792
10794
  document.addEventListener('DOMContentLoaded', () => {
@@ -10797,7 +10799,7 @@ loadAgent();
10797
10799
  extras.innerHTML = ${JSON.stringify(a)};
10798
10800
  right.insertBefore(extras, right.firstChild);
10799
10801
  });
10800
- </script>`})}var vf=`
10802
+ </script>`})}var Sf=`
10801
10803
  /* --- Page frame --- */
10802
10804
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
10803
10805
 
@@ -11018,7 +11020,7 @@ loadAgent();
11018
11020
  border-top-color: var(--ax-accent); border-radius: 50%;
11019
11021
  animation: ax-spin 800ms linear infinite; display: inline-block;
11020
11022
  }
11021
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,yf=`
11023
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,Ef=`
11022
11024
  'use strict';
11023
11025
 
11024
11026
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -11665,7 +11667,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11665
11667
  });
11666
11668
  }
11667
11669
 
11668
- `;var Ki=`
11670
+ `;var Yi=`
11669
11671
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
11670
11672
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
11671
11673
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -11839,7 +11841,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11839
11841
  .mx-summary{max-width:56vw}
11840
11842
  }
11841
11843
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
11842
- `;var Ji=`<script>
11844
+ `;var Qi=`<script>
11843
11845
  window.MX=(function(){
11844
11846
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
11845
11847
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -11948,7 +11950,7 @@ window.MX=(function(){
11948
11950
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
11949
11951
  setHealth:setHealth,get:get};
11950
11952
  })();
11951
- </script>`;var Vi=`<script>
11953
+ </script>`;var Zi=`<script>
11952
11954
  window.MXD=(function(){
11953
11955
  function el(id){return document.getElementById(id)}
11954
11956
  function tz(){return -new Date().getTimezoneOffset()}
@@ -12162,7 +12164,7 @@ window.MXD=(function(){
12162
12164
 
12163
12165
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
12164
12166
  })();
12165
- </script>`;var Yi=`<script>
12167
+ </script>`;var el=`<script>
12166
12168
  (function(){
12167
12169
  var LANES=[
12168
12170
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -12478,7 +12480,7 @@ window.MXD=(function(){
12478
12480
  window.addEventListener('scroll',hideTip,{passive:true});
12479
12481
  load();
12480
12482
  })();
12481
- </script>`;var Qi=`<script>
12483
+ </script>`;var tl=`<script>
12482
12484
  (function(){
12483
12485
  var showAll=document.getElementById('mx-show-all'),expanded=false;
12484
12486
  var esc=MX.esc;
@@ -12656,7 +12658,7 @@ window.MXD=(function(){
12656
12658
  }
12657
12659
  load();setInterval(load,5000);
12658
12660
  })();
12659
- </script>`;var Zi=`
12661
+ </script>`;var al=`
12660
12662
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
12661
12663
  .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}
12662
12664
  .mx-rt-wrap > .mx-empty{border:0}
@@ -12697,7 +12699,7 @@ window.MXD=(function(){
12697
12699
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
12698
12700
  .mx-rt-name{max-width:100%}
12699
12701
  }
12700
- `,el=`<script>
12702
+ `,nl=`<script>
12701
12703
  (function(){
12702
12704
  var root=document.getElementById('mx-routines');
12703
12705
  var bar=document.getElementById('mx-rt-filter');
@@ -12824,7 +12826,7 @@ window.MXD=(function(){
12824
12826
  syncBar();
12825
12827
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
12826
12828
  })();
12827
- </script>`;var tl=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],al=`<script>
12829
+ </script>`;var rl=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],ol=`<script>
12828
12830
  (function(){
12829
12831
  var root=document.getElementById('mx-feed');
12830
12832
  if(!root)return;
@@ -12899,12 +12901,12 @@ window.MXD=(function(){
12899
12901
  }
12900
12902
  load();setInterval(load,5000);
12901
12903
  })();
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">
12904
+ </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 Tf=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Af=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Cf=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function sl(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">
12903
12905
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
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("")}
12906
+ ${Af.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("")}
12905
12907
  </div>
12906
12908
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
12907
- ${_f.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12909
+ ${Cf.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12908
12910
  </div>
12909
12911
  </div>
12910
12912
  <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">
@@ -12957,7 +12959,7 @@ window.MXD=(function(){
12957
12959
  <section class="mx-section" aria-labelledby="mx-routines-title">
12958
12960
  ${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>')}
12959
12961
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
12960
- ${wf.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12962
+ ${Tf.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12961
12963
  </div>
12962
12964
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
12963
12965
  </section>
@@ -12965,7 +12967,7 @@ window.MXD=(function(){
12965
12967
  <section class="mx-section" aria-labelledby="mx-feed-title">
12966
12968
  ${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>')}
12967
12969
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
12968
- ${tl.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12970
+ ${rl.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12969
12971
  </div>
12970
12972
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
12971
12973
  </section>
@@ -12998,7 +13000,7 @@ window.MXD=(function(){
12998
13000
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
12999
13001
  </header>
13000
13002
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
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>
13003
+ </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Yi+al,scripts:Qi+If+Zi+el+nl+tl+ol})}var If=`<script>
13002
13004
  (function(){
13003
13005
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
13004
13006
  var range=document.getElementById('mx-range');
@@ -13026,10 +13028,10 @@ window.MXD=(function(){
13026
13028
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
13027
13029
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
13028
13030
  })();
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."})+`
13031
+ </script>`;function il(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."})+`
13030
13032
  <div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
13031
13033
  <ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
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=`
13034
+ <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:Mf,scripts:`<script>${Rf}</script>`})}var Mf=`
13033
13035
  .gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
13034
13036
  .gm-empty { color: var(--ax-text-2); }
13035
13037
  .gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
@@ -13047,7 +13049,7 @@ window.MXD=(function(){
13047
13049
  .gm-msg { min-height: 1.4em; margin: 8px 0 0; }
13048
13050
  .gm-msg.is-bad { color: var(--ax-red-ink); }
13049
13051
  .gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
13050
- `,Tf=`
13052
+ `,Rf=`
13051
13053
  (function () {
13052
13054
  var list = document.getElementById('gm-list');
13053
13055
  var msg = document.getElementById('gm-msg');
@@ -13094,7 +13096,7 @@ window.MXD=(function(){
13094
13096
  load();
13095
13097
  setInterval(load, 30000);
13096
13098
  })();
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=`
13099
+ `;async function ll(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Lf(s,e.days)}function Lf(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,p=0,c=0,m=0,g=0,k=0;for(let{node:S,data:T}of t)if(T){a.runs+=T.totals.runs,a.errors+=T.totals.errors,a.hours+=T.totals.hours,a.agents+=T.totals.agents,a.threads+=T.totals.threads;for(let h of T.days){let u=n.get(h.day)||{day:h.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let f of["cron","workflow","direct"])u[f][0]+=h[f]?.[0]||0,u[f][1]+=h[f]?.[1]||0;n.set(h.day,u)}for(let h of T.origins){let u=r.get(h.channel)||{channel:h.channel,runs:0,errors:0,hours:0};u.runs+=h.runs,u.errors+=h.errors,u.hours+=h.hours,r.set(h.channel,u)}for(let h of T.causes){let u=o.get(h.cause)||{cause:h.cause,count:0,agents:[],example:""};u.count+=h.count;for(let f of h.agents)u.agents.includes(f)||u.agents.push(f);u.example||(u.example=h.example),o.set(h.cause,u)}for(let h of T.rotations.byReason)s.set(h.reason,(s.get(h.reason)||0)+h.count);d+=T.rotations.total,p+=T.rotations.tokenSum||0,c+=T.rotations.tokenSamples||0,m=Math.max(m,T.rotations.maxTokens),g+=T.retention.traces,k+=T.retention.tracesWithSteps;for(let h of T.jobs)i.push({...h,node:S.name,nodeUrl:S.url});for(let h of T.threads)l.push({...h,node:S.name,nodeUrl:S.url})}let b=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:b.length?Math.min(...b):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,T)=>S.day.localeCompare(T.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,T)=>T.runs-S.runs),causes:[...o.values()].sort((S,T)=>T.count-S.count),jobs:i.sort((S,T)=>T.hours-S.hours),threads:l.sort((S,T)=>T.lastAt-T.firstAt-(S.lastAt-S.firstAt)||T.runs-S.runs),rotations:{total:d,byReason:[...s.entries()].map(([S,T])=>({reason:S,count:T})).sort((S,T)=>T.count-S.count),tokenSum:p,tokenSamples:c,maxTokens:m},retention:{traces:g,tracesWithSteps:k}}}async function dl(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 cl(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Pf(s,e.day)}function Pf(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function pl(t={}){let e=`
13098
13100
  <select id="boardPicker" title="Switch board"></select>
13099
13101
  <div class="search">
13100
13102
  <span class="icon">\u2315</span>
@@ -13195,7 +13197,7 @@ window.MXD=(function(){
13195
13197
  </footer>
13196
13198
  </div>
13197
13199
  </div>
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>
13200
+ <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:$f,scripts:`<script>${jf}</script>`,headExtras:`<script>
13199
13201
  // The boards page has its own connection dot + wants body height:100%
13200
13202
  // for the full-viewport kanban layout. Inject the dot into the topbar
13201
13203
  // and override body height at runtime so the shared shell doesn't
@@ -13211,7 +13213,7 @@ window.MXD=(function(){
13211
13213
  right.insertBefore(dot, right.firstChild);
13212
13214
  }
13213
13215
  });
13214
- </script>`})}var If=`
13216
+ </script>`})}var $f=`
13215
13217
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
13216
13218
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
13217
13219
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -13464,7 +13466,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
13464
13466
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
13465
13467
  .draft-box .draft-row .hint.err { color: var(--red); }
13466
13468
  .draft-box .draft-row .hint.ok { color: var(--green); }
13467
- `,Mf=`
13469
+ `,jf=`
13468
13470
  'use strict';
13469
13471
  const state = {
13470
13472
  boards: [], current: null, items: {},
@@ -14517,9 +14519,9 @@ function appendEvents(events) {
14517
14519
  }
14518
14520
 
14519
14521
  loadBoards().catch(e => toast('Init failed: ' + e.message));
14520
- `;function cl(t={}){let a=`<h1>Plain-English glossary</h1>
14522
+ `;function ul(t={}){let a=`<h1>Plain-English glossary</h1>
14521
14523
  <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>
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=`
14524
+ ${Vi.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:Of})}var Of=`
14523
14525
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
14524
14526
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
14525
14527
  .lead {
@@ -14549,7 +14551,7 @@ article.term .alias {
14549
14551
  }
14550
14552
  article.term p {
14551
14553
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
14552
- }`;function dl(t={}){let e=`<div class="ax-wf__root">
14554
+ }`;function ml(t={}){let e=`<div class="ax-wf__root">
14553
14555
  <aside class="ax-wf__list">
14554
14556
  <header>
14555
14557
  <h2>Workflows</h2>
@@ -14647,7 +14649,7 @@ article.term p {
14647
14649
  </aside>
14648
14650
  </div>
14649
14651
 
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:xr})}${Pf}</script>`})}var Lf=`
14652
+ <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:Nf,scripts:`<script>${z({workflowHealth:br})}${Df}</script>`})}var Nf=`
14651
14653
  .ax-wf__root {
14652
14654
  display: grid;
14653
14655
  grid-template-columns: 340px 1fr;
@@ -15065,7 +15067,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15065
15067
  font-size: 12px; z-index: 50;
15066
15068
  }
15067
15069
  .hint { color: var(--ax-muted); font-size: 11px; }
15068
- `,Pf=`
15070
+ `,Df=`
15069
15071
  (() => {
15070
15072
  const $ = (sel) => document.querySelector(sel)
15071
15073
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -15951,7 +15953,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15951
15953
  setInterval(refresh, 15000)
15952
15954
  })
15953
15955
  })();
15954
- `;function pl(t={}){let e=`<div class="ax-proc__root">
15956
+ `;function fl(t={}){let e=`<div class="ax-proc__root">
15955
15957
  <header class="ax-proc__header">
15956
15958
  <h1>Procedures</h1>
15957
15959
  <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>
@@ -15995,7 +15997,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15995
15997
  <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>
15996
15998
  <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>
15997
15999
  </section>
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=`
16000
+ </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Hf,scripts:`<script>${Bf}</script>`})}var Hf=`
15999
16001
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
16000
16002
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
16001
16003
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -16021,7 +16023,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16021
16023
  .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); }
16022
16024
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
16023
16025
  .ax-proc__link:hover { text-decoration: underline; }
16024
- `,jf=`
16026
+ `,Bf=`
16025
16027
  (function(){
16026
16028
  function $(sel){ return document.querySelector(sel) }
16027
16029
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -16121,7 +16123,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16121
16123
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
16122
16124
  else bootAll()
16123
16125
  })();
16124
- `;function ul(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
16126
+ `;function hl(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
16125
16127
  data-task-id="${H(t.taskId)}"
16126
16128
  data-agent-id="${H(t.agentId)}"
16127
16129
  data-node-url="${H(t.nodeUrl)}"
@@ -16164,7 +16166,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16164
16166
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
16165
16167
  </div>
16166
16168
  </footer>
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=`
16169
+ </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:qf,scripts:`<script>${zf}</script>`})}var qf=`
16168
16170
  /* The shell gives <main> no padding, so page content butted straight against
16169
16171
  the sticky topbar. Breathe. */
16170
16172
  .ax-task-page {
@@ -16306,7 +16308,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16306
16308
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
16307
16309
  }
16308
16310
 
16309
- `,Nf=`
16311
+ `,zf=`
16310
16312
  (function () {
16311
16313
  var root = document.querySelector('.ax-task-page');
16312
16314
  if (!root) return;
@@ -16691,7 +16693,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16691
16693
  });
16692
16694
 
16693
16695
  })();
16694
- `;function ml(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16696
+ `;function gl(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16695
16697
  data-agent-id="${H(t.agentId)}"
16696
16698
  data-agent-name="${H(e)}"
16697
16699
  data-node-url="${H(t.nodeUrl)}">
@@ -16720,7 +16722,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16720
16722
  <div class="ax-history__list" id="hist-list">
16721
16723
  <div class="ax-history__empty">loading\u2026</div>
16722
16724
  </div>
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=`
16725
+ </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ff,scripts:`<script>${Uf}</script>`})}var Ff=`
16724
16726
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
16725
16727
  flush against the sticky topbar. */
16726
16728
  .ax-history {
@@ -16772,7 +16774,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16772
16774
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
16773
16775
  }
16774
16776
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
16775
- `,Hf=`
16777
+ `,Uf=`
16776
16778
  (function () {
16777
16779
  var root = document.querySelector('.ax-history');
16778
16780
  if (!root) return;
@@ -16872,31 +16874,31 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16872
16874
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
16873
16875
  });
16874
16876
  })();
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)}
16877
+ `;function bl(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=>xl(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Gf(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,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return P(e,200,{ok:!0,emission:d})}):P(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?P(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Ye(t,e,l=>{try{let d=a.layouts.save(s,l);return P(e,200,{layout:d})}catch(d){return P(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ye(t,e,l=>{let d=Aa.safeParse(l);if(!d.success)return P(e,200,{ok:!1,issues:d.error.issues.map(c=>({path:c.path.join("."),message:c.message}))});let p=Ca(d.data).map(c=>({path:"",message:c}));return P(e,200,{ok:p.length===0,issues:p,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?P(e,200,{workflow:l}):P(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ye(t,e,p=>xl(e,a,p,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var Wf=["mesh"];function xl(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,d=e.store.get(n.id);if(d)for(let p of Wf)!(p in l)&&p in d&&(o[p]=d[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),p=l?.yamlPath,c=!!p||/yaml round-trip failed/.test(d);return P(t,c?409:500,{error:c?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:c?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function Gf(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",c=a.runs.list({workflowId:d,limit:l});if(!p)return P(e,200,{runs:c});let m=c.map(g=>({id:g.id,workflowId:g.workflowId,workflowVersion:g.workflowVersion,homeNode:g.homeNode,status:g.status,pending:g.pending,entityRef:g.entityRef,history:(g.history||[]).slice(-5),parentRunId:g.parentRunId,parentNodeId:g.parentNodeId,rootRunId:g.rootRunId,depth:g.depth,createdAt:g.createdAt,updatedAt:g.updatedAt}));return P(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return P(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Ye(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?P(e,200,{ok:!0,runId:l,status:p}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return Xf(t,e,a,l);let d=a.runs.get(l);return d?P(e,200,{run:d}):P(e,404,{error:"run not found"})}return P(e,404,{error:"unknown runs endpoint"})}function Xf(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)}
16876
16878
 
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)}
16879
+ `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=c=>{if(!o)try{e.write(`data: ${JSON.stringify(c)}
16878
16880
 
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 _r(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,`
16881
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let c=a.runs.get(n);c&&c.updatedAt!==d&&(d=c.updatedAt,i(c))},2e3);return!0}function 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 Hh}from"fs";import{createRequire as Bh}from"module";var vl=4e3;async function yl(t,e,a,n,r){if(n==="GET"&&a==="/api/app/desk")return dt(e,200,await r.board());if(n!=="POST"||a!=="/api/app/desk/reply")return!1;let o;try{o=await qe(t)}catch(d){return dt(e,400,{error:d.message})}let s=typeof o.id=="string"?o.id.trim():"",i=typeof o.text=="string"?o.text.trim():"";if(!s||!i)return dt(e,400,{error:"id and text are required"});if(i.length>vl)return dt(e,400,{error:`the answer is longer than ${vl} characters`});let l=await r.reply(s,i);return dt(e,l.status,l.body)}function dt(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}Xn();var kl=50,Kf=280;async function _l(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=Jf(await o.recent(kl))}catch(d){l=String(d?.message||"unreachable").slice(0,200)}return wl(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return wl(e,404,{error:"not found"})}function Sl(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 Sr(r):null}}}function Jf(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:"",Kf),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,kl)}function mn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function wl(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Vf="operator",Yf=50,El=4,Tl=500;function Qf(t){let e={channel:"app",chatId:t.chatId,sender:Vf,...t.spoken?{via:"voice"}:{}};return t.node==="local"?{path:"/task",body:{agent:t.agent,message:t.message,stream:!0,context:e}}:{path:"/mesh/task",body:{peer:t.node,agent:t.agent,message:t.message,stream:!0,context:e}}}async function Al(t,e,a,n){let{path:r,body:o}=Qf(e),s="",i=!1,l=[],d=new Map,p=(c,m,g)=>{let k=c!=="done",b=i?{text:_t(m,k),artifacts:[]}:kt(m,pe.perMessage,k),{cleanText:S,ui:T}=c==="done"?Et(b.text):{cleanText:b.text,ui:void 0},h=i?void 0:fn(T);return{status:c,text:S,tools:l,files:b.artifacts,...h?{ui:h}:{},...g?{error:g}:{}}};try{let c=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!c.ok||!c.body){let m=await c.json().then(g=>g?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${c.status}.`)}for await(let m of eh(c.body)){n(m.event,m.data);let g=m.data??{};if(m.event==="start")i=g.rich===!1;else if(m.event==="text"&&typeof g.text=="string")s+=g.text;else if(m.event==="tool"&&g.status==="start"&&l.length<Yf){let k={name:String(g.name||"tool").slice(0,80),...g.arg?{arg:String(g.arg).slice(0,80)}:{}};l.push(k),g.id&&d.set(String(g.id),k)}else if(m.event==="tool"&&g.status==="result"&&g.error===!0&&d.has(String(g.id)))d.get(String(g.id)).error=!0;else{if(m.event==="done")return p("done",typeof g.content=="string"&&g.content?g.content:s);if(m.event==="error")return p("error",s,Zf(g.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(c){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${c?.message||c}`)}}function Zf(t){let e=String(t||"The agent could not answer.");return rr(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,El).map(s=>s.slice(0,Tl));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,El).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Tl)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*eh(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,`
16880
16882
  `);let s;for(;(s=n.indexOf(`
16881
16883
 
16882
- `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
16883
- `))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&c.push(p.slice(5).replace(/^ /,""));if(c.length)try{yield{event:l,data:JSON.parse(c.join(`
16884
+ `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
16885
+ `))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&d.push(p.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
16884
16886
  `))}}catch{}}}}finally{e.releaseLock()}}var ia=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];plain=!1;orphaned=!1;startedAt=Date.now();listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="start"&&(this.plain=a?.rich===!1),e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}watched(){return this.listeners.size>0}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
16885
16887
  data: ${JSON.stringify(s)}
16886
16888
 
16887
16889
  `)},r=setInterval(()=>{a()&&e.write(`: ping
16888
16890
 
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}
16891
+ `)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};function Il(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=th(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(`
16892
+ `)){let n=Ml(a);if(n)return gn(n,e)}return""}function th(t,e=120){let a=t.split(`
16893
+ `).map(Ml).filter(Boolean);return a.length?gn(a[a.length-1],e):""}function Ml(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 da(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Cl=140;function ca(t,e,a,n,r){let o=a==="error"?`Could not answer: ${hn(r||"",Cl-18)||"something went wrong."}`:hn(n,Cl)||"Answered.";return{deviceId:t,title:gn(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var Ll=8e3,nh=/^[A-Za-z0-9_.:-]{1,64}$/,Oe=new Map,xn=new Map,yn=new la;function Pl(){return yn}async function $l(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 jl(o)});let i=o.store();if(!i)return B(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),B(e,200,{conversations:Il(r.id,sh(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),B(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return B(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return B(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let c=Oe.get(p.id);return B(e,200,{...p,running:!!c,...c?{partial:{text:c.text,tools:c.tools,...c.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),c=p&&Oe.get(p.id);if(!p||!c)return B(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Ol(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:c.text,tools:c.tools,...c.plain?{plain:!0}:{}})),c.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return B(e,404,{error:"not found"});let d;try{d=await qe(t,64*1024)}catch(p){return B(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(d.conversationId??""));if(!p)return B(e,404,{error:"no such conversation"});let c=Oe.get(p.id);return c?(c.ac.abort(),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 oh(e,d,r,i,o),!0}function rh(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(c=>Qe(c.peerUrl)===i);l&&r.add(l.peer);let d=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:p.map(c=>{let m=Array.isArray(c.runningTasks)?c.runningTasks.length:0;return{id:c.id,name:c.name||c.id,busy:m>0||(c.active??0)>0,running:m,...c.color?{color:c.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function jl(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return rh(e.nodes,t.daemon,a)}async function oh(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Ll){B(t,400,{error:`message must be 1\u2013${Ll} 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(!nh.test(b)){B(t,400,{error:"pick an agent"});return}let S=(await jl(r)).find(h=>h.target===k);if(!S){B(t,400,{error:`unknown node "${k}"`});return}if(!S.online){B(t,409,{error:`${S.name} is offline`});return}let T=S.agents.find(h=>h.id===b);if(!T){B(t,400,{error:`no agent "${b}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:b,agentName:T.name,...T.color?{color:T.color}:{}},o)}if(Oe.has(s.id)){B(t,409,{error:"The agent is still answering in this conversation."});return}let i=new ia(r.orphanLimitMs??18e5);Oe.set(s.id,i);let{id:l,title:d,node:p,nodeName:c,agent:m,agentName:g}=s;xn.set(l,{id:l,deviceId:a.id,title:d,agent:m,...g?{agentName:g}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Ol(t),t.write(bn("conversation",{id:l,title:d,node:p,nodeName:c,agent:m,agentName:g})),i.attach(t);try{let k=e.spoken===!0,b=await Al(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&&da(h)&&r.notifyFinish(ca(a.id,s,b.status,b.text,b.error)).catch(()=>{})}finally{Oe.delete(l),xn.delete(l),i.finish()}}function sh(){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 Ol(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}
16892
16894
  data: ${JSON.stringify(e)}
16893
16895
 
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}
16896
+ `}async function vn(t,e,a){try{let n=Qe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.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 ih}from"stream";var lh=/^\/api\/app\/files\/([^/]+)$/,dh=15e3;async function Dl(t,e,a,n,r,o){let s=lh.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ne(e,405,{error:"GET only"});let i=o.store();if(!i)return Ne(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let d=i.getFile(r.id,l);if(!d)return Ne(e,404,{error:"no such file"});let p=await ch(d.node,o);if(!p)return Ne(e,502,{error:`${d.node} is not linked to this computer's mesh any more.`});let c=new AbortController;e.on("close",()=>c.abort());let m=setTimeout(()=>c.abort(),dh),g;try{let h=new URLSearchParams({agent:d.agent,file:d.path});g=await fetch(`${p.url}${Or}?${h}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:c.signal})}catch{return Ne(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(g.status!==200&&g.status!==206){let h=await g.json().then(f=>f?.error).catch(()=>""),u=[403,404,413,415,416].includes(g.status)?g.status:502;return Ne(e,u,{error:h||`The computer that made this file answered HTTP ${g.status}.`})}let k=Number(g.headers.get("content-length")||0);if(k>pe.bytes)return c.abort(),Ne(e,413,{error:"the file is too large"});let b=g.headers.get("content-range");if(e.writeHead(g.status,{...Nr(d.mime,d.name,d.kind),...g.headers.get("content-length")?{"Content-Length":String(k)}:{},...g.status===206&&b?{"Content-Range":b}:{}}),n==="HEAD"||!g.body)return e.end(),!0;let S=0,T=ih.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 ch(t,e){if(t==="local")return{url:Nl(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Nl(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Nl(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 Bl=8e3;async function ql(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(!Gr(g))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Wr(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Y(e,k.status,{error:k.error});let b=await Ce(t,Ur.bytes);if(!b)return Y(e,413,{error:Xr()});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 Hl(e,o.daemon,"/voice/transcribe",b,S,18e4)}let s,i=await Ce(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let d=l.get(r.id,String(s?.conversationId??""));if(!d)return Y(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Bl):"";if(!p.trim())return Y(e,400,{error:"text is required"});if(!uh(d.messages,p))return Y(e,404,{error:"no such answer in this conversation"});let c=s?.announce===!0?`${d.agentName||d.agent}: ${p}`:p,m={agent:d.agent,text:c,...d.node!=="local"?{peer:d.node}:{}};return Hl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Hl(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(ph(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 ph(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function uh(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Bl&&a.content.startsWith(e)))}var mh=new Set(["ring","offer","answer","ice","hangup"]),Ze=/^[A-Za-z0-9_-]{4,64}$/,fh=128*1024,hh=24,gh=2*1024*1024,De=new Map;async function Fl(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return M(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return M(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return M(e,502,{error:`AgentX answered HTTP ${l.status}.`});let d=await l.json(),p=rt(r.nodeName),c=(Array.isArray(d.peers)?d.peers:[]).filter(g=>rt(String(g?.name??""))!==p),m=(Array.isArray(d.agents)?d.agents:[]).filter(g=>g&&typeof g.id=="string").map(g=>({id:g.id,name:typeof g.name=="string"&&g.name?g.name:g.id}));return M(e,200,{node:r.nodeName,iceServers:d.iceServers??[],peers:c,agents:m,camera:d.camera??null})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,fh);if(!l)return M(e,413,{error:"signal too large"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=bh(d,r.nodeName);if(typeof p=="string")return M(e,400,{error:p});let c=Ul(p.to);if(c&&p.kind==="ring"){let m=await He(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:c});return M(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),g=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:g?.error||`AgentX answered HTTP ${m.status}.`})}catch{return M(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Ze.test(l)?vh(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Ce(t,4096);if(!l)return M(e,413,{error:"note too long"});let d;try{d=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let p=String(d?.callId??"");if(!Ze.test(p))return M(e,400,{error:"callId is required"});let c=typeof d?.note=="string"?d.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:c},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await zl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Ze.test(d))return M(e,400,{error:"callId is required"});let p=Number(l.seconds??0);if(!Number.isFinite(p)||p<0)return M(e,400,{error:"seconds must be 0 or more"});let c=typeof l.note=="string"?l.note:"",m=await He(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/stream`,{seconds:p,note:c});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await zl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let d=String(l.callId??"");if(!Ze.test(d))return M(e,400,{error:"callId is required"});let p=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(d)}`);if(p.status>=300)return M(e,p.status,{error:p.body.error});let c=(Array.isArray(p.body.watch?.replies)?p.body.watch.replies:[]).find(b=>b&&b.at===l.at);if(!c||typeof c.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(p.body.watch.agentId??""),g=JSON.stringify([d,c.at,m,c.text]),k=De.get(g);return k?(De.delete(g),De.set(g,k),Wl(e,k.type,k.bytes)):xh(e,o,s,{agent:m,text:c.text},(b,S)=>{if(!(S.length>gh))for(De.set(g,{type:b,bytes:S});De.size>hh;)De.delete(De.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await He(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let d=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return M(e,200,{asks:d,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return M(e,405,{error:"POST"});let l=await He(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Ze.test(l))return M(e,400,{error:"callId is required"});let d=await He(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return M(e,d.status,d.status<300?{watch:d.body.watch}:{error:d.body.error})}return M(e,404,{error:"not found"})}function Ul(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 zl(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 xh(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),Wl(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 Wl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function bh(t,e){let a=String(t?.kind??"");if(!mh.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:")&&!Ul(r))return"to must be bot:<agent id> for an agent";if(rt(r)===rt(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 vh(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 yh,readFileSync as wh,renameSync as kh,writeFileSync as _h}from"fs";import{dirname as Sh,isAbsolute as Eh,resolve as Th}from"path";import{randomBytes as Ah}from"crypto";var Gl=60,Xl=500,Ch=200,Vl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Ih=/^[A-Za-z0-9_-]{8,64}$/,Mh=/^[A-Za-z0-9._-]{1,64}$/;function Yl(t,e){return Eh(e)?e:Th(t,e)}function Kl(t){return`${t}_${Ah(6).toString("hex")}`}function Jl(){return{places:[],rules:[],seen:[]}}function Ql(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>Gl)return{ok:!1,error:`Keep the name under ${Gl} 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 Zl(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!Vl.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>Xl)return{ok:!1,error:`Keep it under ${Xl} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Mh.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 ed(t){let e=typeof t.id=="string"?t.id:"";if(!Ih.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!Vl.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(wh(this.path,"utf-8"));return!e||typeof e!="object"?Jl():{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 Jl()}}write(e){yh(Sh(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;_h(a,JSON.stringify(e,null,2)+`
16897
+ `,{mode:384}),kh(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:Kl("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:Kl("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(-Ch);let r=this.now(),o=n.places.find(i=>i.id===e.place),s;if(!o)s={status:"unknown-place"};else if(e.time<r-a.maxEventAgeMinutes*6e4)s={status:"too-old"};else{let i=a.cooldownMinutes*6e4,l=n.rules.filter(d=>d.placeId===o.id&&d.on===e.transition&&d.enabled&&!(d.lastFiredAt&&Date.parse(d.lastFiredAt)>r-i));for(let d of l)d.lastFiredAt=new Date(r).toISOString(),d.repeat||(d.enabled=!1);s=l.length?{status:"fired",place:o,rules:l.map(d=>({...d}))}:{status:"no-rules"}}return this.write(n),s}};Jn();function Rh(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function Lh(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(`
16898
+ `)}async function td(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=Rh(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,Lh(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16897
16899
 
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=`
16900
+ (${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 ad(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}
16901
+ ${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?{[Kn]: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 nd(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:od(t,e,a.slice(15),n,o,r)}async function rd(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:od(t,e,a.slice(11),n,r,null)}async function od(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=ed(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?td(o.id,l.place,l.rules,i.value.time,r.fire).catch(d=>r.log(`[places] delivery failed: ${d?.message||d}`)):r.log(`[places] ${l.rules.length} reminder(s) not sent: ${r.pushReason??"this computer doesn't send pushes"}`)),q(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=Ql(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=Zl(s,p=>i.has(p));if(!l.ok)return q(e,400,{error:l.error});let d=r.store.addRule(l.value,r.limits);return d.ok?q(e,200,{ok:!0,rule:d.rule}):q(e,409,{error:d.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return q(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?q(e,200,{ok:!0,rule:i}):q(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?q(e,200,{ok:!0}):q(e,404,{error:"No such reminder."})}return q(e,404,{error:"not found"})}function sd(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new pa(Yl(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function id(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 ld=`
16900
16902
  :root {
16901
16903
  --ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
16902
16904
  --ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
@@ -16910,7 +16912,7 @@ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15
16910
16912
  --ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
16911
16913
  --phone-bubble: #1d2f52; --phone-green: #3dbe74;
16912
16914
  }
16913
- `,sc=`
16915
+ `,dd=`
16914
16916
  [hidden] { display: none !important; }
16915
16917
  main > .sw-peek[hidden] { display: block !important; }
16916
16918
  main > #panel-chat.sw-peek[hidden] { display: flex !important; }
@@ -17016,7 +17018,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
17016
17018
  @media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
17017
17019
  @media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
17018
17020
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
17019
- `;var ic=`
17021
+ `;var cd=`
17020
17022
  window.AXSheet = function (sheet, onClose) {
17021
17023
  var handle = document.createElement('button');
17022
17024
  handle.type = 'button'; handle.className = 'sheet-handle';
@@ -17045,7 +17047,7 @@ window.AXSheet = function (sheet, onClose) {
17045
17047
  handle.addEventListener('pointercancel', reset);
17046
17048
  sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
17047
17049
  };
17048
- `;var lc=`
17050
+ `;var pd=`
17049
17051
  (function () {
17050
17052
  var fleetPanel = document.getElementById('panel-fleet');
17051
17053
  var activityPanel = document.getElementById('panel-activity');
@@ -17341,7 +17343,7 @@ window.AXSheet = function (sheet, onClose) {
17341
17343
  setInterval(refresh, 15000);
17342
17344
  refresh();
17343
17345
  })();
17344
- `;var cc=`
17346
+ `;var ud=`
17345
17347
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
17346
17348
  .fx-head h2 { margin: 4px 0 0; }
17347
17349
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -17406,7 +17408,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17406
17408
  .fx-opt em { font-style: normal; font-size: 12px; color: var(--ax-ok); white-space: nowrap; }
17407
17409
  .fx-error:empty { display: none; }
17408
17410
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
17409
- `;var dc=`
17411
+ `;var md=`
17410
17412
  (function () {
17411
17413
  var panel = document.getElementById('panel-desk');
17412
17414
  var ax = window.AXAsk;
@@ -17457,6 +17459,8 @@ details[open] > summary::before { transform: rotate(90deg); }
17457
17459
  var key = c.node + '|' + c.key;
17458
17460
  return '<article class="fx-card"><div class="fx-row"><h4>' + esc(c.title) + '</h4>' + pill(c) + '</div>' +
17459
17461
  (c.ask ? '<p>' + esc(c.ask) + '</p>' : '') +
17462
+ (c.need && !c.ask ? '<p class="fx-muted">Needed from you: ' + esc(c.need) + '</p>' : '') +
17463
+ (c.said ? '<details data-key="' + esc(key + '|said') + '"' + (openKeys[key + '|said'] ? ' open' : '') + '><summary>You said</summary><p class="fx-muted" dir="auto">' + esc(c.said) + '</p></details>' : '') +
17460
17464
  (c.outcome ? '<p><strong>' + esc(c.outcome) + '</strong>' + (c.evidence ? ' \xB7 ' + esc(c.evidence) : '') + '</p>' : '') +
17461
17465
  (c.recommend ? '<p class="fx-muted">Suggested: ' + esc(c.recommend) + '</p>' : '') +
17462
17466
  (c.facts ? '<details data-key="' + esc(key) + '"' + (openKeys[key] ? ' open' : '') + '><summary>What is known</summary><p class="fx-muted">' + esc(c.facts) + '</p></details>' : '') +
@@ -17538,7 +17542,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17538
17542
  setInterval(refresh, 15000);
17539
17543
  refresh();
17540
17544
  })();
17541
- `;var pc=`
17545
+ `;var fd=`
17542
17546
  .dk-figures { margin: 0 0 4px; line-height: 1.5; }
17543
17547
  .dk-cols {
17544
17548
  position: sticky; top: 0; z-index: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px;
@@ -17555,7 +17559,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17555
17559
  .dk-opt { width: 100%; min-height: 48px; padding: 8px 14px; text-align: left; border-radius: var(--ax-radius-sm); overflow-wrap: anywhere; }
17556
17560
  .dk-opt small { display: block; margin-top: 2px; font-weight: 400; color: var(--ax-text-2); }
17557
17561
  .dk-opt em { font-style: normal; font-weight: 400; color: var(--ax-text-2); }
17558
- `;var uc=`
17562
+ `;var hd=`
17559
17563
  (function () {
17560
17564
  var panel = document.getElementById('panel-alerts');
17561
17565
  if (!panel) return;
@@ -17766,7 +17770,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17766
17770
  refresh();
17767
17771
  loadRecent();
17768
17772
  })();
17769
- `;var mc=`
17773
+ `;var gd=`
17770
17774
  (function () {
17771
17775
  var panel = document.getElementById('panel-alerts');
17772
17776
  if (!panel) return;
@@ -17918,7 +17922,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17918
17922
  document.addEventListener('visibilitychange', function () { if (!document.hidden && state) load(); });
17919
17923
  load();
17920
17924
  })();
17921
- `,fc=`
17925
+ `,xd=`
17922
17926
  .pl-card { margin-top: 12px; }
17923
17927
  .pl-list { margin-top: 8px; }
17924
17928
  .pl-rules { list-style: none; margin: 6px 0 0; padding: 0; }
@@ -17937,7 +17941,162 @@ details[open] > summary::before { transform: rotate(90deg); }
17937
17941
  .pl-check { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); }
17938
17942
  .pl-check input { width: 20px; height: 20px; }
17939
17943
  #pl-here { justify-self: start; }
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=`
17944
+ `;function bd(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 vd='<nav id="pin-bar" class="pin-bar" aria-label="Pinned pages" hidden></nav>',yd=`
17945
+ (function () {
17946
+ var bar = document.getElementById('pin-bar');
17947
+ var panel = document.getElementById('panel-alerts');
17948
+ if (!bar || !panel) return;
17949
+ var card = document.createElement('div');
17950
+ card.className = 'fx-card pn-card';
17951
+ card.id = 'pn-card';
17952
+ card.innerHTML = '<div class="fx-row"><h3>Pinned pages</h3><span id="pn-pill" class="fx-pill"></span></div>' +
17953
+ '<p class="fx-muted">Buttons at the top of Chat that open a web page in this app. A page that uses the microphone asks for it the first time.</p>' +
17954
+ '<ul id="pn-list" class="fx-list pn-list"></ul>' +
17955
+ '<details id="pn-add-wrap" class="pn-add"><summary class="fx-btn">Pin a page</summary>' +
17956
+ '<form id="pn-add" autocomplete="off">' +
17957
+ '<label><span>Button name</span><input name="label" required maxlength="40" placeholder="Remote"></label>' +
17958
+ '<label><span>Page address</span><input name="url" required type="url" inputmode="url" placeholder="https://"></label>' +
17959
+ '<div class="fx-actions"><button type="submit" class="fx-btn fx-primary">Pin page</button></div>' +
17960
+ '</form></details>' +
17961
+ '<p id="pn-error" class="fx-error fx-bad" role="alert"></p>';
17962
+ var places = document.getElementById('pl-card');
17963
+ var head = document.getElementById('al-recent-head');
17964
+ panel.insertBefore(card, places ? places.nextSibling : (head || null));
17965
+
17966
+ var pill = document.getElementById('pn-pill');
17967
+ var list = document.getElementById('pn-list');
17968
+ var addWrap = document.getElementById('pn-add-wrap');
17969
+ var form = document.getElementById('pn-add');
17970
+ var err = document.getElementById('pn-error');
17971
+ var pins = [];
17972
+ function field(n) { return form.elements.namedItem(n); }
17973
+
17974
+ function esc(s) {
17975
+ return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
17976
+ return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
17977
+ });
17978
+ }
17979
+ function host(u) { try { return new URL(u).host; } catch (e) { return ''; } }
17980
+ function api(method, path, body) {
17981
+ return fetch(path, {
17982
+ method: method, credentials: 'same-origin',
17983
+ headers: body ? { 'Content-Type': 'application/json' } : {},
17984
+ body: body ? JSON.stringify(body) : undefined,
17985
+ }).then(function (r) {
17986
+ return r.json().catch(function () { return {}; }).then(function (b) {
17987
+ if (!r.ok) throw new Error(b.error || ('HTTP ' + r.status));
17988
+ return b;
17989
+ });
17990
+ });
17991
+ }
17992
+ // The computer only hands out https addresses; checked again here so a
17993
+ // stray value can never become a javascript: link.
17994
+ function https(list) {
17995
+ return list.filter(function (p) { return p && typeof p.url === 'string' && p.url.indexOf('https://') === 0; });
17996
+ }
17997
+ function paintBar(safe) {
17998
+ bar.innerHTML = safe.map(function (p) {
17999
+ return '<a class="pin-btn" href="' + esc(p.url) + '">' + esc(p.label) + '</a>';
18000
+ }).join('');
18001
+ bar.hidden = !safe.length;
18002
+ }
18003
+ function paint(max) {
18004
+ var safe = https(pins);
18005
+ paintBar(safe);
18006
+ try { localStorage.setItem('ax-pins', JSON.stringify(safe.map(function (p) { return { label: p.label, url: p.url }; }))); } catch (e) {}
18007
+ pill.textContent = safe.length + (safe.length === 1 ? ' page' : ' pages');
18008
+ pill.className = 'fx-pill ' + (safe.length ? 'fx-on' : 'fx-off');
18009
+ list.innerHTML = safe.length ? safe.map(function (p) {
18010
+ if (p.source === 'config') {
18011
+ return '<li class="pn-row"><span><strong>' + esc(p.label) + '</strong> <small class="fx-muted">' + esc(host(p.url)) + '</small></span>' +
18012
+ '<small class="fx-muted">Set in agentx.json</small></li>';
18013
+ }
18014
+ return '<li class="pn-row"><span><strong>' + esc(p.label) + '</strong> <small class="fx-muted">' + esc(host(p.url)) + '</small></span>' +
18015
+ '<span class="pn-acts"><button type="button" class="fx-btn" data-act="rename" data-id="' + esc(p.id) + '" data-label="' + esc(p.label) + '">Rename</button>' +
18016
+ '<button type="button" class="fx-btn fx-danger-o" data-act="remove" data-id="' + esc(p.id) + '" data-label="' + esc(p.label) + '">Remove</button></span></li>';
18017
+ }).join('') : '<li class="fx-muted">No pinned pages yet.</li>';
18018
+ addWrap.hidden = typeof max === 'number' && safe.length >= max;
18019
+ }
18020
+ // Until the list loads, or while offline, show the buttons from last time.
18021
+ try {
18022
+ var saved = JSON.parse(localStorage.getItem('ax-pins') || '[]');
18023
+ if (Array.isArray(saved)) paintBar(https(saved));
18024
+ } catch (e) {}
18025
+ function load() {
18026
+ return api('GET', '/api/app/pins').then(function (s) { pins = s.pins || []; paint(s.max); })
18027
+ .catch(function (e) { pill.textContent = ''; err.textContent = 'Could not load pinned pages: ' + e.message; });
18028
+ }
18029
+
18030
+ form.addEventListener('submit', function (ev) {
18031
+ ev.preventDefault();
18032
+ err.textContent = '';
18033
+ api('POST', '/api/app/pins/add', { label: field('label').value, url: field('url').value })
18034
+ .then(function () { form.reset(); addWrap.open = false; return load(); })
18035
+ .catch(function (e) { err.textContent = e.message; });
18036
+ });
18037
+ list.addEventListener('click', function (ev) {
18038
+ var b = ev.target.closest('button[data-act]');
18039
+ if (!b) return;
18040
+ var act = b.getAttribute('data-act');
18041
+ var id = b.getAttribute('data-id');
18042
+ var label = b.getAttribute('data-label');
18043
+ var body;
18044
+ if (act === 'rename') {
18045
+ var next = prompt('New name for ' + label, label);
18046
+ if (next == null || next.trim() === '' || next.trim() === label) return;
18047
+ body = { id: id, label: next };
18048
+ } else {
18049
+ if (!confirm('Remove the ' + label + ' button?')) return;
18050
+ body = { id: id };
18051
+ }
18052
+ b.disabled = true;
18053
+ err.textContent = '';
18054
+ api('POST', '/api/app/pins/' + act, body)
18055
+ .then(load).catch(function (e) { err.textContent = e.message; b.disabled = false; });
18056
+ });
18057
+ // Opening a pin leaves /app, which ends a voice turn under way (recording,
18058
+ // waiting on the answer, or reading it out). Ask first; idle opens at once.
18059
+ bar.addEventListener('click', function (ev) {
18060
+ var a = ev.target.closest('a.pin-btn');
18061
+ var V = window.AXVoice;
18062
+ var state = V && typeof V.state === 'function' ? V.state() : 'idle';
18063
+ if (!a || state === 'idle') return;
18064
+ if (!confirm('Open ' + a.textContent + '? The voice reply in progress will stop.')) ev.preventDefault();
18065
+ });
18066
+ document.addEventListener('visibilitychange', function () { if (!document.hidden) load(); });
18067
+ load();
18068
+ })();
18069
+ `,wd=`
18070
+ .pin-bar {
18071
+ display: flex; gap: 8px; overflow-x: auto; flex: none;
18072
+ padding: 4px calc(12px + env(safe-area-inset-right)) 8px calc(16px + env(safe-area-inset-left));
18073
+ scrollbar-width: none;
18074
+ }
18075
+ .pin-bar[hidden] { display: none; }
18076
+ .pin-bar::-webkit-scrollbar { display: none; }
18077
+ .pin-btn {
18078
+ flex: none; display: inline-flex; align-items: center; min-height: 40px; padding: 0 16px;
18079
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-pill);
18080
+ background: var(--ax-surface-2); color: var(--ax-text); text-decoration: none;
18081
+ font-size: var(--ax-fs-sm); font-weight: 600; white-space: nowrap;
18082
+ }
18083
+ .pin-btn:active { background: var(--ax-accent-t); }
18084
+ body:has(#tab-chat[aria-selected=false]) > .pin-bar { display: none; }
18085
+ .pn-card { margin-top: 12px; }
18086
+ .pn-list { margin-top: 8px; }
18087
+ .pn-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
18088
+ .pn-row > span:first-child { min-width: 0; overflow-wrap: anywhere; }
18089
+ .pn-acts { display: flex; gap: 6px; flex: none; }
18090
+ .pn-add summary { list-style: none; display: inline-flex; margin-top: 10px; cursor: pointer; min-height: 44px; align-items: center; }
18091
+ .pn-add summary::-webkit-details-marker { display: none; }
18092
+ .pn-add[hidden] { display: none; }
18093
+ .pn-card form { display: grid; gap: 10px; margin-top: 10px; }
18094
+ .pn-card label span { display: block; font-weight: 600; margin-bottom: 4px; font-size: var(--ax-fs-sm); }
18095
+ .pn-card input {
18096
+ width: 100%; box-sizing: border-box; min-height: 44px; padding: 8px 10px; font: inherit;
18097
+ border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm); background: var(--ax-surface-2); color: var(--ax-text);
18098
+ }
18099
+ `;var kd=`
17941
18100
  (function () {
17942
18101
  var panel = document.getElementById('panel-alerts');
17943
18102
  if (!panel) return;
@@ -18050,7 +18209,7 @@ details[open] > summary::before { transform: rotate(90deg); }
18050
18209
  }
18051
18210
  load();
18052
18211
  })();
18053
- `;var xc=`
18212
+ `;var _d=`
18054
18213
  (function () {
18055
18214
  var panel = document.getElementById('panel-chat');
18056
18215
  var V = window.AXChatView;
@@ -18333,7 +18492,7 @@ details[open] > summary::before { transform: rotate(90deg); }
18333
18492
  var last = recall('ax-chat-conv');
18334
18493
  if (!fromHash() && last) openConversation(last);
18335
18494
  })();
18336
- `;var bc=`
18495
+ `;var Sd=`
18337
18496
  window.AXChatView = (function () {
18338
18497
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
18339
18498
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -18614,7 +18773,7 @@ window.AXChatView = (function () {
18614
18773
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
18615
18774
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
18616
18775
  })();
18617
- `;var vc=`
18776
+ `;var Ed=`
18618
18777
  window.AXChatSheets = function (o) {
18619
18778
  var V = o.V, picker = o.picker, hist = o.hist;
18620
18779
  function loadPicker() {
@@ -18660,7 +18819,7 @@ window.AXChatSheets = function (o) {
18660
18819
  });
18661
18820
  return { loadPicker: loadPicker, loadHistory: loadHistory };
18662
18821
  };
18663
- `;var yc=`
18822
+ `;var Td=`
18664
18823
  window.AXChatLog = function (o) {
18665
18824
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
18666
18825
  function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
@@ -18723,7 +18882,7 @@ window.AXChatLog = function (o) {
18723
18882
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
18724
18883
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
18725
18884
  };
18726
- `;var wc=`
18885
+ `;var Ad=`
18727
18886
  (function () {
18728
18887
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
18729
18888
  var top = panel && panel.querySelector('.cx-top');
@@ -18873,7 +19032,7 @@ window.AXChatLog = function (o) {
18873
19032
  window.AXStrip = { poll: poll, update: update, banner: banner };
18874
19033
  poll();
18875
19034
  })();
18876
- `;var kc=`
19035
+ `;var Cd=`
18877
19036
  .cs { margin: 0 -2px; }
18878
19037
  .cs[hidden] { display: none; }
18879
19038
  .cs-list {
@@ -18929,7 +19088,7 @@ window.AXChatLog = function (o) {
18929
19088
  @media (prefers-reduced-motion: reduce) {
18930
19089
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
18931
19090
  }
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=`
19091
+ `;function Id(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 Md(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Rd=`
18933
19092
  body { height: 100dvh; }
18934
19093
  main { min-height: 0; }
18935
19094
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -19039,7 +19198,7 @@ main { min-height: 0; }
19039
19198
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
19040
19199
  }
19041
19200
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
19042
- `;var Tc=`
19201
+ `;var Ld=`
19043
19202
  window.AXOrb = (function () {
19044
19203
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
19045
19204
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -19156,7 +19315,7 @@ window.AXOrb = (function () {
19156
19315
  }
19157
19316
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
19158
19317
  })();
19159
- `;var Ac=`
19318
+ `;var Pd=`
19160
19319
  window.AXVoiceIO = (function () {
19161
19320
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
19162
19321
  var ac = null, playing = null;
@@ -19274,7 +19433,7 @@ window.AXVoiceIO = (function () {
19274
19433
 
19275
19434
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
19276
19435
  })();
19277
- `;var Cc=`
19436
+ `;var $d=`
19278
19437
  (function () {
19279
19438
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
19280
19439
  if (!panel || !C || !IO || !O) return;
@@ -19487,7 +19646,7 @@ window.AXVoiceIO = (function () {
19487
19646
  idle();
19488
19647
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
19489
19648
  })();
19490
- `;var Ic=`
19649
+ `;var jd=`
19491
19650
  .vx {
19492
19651
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
19493
19652
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -19523,7 +19682,7 @@ window.AXVoiceIO = (function () {
19523
19682
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
19524
19683
  .cx-typing-on .vx-row { gap: 16px; }
19525
19684
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
19526
- `;var Mc=`
19685
+ `;var Od=`
19527
19686
  <main class="card">
19528
19687
  <h1>This phone isn't paired</h1>
19529
19688
  <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>
@@ -19537,7 +19696,7 @@ window.AXVoiceIO = (function () {
19537
19696
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
19538
19697
  </form>
19539
19698
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
19540
- </main>`,Rc=`
19699
+ </main>`,Nd=`
19541
19700
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
19542
19701
  .pair-form label { font-weight: 600; }
19543
19702
  .pair-form input {
@@ -19559,7 +19718,7 @@ window.AXVoiceIO = (function () {
19559
19718
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
19560
19719
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
19561
19720
  }
19562
- `,Lc=`
19721
+ `,Dd=`
19563
19722
  (function () {
19564
19723
  var form = document.getElementById('pair-form');
19565
19724
  var input = document.getElementById('pair-code');
@@ -19651,7 +19810,7 @@ window.AXVoiceIO = (function () {
19651
19810
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
19652
19811
  }
19653
19812
  })();
19654
- `;var Pc=`
19813
+ `;var Hd=`
19655
19814
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
19656
19815
  <video id="scan-video" playsinline muted autoplay></video>
19657
19816
  <div class="scan-frame" aria-hidden="true"></div>
@@ -19660,7 +19819,7 @@ window.AXVoiceIO = (function () {
19660
19819
  <button type="button" id="scan-close" class="scan-close">Close</button>
19661
19820
  </div>
19662
19821
  <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>
19663
- </div>`,$c=`
19822
+ </div>`,Bd=`
19664
19823
  .pair-form .scan-btn {
19665
19824
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
19666
19825
  }
@@ -19689,7 +19848,7 @@ window.AXVoiceIO = (function () {
19689
19848
  }
19690
19849
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
19691
19850
  body.scanning { overflow: hidden; }
19692
- `,jc=`
19851
+ `,qd=`
19693
19852
  (function () {
19694
19853
  var openBtn = document.getElementById('scan-btn');
19695
19854
  var box = document.getElementById('scan');
@@ -19914,7 +20073,7 @@ body.scanning { overflow: hidden; }
19914
20073
  @keyframes cam-pulse { 50% { opacity: .3; } }
19915
20074
  @media (prefers-reduced-motion: reduce) { .cam-live.is-stream .cam-dot { animation: none; } }
19916
20075
  #cam-stream[aria-pressed="true"] { border-color: var(--ax-red); color: var(--ax-red-ink); }
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=`
20076
+ `;var zd='<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>',Fd=`
19918
20077
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
19919
20078
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
19920
20079
  <span class="cam-dot" aria-hidden="true"></span>
@@ -19943,7 +20102,7 @@ body.scanning { overflow: hidden; }
19943
20102
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
19944
20103
  </div>
19945
20104
  </div>
19946
- </div>`,Dc=`
20105
+ </div>`,Ud=`
19947
20106
  (function () {
19948
20107
  var btn = document.getElementById('cam-btn');
19949
20108
  var sheet = document.getElementById('cam');
@@ -20417,7 +20576,7 @@ body.scanning { overflow: hidden; }
20417
20576
  });
20418
20577
  window.addEventListener('pagehide', function () { stop(); });
20419
20578
  })();
20420
- `;var Hc=`
20579
+ `;var Wd=`
20421
20580
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
20422
20581
  <div class="cam-askbar-text">
20423
20582
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -20427,7 +20586,7 @@ body.scanning { overflow: hidden; }
20427
20586
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
20428
20587
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
20429
20588
  </div>
20430
- </div>`,Bc=`
20589
+ </div>`,Gd=`
20431
20590
  .cam-askbar[hidden] { display: none; }
20432
20591
  .cam-askbar {
20433
20592
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -20442,7 +20601,7 @@ body.scanning { overflow: hidden; }
20442
20601
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
20443
20602
  }
20444
20603
  .cam-askbar-no { background: transparent; color: #fff; }
20445
- `,qc=`
20604
+ `,Xd=`
20446
20605
  (function () {
20447
20606
  var bar = document.getElementById('cam-ask-bar');
20448
20607
  if (!bar) return;
@@ -20512,7 +20671,7 @@ body.scanning { overflow: hidden; }
20512
20671
  setInterval(poll, 5000);
20513
20672
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
20514
20673
  })();
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=`
20674
+ `;function Kd(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 Jd(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 Vd(t){return t>=400?"send":"listen"}function Yd(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var Qd=`
20516
20675
  (function () {
20517
20676
  var main = document.querySelector('main');
20518
20677
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
@@ -20631,7 +20790,7 @@ body.scanning { overflow: hidden; }
20631
20790
  main.addEventListener('touchend', function () { end(false); });
20632
20791
  main.addEventListener('touchcancel', function () { end(true); });
20633
20792
  })();
20634
- `,Xc=`
20793
+ `,Zd=`
20635
20794
  main { position: relative; }
20636
20795
  main.sw-on { overflow: hidden; }
20637
20796
  .sw-on > [role=tabpanel] { will-change: transform; }
@@ -20642,8 +20801,8 @@ main > .sw-peek {
20642
20801
  }
20643
20802
  main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
20644
20803
  @media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
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})}
20804
+ `;function ec(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 tc(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function ac(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function nc(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=`
20805
+ ${z({afterUnauthorized:ts})}
20647
20806
  var CACHE = 'agentx-app-v3';
20648
20807
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
20649
20808
  self.addEventListener('install', function (e) {
@@ -20734,7 +20893,7 @@ self.addEventListener('notificationclick', function (e) {
20734
20893
  return self.clients.openWindow(target);
20735
20894
  }));
20736
20895
  });
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">
20896
+ `;var Ph="<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">
20738
20897
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
20739
20898
  <meta name="theme-color" content="#2979FF">
20740
20899
  <meta name="referrer" content="no-referrer">
@@ -20745,41 +20904,43 @@ self.addEventListener('notificationclick', function (e) {
20745
20904
  <link rel="icon" type="image/png" href="/app/icon-192.png">
20746
20905
  <link rel="apple-touch-icon" href="/app/icon-192.png">
20747
20906
  <title>${t}</title>
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"}>
20907
+ ${Ph}
20908
+ <style>${Ue}${ld}${Nh}</style>`}var $h={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"},rc=[{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 oc(){let t=rc.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="${$h[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=rc.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20750
20909
  <h2>${a.label}</h2>
20751
20910
  <p class="soon">${a.soon}</p>
20752
20911
  </section>`).join("");return`<!doctype html>
20753
20912
  <html lang="en">
20754
- <head>${_n("AgentX")}<style>${Ph}${cc}${pc}${Ec}${kc}${Ic}${wn}${Bc}${Xc}${fc}${sc}</style></head>
20913
+ <head>${_n("AgentX")}<style>${Dh}${ud}${fd}${Rd}${Cd}${jd}${wn}${Gd}${Zd}${xd}${dd}${wd}</style></head>
20755
20914
  <body>
20756
20915
  <header class="bar">
20757
20916
  <div>
20758
20917
  <h1>AgentX</h1>
20759
20918
  <p id="who" class="who">Connecting\u2026</p>
20760
20919
  </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>
20920
+ <div class="bar-btns">${zd}<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>
20762
20921
  </header>
20922
+ ${vd}
20763
20923
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
20764
- ${Hc}
20924
+ ${Wd}
20765
20925
  <main>${e}</main>
20766
20926
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
20767
- ${Nc}
20768
- <script>${Mh}</script>
20769
- <script>${z({swipeMayStart:Kc,swipeAxis:Jc,swipeOffset:Vc,swipeLanding:Yc})}${Gc}</script>
20770
- <script>${ic}</script>
20771
- <script>${lc}</script>
20772
- <script>${dc}</script>
20773
- <script>${uc}</script>
20774
- <script>${z({locationErrorText:hc})}${mc}</script>
20775
- <script>${gc}</script>
20776
- <script>${z({markdownToHtml:pr})}${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>
20927
+ ${Fd}
20928
+ <script>${jh}</script>
20929
+ <script>${z({swipeMayStart:ec,swipeAxis:tc,swipeOffset:ac,swipeLanding:nc})}${Qd}</script>
20930
+ <script>${cd}</script>
20931
+ <script>${pd}</script>
20932
+ <script>${md}</script>
20933
+ <script>${hd}</script>
20934
+ <script>${z({locationErrorText:bd})}${gd}</script>
20935
+ <script>${yd}</script>
20936
+ <script>${kd}</script>
20937
+ <script>${z({markdownToHtml:ur})}${Sd}${Td}${Ed}${_d}</script>
20938
+ <script>${z({queueSpeech:Id,nextSpeech:Md})}${Ld}${Pd}${$d}</script>
20939
+ <script>${Ad}</script>
20940
+ <script>${z({cameraConstraints:Kd,shareClock:Jd,streamLabel:Yd,talkRelease:Vd})}${Ud}</script>
20941
+ <script>${Xd}</script>
20781
20942
  </body>
20782
- </html>`}function ed(){return`<!doctype html>
20943
+ </html>`}function sc(){return`<!doctype html>
20783
20944
  <html lang="en">
20784
20945
  <head>${_n("Pair \xB7 AgentX")}</head>
20785
20946
  <body>
@@ -20787,17 +20948,17 @@ ${Nc}
20787
20948
  <h1>Pairing this phone\u2026</h1>
20788
20949
  <p id="msg" role="status">One moment.</p>
20789
20950
  </main>
20790
- <script>${Rh}</script>
20951
+ <script>${Oh}</script>
20791
20952
  </body>
20792
- </html>`}function td(){return`<!doctype html>
20953
+ </html>`}function ic(){return`<!doctype html>
20793
20954
  <html lang="en">
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>
20955
+ <head>${_n("Not paired \xB7 AgentX")}<style>${Nd}${Bd}</style></head>
20956
+ <body>${Od}${Hd}
20957
+ <script>${z({mayBounce:as,formatPairInput:Xt,parsePairScan:ns})}</script>
20958
+ <script>${Dd}</script>
20959
+ <script>${qd}</script>
20799
20960
  </body>
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=`
20961
+ </html>`}function lc(){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 jh=`
20801
20962
  (function () {
20802
20963
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
20803
20964
  function select(tab, focus, keepHash) {
@@ -20869,7 +21030,7 @@ ${Nc}
20869
21030
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
20870
21031
  }
20871
21032
  })();
20872
- `,Rh=`
21033
+ `,Oh=`
20873
21034
  (function () {
20874
21035
  var msg = document.getElementById('msg');
20875
21036
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -20886,7 +21047,7 @@ ${Nc}
20886
21047
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
20887
21048
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
20888
21049
  })();
20889
- `,Lh=`
21050
+ `,Nh=`
20890
21051
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
20891
21052
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
20892
21053
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -20898,7 +21059,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
20898
21059
  .card h1 { font-size: 22px; margin: 0 0 12px; }
20899
21060
  .muted { color: var(--ax-text-2); }
20900
21061
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
20901
- `,Ph=`
21062
+ `,Dh=`
20902
21063
  body { display: flex; flex-direction: column; }
20903
21064
  .bar {
20904
21065
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -20936,8 +21097,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20936
21097
  }
20937
21098
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
20938
21099
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
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 Sr(t,e,a,n,s.name,r.fleet)||r.desk&&await xl(t,e,a,n,r.desk)||r.push&&await Er(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."})+`
21100
+ `;var ua="agentx_app",qh=400*86400,zh=new Rt,Fh=new Re;async function dc(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",lc());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",sc());if(a==="/app/qr.js"){let i=Uh();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(pt(t),o);return i?(e.setHeader("Set-Cookie",En(pt(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 $r(t,{codes:r.pairCodes??new At,limiter:r.pairLimiter??zh,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(Wh(t),o);if(!s){let i=pt(t);return(r.rejectLog??Fh).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",ic()):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&&!pt(t)&&e.setHeader("Set-Cookie",En(i)),fe(e,200,"text/html; charset=utf-8",oc())}return n==="GET"&&a==="/api/app/me"?Ee(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Er(t,e,a,n,s.name,r.fleet)||r.desk&&await yl(t,e,a,n,r.desk)||r.push&&await Tr(t,e,a,n,s,r.push)||r.announce&&await _l(t,e,a,n,s,r.announce)||r.chat&&await $l(t,e,a,n,s,r.chat)||r.chat&&await Dl(t,e,a,n,s,r.chat)||r.voice&&await ql(t,e,a,n,s,r.voice)||r.camera&&await Fl(t,e,a,n,r.camera)||r.places&&await nd(t,e,a,n,s,r.places)||r.pins&&await po(t,e,a,n,r.pins)?!0:Ee(e,404,{error:"not found"})}var ct;function Uh(){if(ct!==void 0)return ct;try{let t=Bh(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
21101
+ `;ct=Buffer.concat([Buffer.from(a),Hh(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=${qh}; HttpOnly; Secure; SameSite=Lax`}function Wh(t){return pt(t)??Tn(t,ua)}function pt(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 cc(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."})+`
20941
21102
  <div class="pl-wrap">
20942
21103
  <div id="pl-msg" class="pl-msg" role="status" aria-live="polite"></div>
20943
21104
  <form id="pl-add" class="pl-form" autocomplete="off">
@@ -20949,7 +21110,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20949
21110
  <button type="submit" class="ax-btn ax-btn--primary">Add place</button>
20950
21111
  </form>
20951
21112
  <ol id="pl-list" class="pl-list" aria-label="Places"><li class="pl-empty">Loading\u2026</li></ol>
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=`
21113
+ </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:Gh,scripts:`<script>${Xh}</script>`})}var Gh=`
20953
21114
  .pl-wrap { max-width: 1040px; margin: 0 auto; padding: 0 24px 96px; box-sizing: border-box; }
20954
21115
  .pl-msg { min-height: 1.4em; margin: 8px 0 0; }
20955
21116
  .pl-msg.is-bad { color: var(--ax-red-ink); }
@@ -20972,7 +21133,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20972
21133
  .pl-rule-form { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
20973
21134
  .pl-rule-form input[name=text] { flex: 1 1 240px; }
20974
21135
  .pl-btns { margin-left: auto; display: flex; gap: 8px; }
20975
- `,zh=`
21136
+ `,Xh=`
20976
21137
  (function () {
20977
21138
  var list = document.getElementById('pl-list');
20978
21139
  var msg = document.getElementById('pl-msg');
@@ -21051,7 +21212,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
21051
21212
  });
21052
21213
  load();
21053
21214
  })();
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 (
21215
+ `;import{randomBytes as pc}from"crypto";var Be={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:pe.perMessage},Kh=/^[a-f0-9]{32}$/,Jh=/^c[a-z0-9]{8,32}$/,Vh=/^#[0-9a-fA-F]{6}$/;function An(t){return Jh.test(t)}var ut=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
21055
21216
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
21056
21217
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
21057
21218
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -21064,39 +21225,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
21064
21225
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
21065
21226
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
21066
21227
  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 (
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.*,
21228
+ 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)}${pc(4).toString("hex")}`,{color:s,...i}=a,l=s&&Vh.test(s)?s:void 0,d={id:o,title:Qh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
21229
+ (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,d.title,d.node,d.nodeName,d.agent,d.agentName??null,l??null,r,r,r),this.pruneDevice(e),d}get(e,a){if(!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(Yh);return{...uc(n),messages:r}}list(e,a=Be.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
21069
21230
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
21070
21231
  (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
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,
21232
+ 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{...uc(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,
21072
21233
  substr(m.content, 1, 240) AS answer, m.status, m.at
21073
21234
  FROM app_chat_conversations c
21074
21235
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
21075
21236
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
21076
21237
  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)+`
21077
21238
 
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)
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)
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
21239
+ [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=pr(g);if(!k||!g||g.length>pe.pathChars||g.includes("\0"))continue;let b=(g.split(/[\\/]/).pop()||g).slice(0,120);l.push({id:pc(16).toString("hex"),name:b,mime:k.mime,kind:k.kind,path:g})}let d=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
21240
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,d.length?JSON.stringify(d):null,n.at),c=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
21241
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)c.run(m.id,a,Number(p.lastInsertRowid),m.path,m.name,m.mime,m.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
21081
21242
  (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
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
21243
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),d}getFile(e,a){if(!Kh.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
21083
21244
  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 = ?
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:mr(n.text,Rn),agent:n.agentId,askedAt:fa(n.createdAt),changedAt:fa(n.stateChangedAt??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.stateChangedAt??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(`
21245
+ 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 uc(t){return{id:t.id,title:t.title,node:t.node,nodeName:t.node_name,agent:t.agent,...t.agent_name?{agentName:t.agent_name}:{},...t.color?{color:t.color}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function Yh(t){let e=o=>{if(o)try{return JSON.parse(o)}catch{return}},a=e(t.ui),n=e(t.tools),r=e(t.files);return{role:t.role,content:t.content,at:t.at,...t.status?{status:t.status}:{},...t.error?{error:t.error}:{},...a?{ui:a}:{},...n?{tools:n}:{},...r?{files:r}:{}}}function Qh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Zh=4e3,Cn=100,eg=15,mc=t=>t.replace(/\/+$/,""),ma=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Zh){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??eg)-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||mc(l)!==mc(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let d=tg(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,d.row,d.declared)===null)return"skip";let c=d.row.status,m=!!this.deps.finishAlerts?.(s),g={status:c,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&da(g)&&this.deps.notifyFinish(ca(s,i,c,d.row.content,d.row.error)).catch(()=>{}),"filed"}};function tg(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:ag(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function ag(t){return t.replace(/\s+/g," ").trim().slice(0,300)}Xn();var ng=3,Mn=7,Rn=50,Ln=120,rg=280,In=600,hc=36e5,og=24*hc;function gc(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 et(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 sg(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:et(e.title,Ln),...e.ask?{ask:et(e.ask,In)}:{},...e.detail?{facts:et(e.detail,rg)}:{},...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 ig={done:"Done",declined:"Declined",dropped:"Dropped"};function lg(t,e,a){let{record:n,links:r}=e,o=fr(n,Ln),s={key:`request:${n.id}`,kind:"request",node:t.node,nodeName:t.nodeName,title:o.headline,need:o.need,...n.headline?{said:et(o.said,In)}:{},agent:n.agentId,askedAt:fa(n.createdAt),changedAt:fa(n.stateChangedAt??n.updatedAt)};switch(n.state){case"candidate":case"needs_attention":return null;case"waiting_owner":return r.some(i=>i.kind==="card"&&a.has(`card:${i.ref}`))?null:{...s,column:"yours",...n.question?{ask:et(n.question,In)}:{},can:{answer:!1,later:!1,reply:!0}};case"in_progress":case"waiting_other":{let i=r.some(d=>d.kind==="run"&&t.liveRuns.has(d.ref)),l=t.now-n.updatedAt<(t.quietHours??ng)*hc;return{...s,column:i||l?"agent":"quiet",...i?{live:i}:{},can:{answer:!1,later:!1,reply:!i}}}default:{let i=n.state==="done"?n.evidence:n.closeReason;return{...s,need:void 0,column:"done",changedAt:fa(n.closedAt??n.stateChangedAt??n.updatedAt),outcome:ig[n.state]??n.state,...i?{evidence:i}:{},can:{answer:!1,later:!1,reply:!1}}}}}function dg(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 cg(t,e){return{key:`card:${e.id}`,kind:"card",column:"done",node:t.node,nodeName:t.nodeName,title:et(e.title,Ln),ask:e.ask,agent:e.raised_by,askedAt:e.created_at,...e.decided_at?{changedAt:e.decided_at}:{},outcome:dg(e),...e.resolution?{evidence:e.resolution}:{},can:{answer:!1,later:!1,reply:!1}}}var de=t=>t&&Date.parse(t)||0,fc=(t,e)=>t.map(a=>a[e]).filter(a=>!!de(a)).sort((a,n)=>de(a)-de(n))[0];function xc(t){let e=[],a=[];for(let c of t.inbox){c.error&&a.push(`What waits on ${c.nodeName} could not be read: ${c.error}`);for(let m of c.items)e.push(sg(c,m,c.node===t.node))}let n=new Set([...e.filter(c=>c.node===t.node).map(c=>c.key),...t.deferred??[]]),r=[],o=[],s=[];for(let c of t.requests??[]){let m=lg(t,c,n);m&&{yours:e,agent:r,quiet:o,done:s}[m.column].push(m)}let i=t.now-(t.doneDays??Mn)*og;for(let c of t.cards)c.status!=="pending"&&de(c.decided_at)>=i&&s.push(cg(t,c));r.sort((c,m)=>de(m.changedAt)-de(c.changedAt)),o.sort((c,m)=>de(c.changedAt)-de(m.changedAt)),s.sort((c,m)=>de(m.changedAt)-de(c.changedAt));let l=s.filter(c=>de(c.changedAt)>=i).slice(0,Rn),d=fc(e,"askedAt"),p=fc(o,"changedAt");return{ts:fa(t.now),cards:[...e,...r,...o,...l],figures:{yours:{count:e.length,...d?{oldest:d}:{}},agent:{count:r.length},quiet:{count:o.length,...p?{oldest:p}:{}},done:{count:l.length}},errors:a}}function tt(){let t=bt();return t&&Se(t,"dashboard"),t}function V_(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,kg(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,d=new or(l?{baseDir:l}:void 0),p=new sr(l?{baseDir:l,nodeId:i}:{nodeId:i}),c=new ir(l?{baseDir:l}:void 0);Hi(t),tt(),Br({business:t.business?.enabled===!0});let m=pg(async(g,k)=>{try{await bg(g,k,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:c})}catch(b){w(k,500,{error:b.message||"internal error"})}});Bg(t).start(),m.listen(n,r,()=>{let g=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
21085
21246
  Live dashboard: http://${g}:${n}
21086
21247
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
21087
21248
  Kanban dashboard: http://${g}:${n}
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=gr(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 hr(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-FOKX4K2G.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
21249
+ `),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 xg=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 bg(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(Dr(t.headers)==="foreign"&&Hr(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 As(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>st(a.config.people),members:vc(a.config.members.logRetentionDays),db:()=>tt(),linkFor:(u,f)=>Jo(u,f,{gitlab:a.config.channels.gitlab?.host})})||await dc(t,e,r,o,{nodeName:a.config.node?.name,fleet:Dn(a.config),desk:Dg(a.config),push:Nn(a.config),announce:Sl(a.config),chat:Sc(a.config),voice:qg(a.config),camera:zg(a.config),places:bc(a.config),pins:co(a.config,process.cwd()),assetLinks:()=>id(a.config)}))return;let s=o==="GET"?Go(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"&&xg.has(r)&&_o("page",r),o==="GET"&&r==="/"){let u=oo();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(pl({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(No({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oo({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(Lo({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=xr(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 gr(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(sl({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cc({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(il({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(ul({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ml({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fl({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ro({}));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(hl({taskId:decodeURIComponent(l[1]),agentId:u,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:D(a.config)}));return}let d=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(d){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gl({agentId:decodeURIComponent(d[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){so(t,e);return}if(o==="POST"&&r==="/api/setup"){await io(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await lo(t,e);return}if(o==="GET"&&r==="/admin"){Ds(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){ei(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Gs(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}ci(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 Kg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await cn(t,e,r,v=>Tc(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 wc(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 wc(t,e,f,r+(v==="?"?"":v));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await pi(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Jg(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-T7QAQRCJ.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(hi({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await fi(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gi({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xi({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 Eg(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 Bi(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await cn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await zi(t,e,r))return;let p=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(p){Wi(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 Hs(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){w(e,200,Fr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await ti(t,e,r,n);return}if(await ni(t,e,r,{people:()=>st(a.config.people),members:vc(a.config.members.logRetentionDays),root:process.cwd(),db:()=>tt(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Xs(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Gi(t,e,r);return}if(r.startsWith("/api/admin/")){await Bs(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(Cs);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=Gg("web/"+u);try{let v=await Xg(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 at(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 at(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 ll(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 cl(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 dl(e,await Te(a.config),u,v)}catch(y){w(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){Lg(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 Pg(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 Og(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 Ng(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 Ug(a.config,u);w(e,200,f)}catch(f){w(e,502,{error:f.message||"draft failed"})}return}let c=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(c&&o==="POST"){let u=c[1];if(!$g(t,e,[`agent:${u}`]))return;await jg(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,zr(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 Tg(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 rd(t,e,r,o,bc(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
21089
21250
 
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(`
21251
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(x));for(let A of v)(async()=>{let L={Accept:"text/event-stream"};A.token&&(L.Authorization=`Bearer ${A.token}`);let _=new AbortController;E.push(_);try{let R=await fetch(`${A.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:L,signal:_.signal});if(!R.ok||!R.body)return;let j=R.body.getReader(),$=new TextDecoder,O="";for(;!y.flag;){let{done:W,value:ce}=await j.read();if(W)break;O+=$.decode(ce,{stream:!0});let Q;for(;(Q=O.indexOf(`
21091
21252
 
21092
21253
  `))>=0;){let oe=O.slice(0,Q);if(O=O.slice(Q+2),y.flag)break;try{e.write(oe+`
21093
21254
 
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,vr.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}
21096
- data: ${JSON.stringify(c)}
21255
+ `)}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:Io(),agents:Object.keys(a.config.agents??{}).sort()});if(o==="GET"){w(e,200,u());return}if(o!=="POST"){w(e,405,{error:"Method not allowed"});return}if(a.config.workflows?.editor!=="edit"){w(e,403,{error:"the workflow editor is read-only on this node (workflows.editor)"});return}let f=await re(t).catch(()=>({})),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 Mo(v);if(!y.success){w(e,400,{error:y.error});return}w(e,200,{ok:!0,reloaded:!!y.reloaded,...u()});return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),v=u.searchParams.get("workflowId")||void 0,y=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",E=a.workflowRuns.list({limit:f,workflowId:v}),x=`?limit=${f}${v?`&workflowId=${encodeURIComponent(v)}`:""}${y?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],L=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let W=new AbortController,ce=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${x}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let oe=await Q.json();return Array.isArray(oe.runs)?oe.runs:[]}finally{clearTimeout(ce)}}catch{return[]}})),_=new Map;for(let $ of E)_.set($.id,$);for(let $ of L)for(let O of $)_.set(O.id,O);let R=Array.from(_.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,f),j=y?R.map($=>wg($)):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")&&bl(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 yg(E,v,L,A),Pn({actor:$n(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 vg(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}Pn({actor:$n(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});Pn({actor:$n(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 vg(t,e,a){if(!e.capabilities.listAll||!e.listAll){let h={};for(let u of t.columns)h[u.id]=[];return{columns:h,totals:Object.fromEntries(t.columns.map(u=>[u.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(h=>h.kind!=="closed"),c=t.columns.some(h=>h.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],g=c?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let h of t.columns)k[h.id]=[];let b=t.columns.find(h=>h.kind==="closed");for(let h of g)b&&k[b.id].push({...h,stage:b.id});let S=t.columns.filter(h=>h.kind!=="closed");for(let h of m){let u=qn(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 yg(t,e,a,n){let r=zn(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 wg(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:dr(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function kg(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 Kr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Pn(t){try{let e=mt(process.cwd(),".agentx");kc(e)||mg(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
21256
+ `;ug(mt(e,"board-audit.jsonl"),a)}catch{}}function $n(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var _g=2e3;async function Sg(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(),_g),v=()=>u.abort();return a?.addEventListener("abort",v,{once:!0}),fetch(t+h,{headers:r,signal:u.signal}).then(async y=>{let E=y.ok?await y.json().catch(()=>{}):void 0;return{ok:E!==void 0,json:async()=>E}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",v)})},[l,d,p,c,m,g,k,b,S]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions"),i("/api/signals/stopped?limit=20")]);if(!d||!d.ok)return o.error=d?`HTTP ${d.status}`:"unreachable",o;let T=await d.json();if(o.agents=T.map(h=>({id:h.id,name:h.name,tier:h.tier,model:h.model,...typeof h.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(h.color)?{color:h.color}:{},skillCount:Number.isFinite(h.skillCount)?h.skillCount:void 0,active:h.active||0,total:h.total||0,errors:h.errors||0,lastActive:h.lastActive,lastSummary:h.lastSummary,hourlyTasks:Array.isArray(h.hourlyTasks)?h.hourlyTasks:void 0,runningTasks:Array.isArray(h.runningTasks)?h.runningTasks:[]})),l&&l.ok){let h=await l.json().catch(()=>({}));o.uptimeSec=h.uptime,typeof h.inflight?.total=="number"&&(o.inflight=h.inflight.total),h.restart&&typeof h.restart.state=="string"&&(o.restart=h.restart),o.name=h.node?.name||h.node?.id||t,o.id=h.node?.id||t,h.usage&&(o.usage=h.usage)}if(S&&S.ok){let h=await S.json().catch(()=>({})),u=Array.isArray(h?.tasks)?h.tasks:[];o.stoppedTasks=u.filter(f=>f&&f.state!=="resumed").slice(0,10).map(f=>({id:String(f.id),agentId:String(f.agentId),channel:String(f.channel??""),chatId:String(f.chatId??""),state:String(f.state),stoppedAt:String(f.stoppedAt),stoppedBy:String(f.stoppedBy??""),reason:typeof f.reason=="string"?f.reason:void 0,request:String(f.request??""),plan:f.plan&&typeof f.plan.text=="string"?{author:String(f.plan.author),text:f.plan.text,note:f.plan.note}:void 0,resumable:f.resumable===!0,...f.workflow&&typeof f.workflow.runId=="string"?{workflow:{runId:f.workflow.runId,workflowId:String(f.workflow.workflowId??""),nodeId:String(f.workflow.nodeId??"")}}:{}}))}if(c&&c.ok){let h=await c.json().then(u=>Array.isArray(u)?u:[],()=>[]);o.crons=h.map(u=>({id:u.id,enabled:u.enabled===!0,schedule:String(u.schedule||""),timezone:u.timezone,agent:String(u.agent||""),kind:typeof u.command=="string"&&u.command.trim()?"command":"agent",model:u.model,nextRun:u.nextRun,retryPending:u.retryPending===!0,consecutiveErrors:Number(u.consecutiveErrors)||0}))}if(m&&m.ok){let h=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(h.runs)?h.runs:[]}if(k&&k.ok){let h=await k.json().catch(()=>null);h&&Array.isArray(h.routines)&&(o.routines=h.routines.slice(0,yr.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)&&Rg(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 Eg(t){if(ha)return ha;let e=mt(process.cwd(),".agentx/wiki");return ha=Co({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 Tg(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 Ag=3e3,Cg=6e3,Ig=5*6e4,On=new Map,ga=new Map;function at(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(Ag)),s=await Promise.all(o.map(async i=>{let l=await Sg(i.url,i.token,AbortSignal.timeout(Cg),e);return e?l:Mg(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ga.delete(a));return ga.set(a,r),r}function Mg(t,e,a=Date.now()){if(e.reachable&&!e.error)return On.set(t,{node:e,at:a}),e;let n=On.get(t);return!n||a-n.at>Ig?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Y_(){On.clear(),ga.clear()}function Rg(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 Lg(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,d)=>{n||e.write(`event: ${l}
21257
+ data: ${JSON.stringify(d)}
21097
21258
 
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=Ar(e.keysFile);return{store:()=>{let r=et();return r?new Zr(r):null},publicKey:()=>Cr(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=Ir(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(Mr(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 Tr.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=`
21259
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await at(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 Pg(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await ba(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let b of k)i.add(b.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,c;try{c=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(k){w(e,502,{error:k.message||"upstream connect failed"});return}if(!c.ok||!c.body){w(e,c.status||502,{error:`upstream HTTP ${c.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=c.body.getReader();(async()=>{try{for(;;){let{value:k,done:b}=await m.read();if(b)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function $g(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 jg(t,e,a,n){let r=a.agents?.[n];if(!r){w(e,404,{error:"unknown agent"});return}if(r.access!=="public"){w(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await re(t)}catch{w(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){w(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(d){w(e,502,{error:d.message||"upstream call failed"})}}async function Og(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of e.config.dashboard.daemons)i.add(c.url.replace(/\/+$/,""));try{let c=await ba(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of c)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let c=await fetch(`${s}${p}`,{headers:d}),m=await c.text();t.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(c){w(t,502,{error:c.message||"upstream fetch failed"})}}async function Ng(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 _c(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function _c(t,e,a,n){let r=(d,p)=>({status:d,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await ba(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of d)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function Nn(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=Cr(e.keysFile);return{store:()=>{let r=tt();return r?new eo(r):null},publicKey:()=>Ir(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function bc(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?ad({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}.`:Nn(t).reason;return sd(t,process.cwd(),n,r)}function Dn(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>at(t,n),async nodePost(n,r,o){let s=await _c(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(yc)}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 d=await l.json();s.items=(d.items??[]).map(yc)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s,i={}){let l=n.replace(/\/+$/,"");if(l===e){let p=Ie(),c=await Mt({root:process.cwd()},r,o,{laterHours:p.laterHours,by:s,...i});return c.ok?{status:200,body:{ok:!0,message:c.message}}:{status:409,body:{error:c.error}}}let d=ft(l,t);if(!d)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let p=await fetch(`${d.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:JSON.stringify({key:r,action:o,...i}),signal:AbortSignal.timeout(1e4)});return{status:p.status,body:a(await p.text())}}catch(p){return{status:502,body:{error:p.message||"peer dashboard unreachable"}}}}}}function Dg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=Dn(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=gc(l.agents);let d=Date.now(),p=null;try{let k=ze(n);k&&(p=[...k.listOpen(),...k.listClosedSince(d-Mn*864e5,Rn)].map(b=>({record:b,links:k.links(b.id)})))}catch(k){i.push(`Requests could not be read: ${k.message}`)}let c=[];try{c=Mr(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(Rr(n.root).snoozed).filter(([,k])=>Date.parse(k)>d).map(([k])=>k)),g=xc({now:d,node:e,nodeName:t.node?.name||"this computer",inbox:r,requests:p,cards:c,liveRuns:s,deferred:m});return{...g,errors:[...g.errors,...i]}},async reply(r,o){return ta("POST",`${xe}/reply`,{id:r,text:o},n)}}}var jn=null;function vc(t){return jn?.days!==t&&(jn={days:t,store:new wt(process.cwd(),Date.now,t)}),jn.store}function Sc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Dn(t);return{store:()=>{let r=tt();return r?new ut(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:Ea(process.cwd())??void 0},snapshot:()=>at(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(/\/+$/,"")),...Hg(t,e,a)}}function Hg(t,e,a){let n=Nn(t);return{finishAlerts:r=>{if(n.forward)return Ar.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}
21260
+ ${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 Bg(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=Sc(t);return new ma({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let d=await l.json();return{events:Array.isArray(d.events)?d.events:[],gap:d.gap===!0}},nodeUrl:async o=>{let i=(await at(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:Pl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function qg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=tt();return a?new ut(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function zg(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function yc(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 Fg=`
21100
21261
  You are helping draft a new GitLab issue. Follow these conventions strictly.
21101
21262
 
21102
21263
  Title pattern:
@@ -21128,16 +21289,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
21128
21289
  Shape:
21129
21290
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
21130
21291
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
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):
21292
+ `;async function Ug(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):
21132
21293
  - ${r.knownLabels.slice(0,60).join(`
21133
21294
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
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}
21295
+ `),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:Fg}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let p=(d.content||"").toString(),c=Wg(p);if(!c||typeof c.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(c.labels)?c.labels.filter(g=>typeof g=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:c.title.trim(),description:(c.description||"").toString(),labels:m,assigneeUsername:typeof c.assigneeUsername=="string"?c.assigneeUsername:void 0,kind:typeof c.kind=="string"?c.kind:void 0,raw:p}}function Wg(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 Gg(t){let e=gg(hg(import.meta.url));return mt(e,t)}async function Xg(t){return fg(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 Ec(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:Ec(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 Kg(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 Tc(r,a.config)))}async function Tc(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=dn(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 d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let c=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return c.ok?{nodeId:i.name||i.url,snap:await c.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Ni(n)}async function Jg(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let c=process.env.HOME||"",m=[c&&`${c}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),g=m.find(k=>kc(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}
21135
21296
 
21136
- `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=d=>{i+=d.toString("utf8");let m;for(;(m=i.indexOf(`
21297
+ `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=c=>{i+=c.toString("utf8");let m;for(;(m=i.indexOf(`
21137
21298
  `))>=0;){let g=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
21138
21299
  data: ${g.replace(/\n/g," ")}
21139
21300
 
21140
- `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
21301
+ `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
21141
21302
 
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-5V6RHW3E.js.map
21303
+ `)}catch{}},15e3),p=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function wc(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((c,m)=>{let g=[];t.on("data",k=>g.push(k)),t.on("end",()=>c(Buffer.concat(g))),t.on("error",m)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let c=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await c.arrayBuffer());e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(c){w(e,502,{error:`proxy to peer failed: ${c?.message||c}`,target:r})}}function ft(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Ec(n),token:n.dashboardToken||n.token}:null}export{Rg as applyAttachSessions,Sg as fetchDaemonAgents,bg as handleBoardRequest,Y_ as resetLiveCaches,Te as resolveNodeTargets,V_ as startBoardDashboard,Mg as withLastGood};
21304
+ //# sourceMappingURL=board-dashboard-POWARL34.js.map