agentix-cli 0.122.0 → 0.124.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 (120) hide show
  1. package/dist/{App-2D5W26LY.js → App-BUYK4EGC.js} +2 -2
  2. package/dist/{ChatApp-FZFZD2XY.js → ChatApp-ZS6EPDDK.js} +2 -2
  3. package/dist/{agent-PCRE3TRK.js → agent-W7UNXO6L.js} +2 -2
  4. package/dist/{board-dashboard-ZDJ4UDW4.js → board-dashboard-3AOENRSG.js} +292 -226
  5. package/dist/board-dashboard-3AOENRSG.js.map +1 -0
  6. package/dist/{chunk-XLCUHG3N.js → chunk-46ACP7A7.js} +71 -69
  7. package/dist/chunk-46ACP7A7.js.map +1 -0
  8. package/dist/{chunk-ZLUROC2Y.js → chunk-46JKX6CT.js} +17 -17
  9. package/dist/chunk-46JKX6CT.js.map +1 -0
  10. package/dist/{chunk-ZWZADDXV.js → chunk-5DFUUYEA.js} +2 -2
  11. package/dist/{chunk-NFS2VR3L.js → chunk-5RE2B5YQ.js} +2 -2
  12. package/dist/{chunk-NYAMY7EA.js → chunk-6GLJIA25.js} +2 -2
  13. package/dist/{chunk-5SLTRG66.js → chunk-6HKLRU62.js} +2 -2
  14. package/dist/{chunk-XBRVV4ZT.js → chunk-6PJ6XHG4.js} +2 -2
  15. package/dist/{chunk-54XX2LSW.js → chunk-AKLZ4YO2.js} +4 -4
  16. package/dist/{chunk-54XX2LSW.js.map → chunk-AKLZ4YO2.js.map} +1 -1
  17. package/dist/{chunk-TYFGL2YS.js → chunk-B3B7KEHJ.js} +2 -2
  18. package/dist/{chunk-EHKI2RKD.js → chunk-BN5QMNON.js} +2 -2
  19. package/dist/{chunk-2UDSIG5K.js → chunk-BSTIA4M6.js} +2 -2
  20. package/dist/{chunk-YCMO3KZ4.js → chunk-CY6ABHF2.js} +2 -2
  21. package/dist/{chunk-BRVQZC6P.js → chunk-FHBPKMCF.js} +2 -2
  22. package/dist/{chunk-C52IPIKJ.js → chunk-INLKJEEN.js} +2 -2
  23. package/dist/chunk-ITATBKUL.js +37 -0
  24. package/dist/chunk-ITATBKUL.js.map +1 -0
  25. package/dist/{chunk-DMPTCBX6.js → chunk-K5QUQNFE.js} +3 -3
  26. package/dist/chunk-K5QUQNFE.js.map +1 -0
  27. package/dist/{chunk-UVV6GUOG.js → chunk-PAM56O25.js} +257 -254
  28. package/dist/chunk-PAM56O25.js.map +1 -0
  29. package/dist/{chunk-SB7WMFJV.js → chunk-QQYXYJOG.js} +2 -2
  30. package/dist/{chunk-WJDFR3WE.js → chunk-VHT7HESZ.js} +2 -2
  31. package/dist/{chunk-QCPSGOSK.js → chunk-WEPON4FP.js} +2 -2
  32. package/dist/{chunk-XX6MLDTL.js → chunk-WMTGAVPW.js} +2 -2
  33. package/dist/{chunk-YUNMSLZN.js → chunk-YL4C63S2.js} +2 -2
  34. package/dist/{chunk-7ZGTRXWS.js → chunk-YSIRJZWF.js} +2 -2
  35. package/dist/cli.js +1 -1
  36. package/dist/{client-TFZEASIJ.js → client-PO5LDFS4.js} +2 -2
  37. package/dist/config-L2RQ6EJX.js +2 -0
  38. package/dist/config-mutator-44OAOZXM.js +2 -0
  39. package/dist/doctor-AU5TCOSG.js +2 -0
  40. package/dist/{editor-chat-4MLCP5D2.js → editor-chat-ELKNLXM6.js} +10 -3
  41. package/dist/{editor-chat-4MLCP5D2.js.map → editor-chat-ELKNLXM6.js.map} +1 -1
  42. package/dist/follow-up-tool-AIOLNUF7.js +6 -0
  43. package/dist/follow-up-tool-AIOLNUF7.js.map +1 -0
  44. package/dist/{grants-NGBKFONG.js → grants-HIFE6L5N.js} +2 -2
  45. package/dist/index.d.ts +80 -3
  46. package/dist/index.js +1 -1
  47. package/dist/{program-CGPPGRMR.js → program-EJWE7NVT.js} +221 -221
  48. package/dist/program-EJWE7NVT.js.map +1 -0
  49. package/dist/{promote-VTVIPRTC.js → promote-DPPNEINZ.js} +2 -2
  50. package/dist/push-bridge-325SXDGN.js +1 -1
  51. package/dist/{query-3CVDT2GZ.js → query-SLUOL6MQ.js} +2 -2
  52. package/dist/{registry-NOJMMWE3.js → registry-UBVBEEDW.js} +2 -2
  53. package/dist/{request-planner-E2Q5O66N.js → request-planner-2G73AJ4S.js} +2 -2
  54. package/dist/{review-candidates-I36HEYKX.js → review-candidates-S34UICQD.js} +2 -2
  55. package/dist/routing-K2LAUFRL.js +2 -0
  56. package/dist/schedule-tool-YRANRFHO.js +2 -0
  57. package/dist/scheduler-L4P4Z55R.js +2 -0
  58. package/dist/{seat-NGY2BMP6.js → seat-ZJT5T2NO.js} +2 -2
  59. package/dist/{select-X7VBGZ6X.js → select-Y23SKHCJ.js} +2 -2
  60. package/dist/{set-enabled-6NP63KCU.js → set-enabled-YWXWSKME.js} +2 -2
  61. package/dist/{tool-EZIILXYL.js → tool-5JTCSRTW.js} +2 -2
  62. package/dist/{tool-WKIF52OH.js → tool-FZEC5FQX.js} +2 -2
  63. package/dist/web/workflow-editor.global.js +1 -1
  64. package/dist/web/workflow-editor.global.js.map +1 -1
  65. package/dist/wiki-ZZ3MU5Y5.js +2 -0
  66. package/package.json +1 -1
  67. package/dist/board-dashboard-ZDJ4UDW4.js.map +0 -1
  68. package/dist/chunk-DMPTCBX6.js.map +0 -1
  69. package/dist/chunk-TLCURHW3.js +0 -28
  70. package/dist/chunk-TLCURHW3.js.map +0 -1
  71. package/dist/chunk-UVV6GUOG.js.map +0 -1
  72. package/dist/chunk-XLCUHG3N.js.map +0 -1
  73. package/dist/chunk-ZLUROC2Y.js.map +0 -1
  74. package/dist/config-IXCOAOPZ.js +0 -2
  75. package/dist/config-mutator-EPYIZVSG.js +0 -2
  76. package/dist/doctor-G5TM5GVF.js +0 -2
  77. package/dist/program-CGPPGRMR.js.map +0 -1
  78. package/dist/routing-KBUZON5R.js +0 -2
  79. package/dist/schedule-tool-GUHHYYTO.js +0 -2
  80. package/dist/scheduler-PGUELFMB.js +0 -2
  81. package/dist/wiki-7BFVMMNR.js +0 -2
  82. /package/dist/{App-2D5W26LY.js.map → App-BUYK4EGC.js.map} +0 -0
  83. /package/dist/{ChatApp-FZFZD2XY.js.map → ChatApp-ZS6EPDDK.js.map} +0 -0
  84. /package/dist/{agent-PCRE3TRK.js.map → agent-W7UNXO6L.js.map} +0 -0
  85. /package/dist/{chunk-ZWZADDXV.js.map → chunk-5DFUUYEA.js.map} +0 -0
  86. /package/dist/{chunk-NFS2VR3L.js.map → chunk-5RE2B5YQ.js.map} +0 -0
  87. /package/dist/{chunk-NYAMY7EA.js.map → chunk-6GLJIA25.js.map} +0 -0
  88. /package/dist/{chunk-5SLTRG66.js.map → chunk-6HKLRU62.js.map} +0 -0
  89. /package/dist/{chunk-XBRVV4ZT.js.map → chunk-6PJ6XHG4.js.map} +0 -0
  90. /package/dist/{chunk-TYFGL2YS.js.map → chunk-B3B7KEHJ.js.map} +0 -0
  91. /package/dist/{chunk-EHKI2RKD.js.map → chunk-BN5QMNON.js.map} +0 -0
  92. /package/dist/{chunk-2UDSIG5K.js.map → chunk-BSTIA4M6.js.map} +0 -0
  93. /package/dist/{chunk-YCMO3KZ4.js.map → chunk-CY6ABHF2.js.map} +0 -0
  94. /package/dist/{chunk-BRVQZC6P.js.map → chunk-FHBPKMCF.js.map} +0 -0
  95. /package/dist/{chunk-C52IPIKJ.js.map → chunk-INLKJEEN.js.map} +0 -0
  96. /package/dist/{chunk-SB7WMFJV.js.map → chunk-QQYXYJOG.js.map} +0 -0
  97. /package/dist/{chunk-WJDFR3WE.js.map → chunk-VHT7HESZ.js.map} +0 -0
  98. /package/dist/{chunk-QCPSGOSK.js.map → chunk-WEPON4FP.js.map} +0 -0
  99. /package/dist/{chunk-XX6MLDTL.js.map → chunk-WMTGAVPW.js.map} +0 -0
  100. /package/dist/{chunk-YUNMSLZN.js.map → chunk-YL4C63S2.js.map} +0 -0
  101. /package/dist/{chunk-7ZGTRXWS.js.map → chunk-YSIRJZWF.js.map} +0 -0
  102. /package/dist/{client-TFZEASIJ.js.map → client-PO5LDFS4.js.map} +0 -0
  103. /package/dist/{config-IXCOAOPZ.js.map → config-L2RQ6EJX.js.map} +0 -0
  104. /package/dist/{config-mutator-EPYIZVSG.js.map → config-mutator-44OAOZXM.js.map} +0 -0
  105. /package/dist/{doctor-G5TM5GVF.js.map → doctor-AU5TCOSG.js.map} +0 -0
  106. /package/dist/{grants-NGBKFONG.js.map → grants-HIFE6L5N.js.map} +0 -0
  107. /package/dist/{promote-VTVIPRTC.js.map → promote-DPPNEINZ.js.map} +0 -0
  108. /package/dist/{query-3CVDT2GZ.js.map → query-SLUOL6MQ.js.map} +0 -0
  109. /package/dist/{registry-NOJMMWE3.js.map → registry-UBVBEEDW.js.map} +0 -0
  110. /package/dist/{request-planner-E2Q5O66N.js.map → request-planner-2G73AJ4S.js.map} +0 -0
  111. /package/dist/{review-candidates-I36HEYKX.js.map → review-candidates-S34UICQD.js.map} +0 -0
  112. /package/dist/{routing-KBUZON5R.js.map → routing-K2LAUFRL.js.map} +0 -0
  113. /package/dist/{schedule-tool-GUHHYYTO.js.map → schedule-tool-YRANRFHO.js.map} +0 -0
  114. /package/dist/{scheduler-PGUELFMB.js.map → scheduler-L4P4Z55R.js.map} +0 -0
  115. /package/dist/{seat-NGY2BMP6.js.map → seat-ZJT5T2NO.js.map} +0 -0
  116. /package/dist/{select-X7VBGZ6X.js.map → select-Y23SKHCJ.js.map} +0 -0
  117. /package/dist/{set-enabled-6NP63KCU.js.map → set-enabled-YWXWSKME.js.map} +0 -0
  118. /package/dist/{tool-EZIILXYL.js.map → tool-5JTCSRTW.js.map} +0 -0
  119. /package/dist/{tool-WKIF52OH.js.map → tool-FZEC5FQX.js.map} +0 -0
  120. /package/dist/{wiki-7BFVMMNR.js.map → wiki-ZZ3MU5Y5.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{A as Zr,B as eo,C as to,a as C,b as Dr,c as Br,d as Hr,e as zr,f as Ae,g as qr,h as Fr,i as jt,k as Ur,q as Wr,r as Gr,s as Xr,t as Kr,u as Jr,y as Vr,z as Yr}from"./chunk-2UDSIG5K.js";import{a as Qr}from"./chunk-5NTWGUSJ.js";import{a as Pr}from"./chunk-LNY6N73E.js";import{a as Nr}from"./chunk-4VDA4UM7.js";import{a as ze,b as q,c as I,h as de,i as Pt,j as oe,k as K,l as $t,m as $r,n as jr,o as Or}from"./chunk-SCJ5ZXEN.js";import{$a as Mr,A as cr,B as St,Ba as _r,C as dr,Ca as Sr,D as Et,Da as Er,E as Tt,F as At,G as pr,H as mr,K as fr,L as hr,La as Tr,M as gr,Na as Te,Sa as Ar,T as U,U as xr,Ua as He,V as vr,Va as Ct,Wa as It,Xa as Mt,Ya as Lt,Za as Cr,_a as Ir,a as Yn,ab as Rt,c as vt,cb as Lr,d as wa,e as Qn,fb as Rr,i as bt,l as Qe,n as Zn,z as _t,za as kr}from"./chunk-DMPTCBX6.js";import"./chunk-GTJIKXDB.js";import{h as Jn,i as Vn}from"./chunk-NFS2VR3L.js";import{p as er,t as tr}from"./chunk-S2GAEH2F.js";import{a as ur,b as B,c as br,d as yr,h as wr}from"./chunk-BGG3ZSMW.js";import{a as rr,b as yt,d as or,e as sr,f as wt}from"./chunk-WCXXXAHV.js";import{g as kt}from"./chunk-LQE73AZR.js";import{b as ir,c as lr}from"./chunk-2D3RYIDU.js";import"./chunk-54XX2LSW.js";import"./chunk-TYFGL2YS.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ee,d as ar,e as ka}from"./chunk-EMGB23H5.js";import{b as nr}from"./chunk-JWDJMFU6.js";import{a as qn,f as Fn,g as ba,h as ya,l as Un,m as Wn,n as Gn,u as ht,v as gt,w as xt,x as ce,y as Kn}from"./chunk-TLCURHW3.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-SB7WMFJV.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-ZWZADDXV.js";import{a as Xn}from"./chunk-XX6MLDTL.js";import"./chunk-7ZGTRXWS.js";import"./chunk-XBRVV4ZT.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as zn}from"./chunk-WJDFR3WE.js";import"./chunk-WPNRDEHW.js";import"./chunk-56KNKUFF.js";import"./chunk-EHKI2RKD.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import{B as Jc,I as On,L as xa,O as Nn,Q as mt,R as Dn,T as Bn,V as Hn,Z as va,a as In,b as Mn,c as Gc,ka as X,na as ft,u as dt,v as Xc,w as ha,x as ga}from"./chunk-ZLUROC2Y.js";import{a as Ln,b as pt,c as fa,d as Rn,h as Pn}from"./chunk-BRK6M6LA.js";import{d as $n,e as Kc,f as ut,n as jn}from"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function _a(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 ao(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:_a(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Ce=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Ot=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Ce(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function no(t={}){return I({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{A as to,B as ao,C as no,a as C,b as Hr,c as zr,d as qr,e as Fr,f as Ae,g as Ur,h as Wr,i as jt,k as Gr,q as Xr,r as Kr,s as Jr,t as Vr,u as Yr,y as Qr,z as Zr}from"./chunk-BSTIA4M6.js";import{a as eo}from"./chunk-5NTWGUSJ.js";import{a as jr}from"./chunk-LNY6N73E.js";import{a as Br}from"./chunk-4VDA4UM7.js";import{a as ze,b as q,c as I,h as de,i as Pt,j as oe,k as K,l as $t,m as Or,n as Nr,o as Dr}from"./chunk-SCJ5ZXEN.js";import{$a as Rr,A as pr,B as St,Ba as Er,C as ur,Ca as Tr,D as Et,Da as Ar,E as Tt,F as At,G as mr,H as hr,K as gr,L as xr,La as Cr,M as br,Na as Te,Sa as Ir,T as U,U as vr,Ua as He,V as yr,Va as Ct,Wa as It,Xa as Mt,Ya as Lt,Za as Mr,_a as Lr,a as Zn,ab as Rt,c as bt,cb as Pr,d as wa,e as er,fb as $r,i as vt,l as Qe,n as tr,z as _t,za as Sr}from"./chunk-K5QUQNFE.js";import"./chunk-GTJIKXDB.js";import{h as Yn,i as Qn}from"./chunk-5RE2B5YQ.js";import{p as ar,t as nr}from"./chunk-S2GAEH2F.js";import{a as fr,b as B,c as wr,d as kr,h as _r}from"./chunk-BGG3ZSMW.js";import{a as sr,b as yt,d as ir,e as lr,f as wt}from"./chunk-WCXXXAHV.js";import{g as kt}from"./chunk-LQE73AZR.js";import{b as cr,c as dr}from"./chunk-2D3RYIDU.js";import"./chunk-AKLZ4YO2.js";import"./chunk-B3B7KEHJ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as Ee,d as rr,e as ka}from"./chunk-EMGB23H5.js";import{b as or}from"./chunk-JWDJMFU6.js";import{E as Jn,F as ht,G as gt,H as xt,I as ce,J as Vn,a as qn,f as Fn,g as va,h as ya,l as Un,m as Wn,n as Gn,y as Kn}from"./chunk-ITATBKUL.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-QQYXYJOG.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-5DFUUYEA.js";import{a as Xn}from"./chunk-WMTGAVPW.js";import"./chunk-YSIRJZWF.js";import"./chunk-6PJ6XHG4.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as zn}from"./chunk-VHT7HESZ.js";import"./chunk-WPNRDEHW.js";import"./chunk-56KNKUFF.js";import"./chunk-BN5QMNON.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import{B as Yc,I as On,L as xa,O as Nn,Q as mt,R as Dn,T as Bn,V as Hn,Z as ba,a as In,b as Mn,c as Kc,oa as X,ra as ft,u as dt,v as Jc,w as ha,x as ga}from"./chunk-46JKX6CT.js";import{d as $n,e as Vc,f as ut,n as jn}from"./chunk-UIBUZ2N3.js";import{a as Ln,b as pt,c as fa,d as Rn,h as Pn}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function _a(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:_a(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Ce=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Ot=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Ce(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function oo(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 @@ ${Ot(se.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:Vc,scripts:`<script>${q({decayOf:_a,rankByDecay:ao})}const ICON = ${JSON.stringify(se)};${Yc}</script>`})}var Vc=`
88
+ </div>`,css:Qc,scripts:`<script>${q({decayOf:_a,rankByDecay:ro})}const ICON = ${JSON.stringify(se)};${Zc}</script>`})}var Qc=`
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
- }`,Yc=String.raw`
364
+ }`,Zc=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 Sa(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),d=r[r.length-1];d&&l.startedAt-d.to<=e?(d.to=Math.max(d.to,c),d.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let d=1;d<r.length;d++){let p=r[d].from-r[d-1].to;p<c&&(c=p,l=d)}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 Ea(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 ro(t,e=[],a){let{bands:n,gaps:r}=Sa(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(v=>l.startedAt>=v.from&&l.startedAt<=v.to);if(c===-1)continue;let d=n[c],p=d.to-d.from||1,m=(l.startedAt-d.from)/p*100,f=Math.min(Math.max((l.durationMs||0)/p*100,1.2),100-m),_=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};_.runs.push({...l,band:c,track:0,left:m,width:f,marks:o.get(l.id)??[]}),s.set(l.laneKey,_)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,d)=>Ea(l.runs.filter(p=>p.band===d))),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 Qc}from"crypto";import{readFileSync as Zc,statSync as ed}from"fs";import{resolve as td,dirname as ad}from"path";import{fileURLToPath as nd}from"url";var oo=new Map;function Nt(t){let e=oo.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=ad(nd(import.meta.url)),r=td(n,"web",t),o=ed(r),s=o.size<8e6?Qc("sha1").update(Zc(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return oo.set(t,a),a}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"/>',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"/>'},Dt=(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>",rd=[["agent","Agent",ie.bot],["client","Client",ie.user],["project","Project",ie.folder],["channel","Channel",ie.route],["person","Person",ie.user],["node","Node",ie.mesh]],so={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &mdash; quiet stretches are labelled, not drawn.",map:"The fleet as a transit map: projects are lines, agents are stations, work in flight is a train. Live."};function io(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return I({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function Sa(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),d=r[r.length-1];d&&l.startedAt-d.to<=e?(d.to=Math.max(d.to,c),d.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let d=1;d<r.length;d++){let p=r[d].from-r[d-1].to;p<c&&(c=p,l=d)}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 Ea(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function so(t,e=[],a){let{bands:n,gaps:r}=Sa(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(v=>l.startedAt>=v.from&&l.startedAt<=v.to);if(c===-1)continue;let d=n[c],p=d.to-d.from||1,m=(l.startedAt-d.from)/p*100,h=Math.min(Math.max((l.durationMs||0)/p*100,1.2),100-m),S=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};S.runs.push({...l,band:c,track:0,left:m,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,S)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,d)=>Ea(l.runs.filter(p=>p.band===d))),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 ed}from"crypto";import{readFileSync as td,statSync as ad}from"fs";import{resolve as nd,dirname as rd}from"path";import{fileURLToPath as od}from"url";var io=new Map;function Nt(t){let e=io.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=rd(od(import.meta.url)),r=nd(n,"web",t),o=ad(r),s=o.size<8e6?ed("sha1").update(td(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return io.set(t,a),a}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"/>',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"/>'},Dt=(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>",sd=[["agent","Agent",ie.bot],["client","Client",ie.user],["project","Project",ie.folder],["channel","Channel",ie.route],["person","Person",ie.user],["node","Node",ie.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 co(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">${so[e]}</p>
785
+ <p class="ac-sub" id="sub">${lo[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
@@ -799,7 +799,7 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${rd.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Dt(o,13)}${r}</button>`).join("")}
802
+ ${sd.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Dt(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="${Nt("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:od,scripts:`<script>${q({computeBands:Sa,packTracks:Ea,buildTimeline:ro})}const ICON = ${JSON.stringify(ie)};const SUB = ${JSON.stringify(so)};${sd}</script>`})}var od=`
822
+ </div>`,css:id,scripts:`<script>${q({computeBands:Sa,packTracks:Ea,buildTimeline:so})}const ICON = ${JSON.stringify(ie)};const SUB = ${JSON.stringify(lo)};${ld}</script>`})}var id=`
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
- `,sd=String.raw`
908
+ `,ld=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 lo(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:id,scripts:`<script src="${Nt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var id=`
1027
+ `;function po(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:cd,scripts:`<script src="${Nt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var cd=`
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 gh}from"http";import{appendFileSync as xh,existsSync as Nc,mkdirSync as vh}from"fs";import{readFile as bh}from"fs/promises";import{fileURLToPath as yh}from"url";import{dirname as wh,resolve as it}from"path";Nn();function qe(t,e){if(!t)return"absent";let a=ar(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ie=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function Bt(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=co(t.headers["sec-fetch-mode"]),n.site=co(t.headers["sec-fetch-site"]),n}function co(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as dd}from"zlib";var ld=[[[441,393],[600,393],[614,396],[625,401],[634,410],[1028,940],[846,940],[833,937],[823,931],[818,925],[440,414],[435,406],[436,398]],[[893,393],[1079,393],[861,653],[771,535]],[[413,439],[510,574],[282,874],[100,874]],[[451,709],[610,709],[615,712],[698,824],[599,939],[447,719],[446,713]]],ye={x:100,y:393,width:979,height:547},Ta="#1a1a18",Aa="#ffffff",po=Math.hypot(ye.width,ye.height)/2/ye.width,Ht={full:.74,safe:.37/po,android:.29/po,mac:.6};function Ca(t,e){let a=t*e/ye.width,n=t/2-(ye.x+ye.width/2)*a,r=t/2-(ye.y+ye.height/2)*a;return ld.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function cd(t,e){let a=n=>String(Math.round(n*100)/100);return Ca(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function uo(t=64,e=Ht.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${Aa}"/><path fill="${Ta}" d="${cd(t,e)}"/></svg>`}var pd=yo(Ta),mo=yo(Aa),fo=new Map;function Fe(t){let e=fo.get(t);return e||(e=bo({size:t,width:Ht.safe,background:"square"}),fo.set(t,e)),e}var ud=uo();function vo(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:ud}:t==="/favicon.ico"?{type:"image/png",body:go(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:go(180)}:null}var ho=new Map;function go(t){let e=ho.get(t);return e||(e=bo({size:t,width:Ht.full,background:"square"}),ho.set(t,e)),e}function bo(t){let{size:e}=t,a=t.background==="mac"?xo(e,[md(e)]):null,n=xo(e,Ca(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],d=s*r+1+i*4;for(let p=0;p<3;p++)o[d+p]=Math.round(mo[p]+(pd[p]-mo[p])*c);o[d+3]=Math.round(255*(a?a[l]:1))}return fd(e,o)}function md(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 d=0;d<=12;d++){let p=(c+90*d/12)*Math.PI/180;o.push([i+r*Math.cos(p),l+r*Math.sin(p)])}return o}var Ia=8;function xo(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,d]=o[(s+1)%o.length];l!==d&&n.push([i,l,c,d])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Ia;s++){let i=o+(s+.5)/Ia;r.length=0;for(let[l,c,d,p]of n)(i>=c&&i<p||i>=p&&i<c)&&r.push(l+(i-c)*(d-l)/(p-c));r.sort((l,c)=>l-c);for(let l=0;l+1<r.length;l+=2){let c=Math.max(0,r[l]),d=Math.min(t,r[l+1]);for(let p=Math.floor(c);p<d;p++){let m=Math.min(p+1,d)-Math.max(p,c);m>0&&(a[o*t+p]+=m/Ia)}}}for(let o=0;o<a.length;o++)a[o]>1&&(a[o]=1);return a}function yo(t){let e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,e&255]}function fd(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]),Ma("IHDR",a),Ma("IDAT",dd(e)),Ma("IEND",Buffer.alloc(0))])}function Ma(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(gd(n)),Buffer.concat([a,n,r])}var hd=Array.from({length:256},(t,e)=>{let a=e;for(let n=0;n<8;n++)a=a&1?3988292384^a>>>1:a>>>1;return a>>>0});function gd(t){let e=4294967295;for(let a of t)e=hd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}ft();Jc();var zt=7,xd=["waiting_owner","needs_attention"],vd={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Ue(t,e){let a=t.toLowerCase().split("@")[0],n=vd[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 wo(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 ko(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(v=>v.name==="person"),i=v=>({id:v.id,state:v.state,agentId:v.agent_id,text:v.text,channel:v.channel,chatId:v.chat_id,createdAt:v.created_at,updatedAt:v.updated_at,closedAt:v.closed_at??null,question:v.question??null,attentionReason:v.attention_reason??null,evidence:v.evidence??null,where:{label:Ue(v.channel,v.chat_id),url:a.linkFor?.(v.channel,v.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ha.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...ha).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ga.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1048
+ `;import{createServer as bh}from"http";import{appendFileSync as vh,existsSync as Bc,mkdirSync as yh}from"fs";import{readFile as wh}from"fs/promises";import{fileURLToPath as kh}from"url";import{dirname as _h,resolve as it}from"path";Nn();function qe(t,e){if(!t)return"absent";let a=rr(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ie=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function Bt(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=uo(t.headers["sec-fetch-mode"]),n.site=uo(t.headers["sec-fetch-site"]),n}function uo(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 dd=[[[441,393],[600,393],[614,396],[625,401],[634,410],[1028,940],[846,940],[833,937],[823,931],[818,925],[440,414],[435,406],[436,398]],[[893,393],[1079,393],[861,653],[771,535]],[[413,439],[510,574],[282,874],[100,874]],[[451,709],[610,709],[615,712],[698,824],[599,939],[447,719],[446,713]]],ye={x:100,y:393,width:979,height:547},Ta="#1a1a18",Aa="#ffffff",mo=Math.hypot(ye.width,ye.height)/2/ye.width,Ht={full:.74,safe:.37/mo,android:.29/mo,mac:.6};function Ca(t,e){let a=t*e/ye.width,n=t/2-(ye.x+ye.width/2)*a,r=t/2-(ye.y+ye.height/2)*a;return dd.map(o=>o.map(([s,i])=>[s*a+n,i*a+r]))}function pd(t,e){let a=n=>String(Math.round(n*100)/100);return Ca(t,e).map(n=>"M"+n.map(([r,o])=>`${a(r)},${a(o)}`).join("L")+"Z").join("")}function fo(t=64,e=Ht.full){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}"><rect width="${t}" height="${t}" rx="${t*.18}" fill="${Aa}"/><path fill="${Ta}" d="${pd(t,e)}"/></svg>`}var md=ko(Ta),ho=ko(Aa),go=new Map;function Fe(t){let e=go.get(t);return e||(e=wo({size:t,width:Ht.safe,background:"square"}),go.set(t,e)),e}var fd=fo();function yo(t){return t==="/favicon.svg"?{type:"image/svg+xml",body:fd}:t==="/favicon.ico"?{type:"image/png",body:bo(32)}:t==="/apple-touch-icon.png"?{type:"image/png",body:bo(180)}:null}var xo=new Map;function bo(t){let e=xo.get(t);return e||(e=wo({size:t,width:Ht.full,background:"square"}),xo.set(t,e)),e}function wo(t){let{size:e}=t,a=t.background==="mac"?vo(e,[hd(e)]):null,n=vo(e,Ca(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],d=s*r+1+i*4;for(let p=0;p<3;p++)o[d+p]=Math.round(ho[p]+(md[p]-ho[p])*c);o[d+3]=Math.round(255*(a?a[l]:1))}return gd(e,o)}function hd(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 d=0;d<=12;d++){let p=(c+90*d/12)*Math.PI/180;o.push([i+r*Math.cos(p),l+r*Math.sin(p)])}return o}var Ia=8;function vo(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,d]=o[(s+1)%o.length];l!==d&&n.push([i,l,c,d])}let r=[];for(let o=0;o<t;o++)for(let s=0;s<Ia;s++){let i=o+(s+.5)/Ia;r.length=0;for(let[l,c,d,p]of n)(i>=c&&i<p||i>=p&&i<c)&&r.push(l+(i-c)*(d-l)/(p-c));r.sort((l,c)=>l-c);for(let l=0;l+1<r.length;l+=2){let c=Math.max(0,r[l]),d=Math.min(t,r[l+1]);for(let p=Math.floor(c);p<d;p++){let m=Math.min(p+1,d)-Math.max(p,c);m>0&&(a[o*t+p]+=m/Ia)}}}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 gd(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]),Ma("IHDR",a),Ma("IDAT",ud(e)),Ma("IEND",Buffer.alloc(0))])}function Ma(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(bd(n)),Buffer.concat([a,n,r])}var xd=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 bd(t){let e=4294967295;for(let a of t)e=xd[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}ft();Yc();var zt=7,vd=["waiting_owner","needs_attention"],yd={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Ue(t,e){let a=t.toLowerCase().split("@")[0],n=yd[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 _o(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 So(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(v=>v.name==="person"),i=v=>({id:v.id,state:v.state,agentId:v.agent_id,text:v.text,channel:v.channel,chatId:v.chat_id,createdAt:v.created_at,updatedAt:v.updated_at,closedAt:v.closed_at??null,question:v.question??null,attentionReason:v.attention_reason??null,evidence:v.evidence??null,where:{label:Ue(v.channel,v.chat_id),url:a.linkFor?.(v.channel,v.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ha.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...ha).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${ga.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1049
1049
  ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...ga,n-zt*864e5).map(i):[],d=[];try{d=jt(t,e,50).filter(v=>v.startedAt>=n-zt*864e5)}catch{}let p=new Map;if(s&&d.length){let v=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 (${d.map(()=>"?").join(",")})`).all(e,...d.map(E=>E.taskId));for(let E of v)p.set(E.ref,{id:E.id,state:E.state,evidence:E.evidence??null})}let m=d.map(v=>({...v,where:v.channel?{label:Ue(v.channel,v.chatId??""),url:a.linkFor?.(v.channel,v.chatId??"")??null}:null,request:p.get(v.taskId)??null})),f=new Set(m.map(v=>v.request?.id).filter(Boolean)),_=[...l.filter(v=>!xd.includes(v.state)),...c].filter(v=>!f.has(v.id));return{open:l,recent:c,runs:m,other:_}}va();Kc();var _o={waiting:0,yours:0,ahead:null};function So(t,e,a={}){let n=$n(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 d=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};d.waiting++,i.person===e&&(d.yours++,d.ahead===null&&(d.ahead=c),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Ue(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:c})),r.set(i.agentId,d)}return{byAgent:r,mine:o}}var bd=4e3;function Eo(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
1050
+ WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${d.map(()=>"?").join(",")})`).all(e,...d.map(E=>E.taskId));for(let E of v)p.set(E.ref,{id:E.id,state:E.state,evidence:E.evidence??null})}let m=d.map(v=>({...v,where:v.channel?{label:Ue(v.channel,v.chatId??""),url:a.linkFor?.(v.channel,v.chatId??"")??null}:null,request:p.get(v.taskId)??null})),h=new Set(m.map(v=>v.request?.id).filter(Boolean)),S=[...l.filter(v=>!vd.includes(v.state)),...c].filter(v=>!h.has(v.id));return{open:l,recent:c,runs:m,other:S}}ba();Vc();var Eo={waiting:0,yours:0,ahead:null};function To(t,e,a={}){let n=$n(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 d=r.get(i.agentId)??{waiting:0,yours:0,ahead:null};d.waiting++,i.person===e&&(d.yours++,d.ahead===null&&(d.ahead=c),o.push({agentId:i.agentId,channel:i.channel,chatId:i.chatId,queuedAt:i.queuedAt,messagePreview:i.messagePreview,where:{label:Ue(i.channel,i.chatId),url:a.linkFor?.(i.channel,i.chatId)??null},ahead:c})),r.set(i.agentId,d)}return{byAgent:r,mine:o}}var wd=4e3;function Ao(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
1051
1051
  WHERE person = ? AND started_at >= ? AND (channel IS NULL OR channel != 'a2a')
1052
- GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-zt*864e5).map(r=>r.agent_id)}function To(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(mt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let c=n.queue?.get(l)??_o,d=s.get(l),p=d??i.get(l);if(!p)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:c};let m=o(p.person??null),f=p.status==="error"||p.status==="timeout",_=d?"working":f&&m==="you"?"blocked":"free",v=m==="you"&&p.channel!=="a2a",E=v&&p.channel;return{agentId:l,state:_,by:m,at:d?p.started_at:p.finished_at??p.started_at,text:d||v?p.message_preview??null:null,fullText:v&&d&&String(p.original_message??p.message_preview??"").slice(0,bd)||null,where:E?{label:Ue(p.channel,p.chat_id??""),url:n.linkFor?.(p.channel,p.chat_id??"")??null}:null,queue:c}})}function Ao(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Co(t,e){return!t||e-t>=3e4||t>e}function qt(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 Io(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 Ft(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 Ut(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 Mo(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 Lo(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 Ro(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 Po(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 $o(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 jo=`
1052
+ GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-zt*864e5).map(r=>r.agent_id)}function Co(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(mt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let c=n.queue?.get(l)??Eo,d=s.get(l),p=d??i.get(l);if(!p)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null,queue:c};let m=o(p.person??null),h=p.status==="error"||p.status==="timeout",S=d?"working":h&&m==="you"?"blocked":"free",v=m==="you"&&p.channel!=="a2a",E=v&&p.channel;return{agentId:l,state:S,by:m,at:d?p.started_at:p.finished_at??p.started_at,text:d||v?p.message_preview??null:null,fullText:v&&d&&String(p.original_message??p.message_preview??"").slice(0,wd)||null,where:E?{label:Ue(p.channel,p.chat_id??""),url:n.linkFor?.(p.channel,p.chat_id??"")??null}:null,queue:c}})}function Io(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Mo(t,e){return!t||e-t>=3e4||t>e}function qt(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 Lo(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 Ft(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 Ut(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 Ro(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 Po(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 $o(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 jo(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 Oo(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 No=`
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
- `,Oo=`
1367
+ `,Do=`
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
- `,No=`
1379
+ `,Bo=`
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 yd="<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 La(t,e={}){return`<meta charset="utf-8">
1383
+ `;var kd="<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 La(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
- ${yd}
1394
- <style>${ze}${Wt}</style>`}function Do(){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 Bo=`
1393
+ ${kd}
1394
+ <style>${ze}${Wt}</style>`}function Ho(){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 zo=`
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 Ra(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 Pa=La,$a=Ra;function Ho(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 zo(){return`<!doctype html>
1427
+ </header>`}var Pa=La,$a=Ra;function qo(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 Fo(){return`<!doctype html>
1428
1428
  <html lang="en">
1429
1429
  <head>${Pa("My work \xB7 AgentX")}<style>${Gt}</style></head>
1430
1430
  <body>
@@ -1439,15 +1439,15 @@ ${$a("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>${q({workState:wd,ageText:ja,connectionNote:Ft,plainPreview:Ut,agentLine:Mo,sentState:Lo,requestState:Ro,summaryLine:Po,freedAgents:$o})}${jo}</script>
1442
+ <script>${q({workState:_d,ageText:ja,connectionNote:Ft,plainPreview:Ut,agentLine:Ro,sentState:Po,requestState:$o,summaryLine:jo,freedAgents:Oo})}${No}</script>
1443
1443
  </body>
1444
- </html>`}function qo(){return`<!doctype html>
1444
+ </html>`}function Uo(){return`<!doctype html>
1445
1445
  <html lang="en">
1446
- <head>${Pa("Pair this machine \xB7 AgentX")}<style>${Oo}</style></head>
1446
+ <head>${Pa("Pair this machine \xB7 AgentX")}<style>${Do}</style></head>
1447
1447
  <body>
1448
1448
  ${$a("This machine is not paired yet")}
1449
1449
  <main class="narrow">
1450
- ${Ho(0)}
1450
+ ${qo(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 @@ ${$a("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>${q({formatPairInput:qt})}${kd}</script>
1467
+ <script>${q({formatPairInput:qt})}${Sd}</script>
1468
1468
  </body>
1469
- </html>`}function Fo(){return`<!doctype html>
1469
+ </html>`}function Wo(){return`<!doctype html>
1470
1470
  <html lang="en">
1471
- <head>${Pa("Waiting for the owner \xB7 AgentX")}<style>${No}</style></head>
1471
+ <head>${Pa("Waiting for the owner \xB7 AgentX")}<style>${Bo}</style></head>
1472
1472
  <body>
1473
1473
  ${$a("This machine is paired")}
1474
1474
  <main class="narrow">
1475
- ${Ho(1)}
1475
+ ${qo(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>${_d}</script>
1482
+ <script>${Ed}</script>
1483
1483
  </body>
1484
- </html>`}function wd(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 ja(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 kd=`
1484
+ </html>`}function _d(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 ja(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 Sd=`
1485
1485
  (function () {
1486
1486
  var form = document.getElementById('pair-form');
1487
1487
  var machine = document.getElementById('machine');
@@ -1525,7 +1525,7 @@ ${$a("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
- `,_d=`
1528
+ `,Ed=`
1529
1529
  (function () {
1530
1530
  var msg = document.getElementById('msg');
1531
1531
  function check() {
@@ -1536,13 +1536,13 @@ ${$a("This machine is paired")}
1536
1536
  }
1537
1537
  setInterval(check, 5000);
1538
1538
  })();
1539
- `;function Uo(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 Wo(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 Go(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 Oa="/member/client.webmanifest",Ze="Your project";function Xo(){return JSON.stringify({id:"/member?client",name:`${Ze} \xB7 AgentX`,short_name:Ze,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 Sd=`
1539
+ `;function Go(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 Xo(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 Ko(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 Oa="/member/client.webmanifest",Ze="Your project";function Jo(){return JSON.stringify({id:"/member?client",name:`${Ze} \xB7 AgentX`,short_name:Ze,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 Td=`
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 Ko(){return`<!doctype html>
1543
+ `;function Vo(){return`<!doctype html>
1544
1544
  <html lang="en">
1545
- <head>${La(`${Ze} \xB7 AgentX`,{manifest:Oa,appTitle:Ze})}<style>${ze}${Wt}${Gt}${Sd}</style></head>
1545
+ <head>${La(`${Ze} \xB7 AgentX`,{manifest:Oa,appTitle:Ze})}<style>${ze}${Wt}${Gt}${Td}</style></head>
1546
1546
  <body>
1547
1547
  ${Ra("Connecting\u2026",`
1548
1548
  <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>`,Ze)}
@@ -1557,9 +1557,9 @@ ${Ra("Connecting\u2026",`
1557
1557
  </section>
1558
1558
  <p id="updated" class="foot"></p>
1559
1559
  </main>
1560
- <script>${q({ageText:ja,connectionNote:Ft,plainPreview:Ut,clientSentState:Uo,clientRequestState:Wo,clientSummary:Go})}${Ed}</script>
1560
+ <script>${q({ageText:ja,connectionNote:Ft,plainPreview:Ut,clientSentState:Go,clientRequestState:Xo,clientSummary:Ko})}${Ad}</script>
1561
1561
  </body>
1562
- </html>`}var Ed=`
1562
+ </html>`}var Ad=`
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 @@ ${Ra("Connecting\u2026",`
1666
1666
  showConn();
1667
1667
  load();
1668
1668
  })();
1669
- `;var Xt="agentx_member",Td=90*86400,Ad=new At,Qo=t=>t.replace(/^\[app\]/,"[member]"),Cd=new Ie(t=>console.log(Qo(t))),Jo=new WeakMap;function Id(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Cd;let e=Jo.get(t.log);return e||Jo.set(t.log,e=new Ie(a=>t.log(Qo(a)))),e}var Vo=null;function et(t,e=X){try{return Vo=e().people}catch{return Vo??t}}async function Zo(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new G(r.root),s=r.members??new ht(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new kt(r.root),limiter:r.pairLimiter??Ad,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return fe(e,200,"application/manifest+json",Do());if(a===Oa)return fe(e,200,"application/manifest+json",Xo());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),fe(e,200,"text/javascript; charset=utf-8",Bo);if(a==="/member/icon-192.png")return fe(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/member/icon-512.png")return fe(e,200,"image/png",Fe(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Gr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Yo(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),we(e,p.status,p.body)}let l=Kr(Ld(t),i,Wr(t));if(!l.ok){if(l.status===401){let p=Na(t);return Id(r).record(a.slice(0,120),Bt(t,qe(Da(t,Xt),o),p?qe(p,o):null)),a==="/member"?fe(e,401,"text/html; charset=utf-8",qo()):we(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?fe(e,202,"text/html; charset=utf-8",Fo()):we(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId),d=c?.role==="client";if(n==="GET"&&a==="/member"){let p=Da(t,Xt);return p&&!Na(t)&&e.setHeader("Set-Cookie",Yo(p)),fe(e,200,"text/html; charset=utf-8",d?Ko():zo())}if(n==="GET"&&a==="/api/member/me")return we(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 p=r.db?.()??null;if(!p)return we(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),f=ko(p,l.personId,{now:m,linkFor:r.linkFor}),_=(x,g)=>{let u=g instanceof Error?g.message:String(g);/no such table/i.test(u)||r.log?.(`[member] ${x} failed: ${u}`)},v={byAgent:new Map,mine:[]};try{v=So(p,l.personId,{linkFor:r.linkFor})}catch(x){_("the line",x)}let E=[];if(d)return we(e,200,{...Md(f),agents:E});try{let x=Eo(p,c??{id:l.personId},m);E=To(p,l.personId,x,{people:r.people(),linkFor:r.linkFor,queue:v.byAgent})}catch(x){_("agent cards",x)}return we(e,200,{...f,agents:E,queued:v.mine})}return we(e,404,{error:"not found"})}function Md(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 Yo(t){return`${Xt}=${t}; Path=/; Max-Age=${Td}; HttpOnly; Secure; SameSite=Lax`}function Ld(t){return Na(t)??Da(t,Xt)}function Na(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Da(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function we(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}Gc();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 Jt,readFileSync as ls,writeFileSync as cs,rmSync as kx,mkdirSync as Nd,copyFileSync as Dd,readdirSync as Bd}from"fs";import{resolve as We}from"path";Xc();function as(t){let e=dt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:dt.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 Kt(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=dt.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 ns(t){return Kt(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 rs(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Kt((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 os(t){let e=String(t?.id??"");return Kt(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 ss(t){let e=String(t?.id??"");return Kt(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}ft();var pe={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function is(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=de({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Pt([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return I({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Pd()+$r,css:jd,scripts:`${e}<script>${jr}
1670
- ${Or}
1671
- ${Rd}
1672
- ${Od}</script>`})}var Rd=`
1669
+ `;var Xt="agentx_member",Cd=90*86400,Id=new At,es=t=>t.replace(/^\[app\]/,"[member]"),Md=new Ie(t=>console.log(es(t))),Yo=new WeakMap;function Ld(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return Md;let e=Yo.get(t.log);return e||Yo.set(t.log,e=new Ie(a=>t.log(es(a)))),e}var Qo=null;function et(t,e=X){try{return Qo=e().people}catch{return Qo??t}}async function ts(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new G(r.root),s=r.members??new ht(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new kt(r.root),limiter:r.pairLimiter??Id,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return fe(e,200,"application/manifest+json",Ho());if(a===Oa)return fe(e,200,"application/manifest+json",Jo());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),fe(e,200,"text/javascript; charset=utf-8",zo);if(a==="/member/icon-192.png")return fe(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/member/icon-512.png")return fe(e,200,"image/png",Fe(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await Kr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Zo(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),we(e,p.status,p.body)}let l=Vr(Pd(t),i,Xr(t));if(!l.ok){if(l.status===401){let p=Na(t);return Ld(r).record(a.slice(0,120),Bt(t,qe(Da(t,Xt),o),p?qe(p,o):null)),a==="/member"?fe(e,401,"text/html; charset=utf-8",Uo()):we(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?fe(e,202,"text/html; charset=utf-8",Wo()):we(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId),d=c?.role==="client";if(n==="GET"&&a==="/member"){let p=Da(t,Xt);return p&&!Na(t)&&e.setHeader("Set-Cookie",Zo(p)),fe(e,200,"text/html; charset=utf-8",d?Vo():Fo())}if(n==="GET"&&a==="/api/member/me")return we(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 p=r.db?.()??null;if(!p)return we(e,503,{error:"the work list needs the database"});let m=(r.now??Date.now)(),h=So(p,l.personId,{now:m,linkFor:r.linkFor}),S=(b,x)=>{let u=x instanceof Error?x.message:String(x);/no such table/i.test(u)||r.log?.(`[member] ${b} failed: ${u}`)},v={byAgent:new Map,mine:[]};try{v=To(p,l.personId,{linkFor:r.linkFor})}catch(b){S("the line",b)}let E=[];if(d)return we(e,200,{...Rd(h),agents:E});try{let b=Ao(p,c??{id:l.personId},m);E=Co(p,l.personId,b,{people:r.people(),linkFor:r.linkFor,queue:v.byAgent})}catch(b){S("agent cards",b)}return we(e,200,{...h,agents:E,queued:v.mine})}return we(e,404,{error:"not found"})}function Rd(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 Zo(t){return`${Xt}=${t}; Path=/; Max-Age=${Cd}; HttpOnly; Secure; SameSite=Lax`}function Pd(t){return Na(t)??Da(t,Xt)}function Na(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Da(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function we(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}Kc();var as='/*! 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 Jt,readFileSync as ds,writeFileSync as ps,rmSync as Sx,mkdirSync as Bd,copyFileSync as Hd,readdirSync as zd}from"fs";import{resolve as We}from"path";Jc();function rs(t){let e=dt.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:dt.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 Kt(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=dt.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 ns=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function os(t){return Kt(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 ss(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Kt((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:ns(t?.chats),senders:ns(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 is(t){let e=String(t?.id??"");return Kt(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 ls(t){let e=String(t?.id??"");return Kt(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}ft();var pe={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function cs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=de({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Pt([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return I({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+jd()+Or,css:Nd,scripts:`${e}<script>${Nr}
1670
+ ${Dr}
1671
+ ${$d}
1672
+ ${Dd}</script>`})}var $d=`
1673
1673
  (function(){
1674
1674
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1675
1675
  async function voiceMissing() {
@@ -1763,8 +1763,8 @@ ${Od}</script>`})}var Rd=`
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 Pd(){let t=yr().business?`<button data-tab="business">Business</button>
1767
- `:"";return $d.replace("__BUSINESS_TABS__",t)}var $d=`
1766
+ })();`;function jd(){let t=kr().business?`<button data-tab="business">Business</button>
1767
+ `:"";return Od.replace("__BUSINESS_TABS__",t)}var Od=`
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>
@@ -2423,7 +2423,7 @@ ${Od}</script>`})}var Rd=`
2423
2423
  <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>
2424
2424
  </section>
2425
2425
  </main>
2426
- `,jd=`
2426
+ `,Nd=`
2427
2427
 
2428
2428
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
2429
2429
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -2631,7 +2631,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
2631
2631
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
2632
2632
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
2633
2633
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
2634
- `,Od=`
2634
+ `,Dd=`
2635
2635
  const $ = (id) => document.getElementById(id);
2636
2636
  let state = null;
2637
2637
 
@@ -5515,11 +5515,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
5515
5515
  })();
5516
5516
 
5517
5517
  refresh();
5518
- `;function ds(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(is({peers:a,localToken:n}))}async function ps(t,e){let a=za();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function us(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Zd(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Hd(t),r={"GET /api/admin/state":()=>qd(),"POST /api/admin/agents":()=>Kd(n),"PATCH /api/admin/agents":()=>Jd(n),"DELETE /api/admin/agents":()=>Vd(n),"POST /api/admin/agents/access":()=>Fd(n),"POST /api/admin/channels/telegram":()=>Yd(n),"DELETE /api/admin/channels/telegram":()=>wp(n),"POST /api/admin/channels/telegram/toggle":()=>kp(n),"POST /api/admin/crons":()=>_p(n),"DELETE /api/admin/crons":()=>Sp(n),"POST /api/admin/config/raw":()=>Ep(n),"GET /api/admin/tokens":()=>Ud(),"POST /api/admin/tokens":()=>Wd(n),"DELETE /api/admin/tokens":()=>Gd(n),"POST /api/admin/agents/test":()=>Xd(n),"POST /api/admin/agents/integrations":()=>op(n),"DELETE /api/admin/agents/integrations":()=>sp(n),"PATCH /api/admin/agents/integrations":()=>ip(n),"PATCH /api/admin/channels/telegram":()=>Qd(n),"POST /api/admin/channels/slack":()=>fp(n),"POST /api/admin/channels/slack/toggle":()=>hp(n),"POST /api/admin/channels/discord":()=>gp(n),"POST /api/admin/channels/discord/toggle":()=>xp(n),"POST /api/admin/channels/gitlab":()=>vp(n),"POST /api/admin/channels/gitlab/toggle":()=>bp(n),"POST /api/admin/channels/request-status":()=>Yr(n),"GET /api/admin/channels/whatsapp/state":()=>tt("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>tt("/webrtc/history"),"POST /api/admin/actions":()=>Dp(n),"DELETE /api/admin/actions":()=>Bp(n),"POST /api/admin/actions/run":()=>Hp(n),"GET /api/admin/channels/whatsapp/chats":()=>tt("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>tt("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>he("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>yp(n),"POST /api/admin/webhooks":()=>lp(n),"PATCH /api/admin/webhooks":()=>cp(n),"DELETE /api/admin/webhooks":()=>mp(n),"POST /api/admin/whatsapp-triage":()=>ns(n),"POST /api/admin/whatsapp-triage/rules":()=>rs(n),"PATCH /api/admin/whatsapp-triage/rules":()=>os(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ss(n),"POST /api/admin/mesh/peers":()=>dp(n),"DELETE /api/admin/mesh/peers":()=>pp(n),"POST /api/admin/mesh/toggle":()=>up(n),"GET /api/admin/files":()=>ep(t),"GET /api/admin/files/read":()=>tp(t),"PUT /api/admin/files":()=>ap(n),"POST /api/admin/files/skill":()=>np(n),"DELETE /api/admin/files/skill":()=>rp(n),"POST /api/admin/business/orgchart":()=>Tp(n),"DELETE /api/admin/business/orgchart":()=>Ap(n),"POST /api/admin/business/project":()=>Cp(n),"DELETE /api/admin/business/project":()=>Lp(n),"POST /api/admin/business/client":()=>Ip(n),"DELETE /api/admin/business/client":()=>Mp(n),"POST /api/admin/business/contact":()=>Rp(n),"DELETE /api/admin/business/contact":()=>Pp(n),"POST /api/admin/boards":()=>$p(n),"DELETE /api/admin/boards":()=>jp(n),"POST /api/admin/boards/columns":()=>Op(n),"DELETE /api/admin/boards/columns":()=>Np(n),"POST /api/admin/notifications":()=>qp(n),"POST /api/admin/screen":()=>Fp(n),"POST /api/admin/webhooks/triggers":()=>Up(n),"POST /api/admin/mesh/health":()=>zp(n),"GET /api/admin/projects":()=>tt("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>he("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>he("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>he("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>he("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>he("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>he("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>he("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>he("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Ba(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Ba(e,200,i)}catch(n){Ba(e,400,{error:n.message||"admin op failed"})}}function Ba(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Hd(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 zd(t){let e=We(process.cwd(),t);if(!Jt(e))return[];let a=[];for(let n of Bd(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(ls(We(e,n.name),"utf-8")))}catch{}return a}function za(){let t=We(process.cwd(),"agentx.json");return Jt(t)?JSON.parse(ls(t,"utf-8")):null}function qd(){let t=za();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([g,u])=>({id:g,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(h=>{let w=h.credentials||{},y={};for(let[T,b]of Object.entries(w))typeof b=="string"&&/^[A-Z][A-Z0-9_]*$/.test(b)?y[T]=process.env[b]?"set":"unset":typeof b=="string"&&(y[T]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:w,credStatus:y,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([g,u])=>({id:g,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(([g,u])=>({id:g,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(g=>({id:g.id,source:g.source,agentId:g.agentId,secretEnv:g.secretEnv||"",description:g.description||"",enabled:g.enabled!==!1,triggers:g.triggers&&typeof g.triggers=="object"?g.triggers:{},defaultWorkflow:g.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(g=>({url:g.url,name:g.name,hasToken:!!g.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},f={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},_=t.notifications||{},v={longTaskThreshold:_.longTaskThreshold??30,destination:_.destination||null,on:{taskComplete:_.on?.taskComplete!==!1,taskError:_.on?.taskError!==!1,taskQueued:!!_.on?.taskQueued},local:er(_.local),ntfy:Zr(t.channels?.ntfy)},E=[];try{E=zd(".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,h)=>u.id.localeCompare(h.id))}catch{}let x=(Array.isArray(t.boards)?t.boards:[]).map(g=>({id:g.id,name:g.name,source:g.source||{type:"gitlab",projects:[]},primaryToolLabel:g.primaryToolLabel||"",timeRangeDays:g.timeRangeDays??30,closedWindowDays:g.closedWindowDays??30,columns:Array.isArray(g.columns)?g.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Vr(t),whatsappTriage:as(t),crons:l,webhooks:c,mesh:d,daemonUrl:p,nodeName:t.node?.name,business:f,boards:x,notifications:v,screen:Lr(t.screen),actions:E}}function Fd(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 Ud(){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 Wd(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 Gd(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 Xd(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 d=X();r=d.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=d.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 Kd(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=fs(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=We(process.cwd(),"agents",e),{summary:l}=C(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let p={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(p.model=o),s&&(p.systemPrompt=s.slice(0,400)),d.agents[e]=p,`added agent "${e}"`}),c=We(i,"CLAUDE.md");if(!Jt(c))try{Nd(i,{recursive:!0}),cs(c,`# ${a}
5518
+ `;function us(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cs({peers:a,localToken:n}))}async function ms(t,e){let a=za();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function fs(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await tp(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await qd(t),r={"GET /api/admin/state":()=>Ud(),"POST /api/admin/agents":()=>Vd(n),"PATCH /api/admin/agents":()=>Yd(n),"DELETE /api/admin/agents":()=>Qd(n),"POST /api/admin/agents/access":()=>Wd(n),"POST /api/admin/channels/telegram":()=>Zd(n),"DELETE /api/admin/channels/telegram":()=>_p(n),"POST /api/admin/channels/telegram/toggle":()=>Sp(n),"POST /api/admin/crons":()=>Ep(n),"DELETE /api/admin/crons":()=>Tp(n),"POST /api/admin/config/raw":()=>Ap(n),"GET /api/admin/tokens":()=>Gd(),"POST /api/admin/tokens":()=>Xd(n),"DELETE /api/admin/tokens":()=>Kd(n),"POST /api/admin/agents/test":()=>Jd(n),"POST /api/admin/agents/integrations":()=>ip(n),"DELETE /api/admin/agents/integrations":()=>lp(n),"PATCH /api/admin/agents/integrations":()=>cp(n),"PATCH /api/admin/channels/telegram":()=>ep(n),"POST /api/admin/channels/slack":()=>gp(n),"POST /api/admin/channels/slack/toggle":()=>xp(n),"POST /api/admin/channels/discord":()=>bp(n),"POST /api/admin/channels/discord/toggle":()=>vp(n),"POST /api/admin/channels/gitlab":()=>yp(n),"POST /api/admin/channels/gitlab/toggle":()=>wp(n),"POST /api/admin/channels/request-status":()=>Zr(n),"GET /api/admin/channels/whatsapp/state":()=>tt("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>tt("/webrtc/history"),"POST /api/admin/actions":()=>Hp(n),"DELETE /api/admin/actions":()=>zp(n),"POST /api/admin/actions/run":()=>qp(n),"GET /api/admin/channels/whatsapp/chats":()=>tt("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>tt("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>he("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>kp(n),"POST /api/admin/webhooks":()=>dp(n),"PATCH /api/admin/webhooks":()=>pp(n),"DELETE /api/admin/webhooks":()=>hp(n),"POST /api/admin/whatsapp-triage":()=>os(n),"POST /api/admin/whatsapp-triage/rules":()=>ss(n),"PATCH /api/admin/whatsapp-triage/rules":()=>is(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ls(n),"POST /api/admin/mesh/peers":()=>up(n),"DELETE /api/admin/mesh/peers":()=>mp(n),"POST /api/admin/mesh/toggle":()=>fp(n),"GET /api/admin/files":()=>ap(t),"GET /api/admin/files/read":()=>np(t),"PUT /api/admin/files":()=>rp(n),"POST /api/admin/files/skill":()=>op(n),"DELETE /api/admin/files/skill":()=>sp(n),"POST /api/admin/business/orgchart":()=>Cp(n),"DELETE /api/admin/business/orgchart":()=>Ip(n),"POST /api/admin/business/project":()=>Mp(n),"DELETE /api/admin/business/project":()=>Pp(n),"POST /api/admin/business/client":()=>Lp(n),"DELETE /api/admin/business/client":()=>Rp(n),"POST /api/admin/business/contact":()=>$p(n),"DELETE /api/admin/business/contact":()=>jp(n),"POST /api/admin/boards":()=>Op(n),"DELETE /api/admin/boards":()=>Np(n),"POST /api/admin/boards/columns":()=>Dp(n),"DELETE /api/admin/boards/columns":()=>Bp(n),"POST /api/admin/notifications":()=>Up(n),"POST /api/admin/screen":()=>Wp(n),"POST /api/admin/webhooks/triggers":()=>Gp(n),"POST /api/admin/mesh/health":()=>Fp(n),"GET /api/admin/projects":()=>tt("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>he("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>he("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>he("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>he("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>he("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>he("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>he("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>he("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Ba(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Ba(e,200,i)}catch(n){Ba(e,400,{error:n.message||"admin op failed"})}}function Ba(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function qd(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 Fd(t){let e=We(process.cwd(),t);if(!Jt(e))return[];let a=[];for(let n of zd(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(ds(We(e,n.name),"utf-8")))}catch{}return a}function za(){let t=We(process.cwd(),"agentx.json");return Jt(t)?JSON.parse(ds(t,"utf-8")):null}function Ud(){let t=za();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([x,u])=>({id:x,name:u.name,tier:u.tier,model:u.model,mentions:u.mentions||[],workspace:u.workspace,access:u.access||"private",systemPrompt:u.systemPrompt||"",maxConcurrent:u.maxConcurrent??1,maxExecutionMinutes:u.maxExecutionMinutes??20,permissionMode:u.permissionMode||"default",integrations:(Array.isArray(u.integrations)?u.integrations:[]).map(f=>{let w=f.credentials||{},y={};for(let[T,g]of Object.entries(w))typeof g=="string"&&/^[A-Z][A-Z0-9_]*$/.test(g)?y[T]=process.env[g]?"set":"unset":typeof g=="string"&&(y[T]="literal");return{kind:f.kind,label:f.label,enabled:f.enabled!==!1,credentials:w,credStatus:y,metadata:f.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([x,u])=>({id:x,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(([x,u])=>({id:x,schedule:u.schedule,agent:u.agent,prompt:(u.prompt||"").slice(0,200),enabled:u.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(x=>({id:x.id,source:x.source,agentId:x.agentId,secretEnv:x.secretEnv||"",description:x.description||"",enabled:x.enabled!==!1,triggers:x.triggers&&typeof x.triggers=="object"?x.triggers:{},defaultWorkflow:x.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(x=>({url:x.url,name:x.name,hasToken:!!x.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},p=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},S=t.notifications||{},v={longTaskThreshold:S.longTaskThreshold??30,destination:S.destination||null,on:{taskComplete:S.on?.taskComplete!==!1,taskError:S.on?.taskError!==!1,taskQueued:!!S.on?.taskQueued},local:ar(S.local),ntfy:to(t.channels?.ntfy)},E=[];try{E=Fd(".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 b=(Array.isArray(t.boards)?t.boards:[]).map(x=>({id:x.id,name:x.name,source:x.source||{type:"gitlab",projects:[]},primaryToolLabel:x.primaryToolLabel||"",timeRangeDays:x.timeRangeDays??30,closedWindowDays:x.closedWindowDays??30,columns:Array.isArray(x.columns)?x.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Qr(t),whatsappTriage:rs(t),crons:l,webhooks:c,mesh:d,daemonUrl:p,nodeName:t.node?.name,business:h,boards:b,notifications:v,screen:Pr(t.screen),actions:E}}function Wd(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 Gd(){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 Xd(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 Kd(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 Jd(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 d=X();r=d.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=d.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 Vd(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=gs(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=We(process.cwd(),"agents",e),{summary:l}=C(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let p={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(p.model=o),s&&(p.systemPrompt=s.slice(0,400)),d.agents[e]=p,`added agent "${e}"`}),c=We(i,"CLAUDE.md");if(!Jt(c))try{Bd(i,{recursive:!0}),ps(c,`# ${a}
5519
5519
 
5520
5520
  ${s||"You are "+a+"."}
5521
- `)}catch{}return{summary:l}}function Jd(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=fs(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function Vd(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 Yd(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 Qd(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 tt(t){let{url:e,headers:a}=qa(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function he(t,e){let{url:a,headers:n}=qa(),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 Zd(t,e){try{let{url:a,headers:n}=qa(),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 qa(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function at(t){let a=za()?.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 Ha(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ep(t){let e=Ha(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=He(at(e));return{agentId:e,...a}}function tp(t){let e=Ha(t,"agent").trim(),a=Ha(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ct(at(e),a)}function ap(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=It(at(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function 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=Mt(at(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function rp(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Lt(at(e),a);return{summary:`removed skill "${a}"`,...n}}function op(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)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 sp(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 ip(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(d=>d.kind===a&&d.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 ms=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function lp(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(!ms.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(p=>p.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(d=>d.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 cp(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"&&ms.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 dp(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 pp(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 up(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 mp(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 fp(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 hp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function gp(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=C(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function xp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function vp(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 bp(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 yp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-PGUELFMB.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 wp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=C(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function kp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function _p(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 Sp(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 Ep(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=We(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Jt(n))try{Dd(n,r)}catch{}cs(n,JSON.stringify(a,null,2)+`
5522
- `,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function fs(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Tp(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 Ap(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 Cp(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 Ip(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 Mp(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 Lp(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 Rp(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 Pp(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 $p(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(p=>p.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let p=l.boards[c];return l.boards[c]={...p,...d,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function jp(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 Op(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(p=>p.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let 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 d=l.columns.findIndex(p=>p.id===a);return d>=0?(l.columns[d]={...l.columns[d],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Np(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 Dp(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 Bp(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 Hp(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 zp(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=C(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function qp(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=tr(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=eo(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 Fp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Rr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Up(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ft();import{resolve as Xp}from"path";function hs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
5521
+ `)}catch{}return{summary:l}}function Yd(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=gs(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function Qd(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 Zd(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 ep(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 tt(t){let{url:e,headers:a}=qa(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function he(t,e){let{url:a,headers:n}=qa(),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 tp(t,e){try{let{url:a,headers:n}=qa(),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 qa(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function at(t){let a=za()?.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 Ha(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ap(t){let e=Ha(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=He(at(e));return{agentId:e,...a}}function np(t){let e=Ha(t,"agent").trim(),a=Ha(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ct(at(e),a)}function rp(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=It(at(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function op(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=Mt(at(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function sp(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Lt(at(e),a);return{summary:`removed skill "${a}"`,...n}}function ip(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 lp(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(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 cp(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(d=>d.kind===a&&d.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 hs=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function dp(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!hs.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=C(l=>{if(s){if(!(l.mesh?.peers||[]).find(p=>p.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(d=>d.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 pp(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"&&hs.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 mp(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 fp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function hp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=C(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function gp(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 xp(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 bp(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 vp(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 yp(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=C(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function wp(t){let e=!!t?.enabled,{summary:a}=C(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function kp(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-L4P4Z55R.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 _p(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 Sp(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 Ep(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 Tp(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 Ap(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=We(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Jt(n))try{Hd(n,r)}catch{}ps(n,JSON.stringify(a,null,2)+`
5522
+ `,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function gs(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Cp(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 Ip(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 Mp(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 Lp(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 Rp(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 Pp(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 $p(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 jp(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 Op(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(p=>p.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let p=l.boards[c];return l.boards[c]={...p,...d,columns:p.columns,labels:p.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function Np(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 Dp(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=C(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(p=>p.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let 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 d=l.columns.findIndex(p=>p.id===a);return d>=0?(l.columns[d]={...l.columns[d],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Bp(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 Hp(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 zp(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 qp(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 Fp(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=C(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function Up(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=nr(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 Wp(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=$r(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Gp(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ft();import{resolve as Jp}from"path";function xs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
5523
5523
 
5524
5524
  <div id="disabled-banner" class="banner warn" style="display:none">
5525
5525
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -5574,7 +5574,7 @@ ${s||"You are "+a+"."}
5574
5574
  <h2>Recent classifications</h2>
5575
5575
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
5576
5576
  <div id="recent"></div>
5577
- </section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Wp,scripts:`${e}<script>${Gp}</script>`})}var Wp=`
5577
+ </section>`;return I({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Xp,scripts:`${e}<script>${Kp}</script>`})}var Xp=`
5578
5578
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
5579
5579
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
5580
5580
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -5678,7 +5678,7 @@ details {
5678
5678
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
5679
5679
  }
5680
5680
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
5681
- details[open] summary { margin-bottom: 8px; }`,Gp=`
5681
+ details[open] summary { margin-bottom: 8px; }`,Kp=`
5682
5682
  const $ = (id) => document.getElementById(id);
5683
5683
  const state = { schema: null, nodes: [], pending: [], recent: [] };
5684
5684
 
@@ -5898,7 +5898,7 @@ $('btn-save-schema').addEventListener('click', async () => {
5898
5898
  $('btn-reload-schema').addEventListener('click', refresh);
5899
5899
 
5900
5900
  refresh();
5901
- `;function xs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hs({peers:a,localToken:n}))}async function vs(t,e,a){try{let n=t.method==="GET"?void 0:await au(t),r=Kp(),o={"GET /api/admin/graph/state":()=>Jp(r),"POST /api/admin/graph/classifications/approve":()=>Vp(r,n),"POST /api/admin/graph/classifications/reject":()=>Yp(r,n),"POST /api/admin/graph/nodes":()=>Qp(r,n),"PATCH /api/admin/graph/nodes":()=>Zp(r,n),"DELETE /api/admin/graph/nodes":()=>eu(r,n),"PUT /api/admin/graph/schema":()=>tu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Fa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Fa(e,200,l)}catch(n){Fa(e,400,{error:n?.message||"graph op failed"})}}function Kp(){let t=X(),e=Xp(process.cwd(),t.graph.baseDir);return new zn({baseDir:e})}function Jp(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 Vp(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=bs(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=Ua(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Yp(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=bs(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function bs(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 Qp(t,e){let a=gs(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?gs(String(e.parentId)):null,o=Ua({[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 Zp(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ua({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function eu(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function tu(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 Ua(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 gs(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Fa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function au(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 ys=`
5901
+ `;function vs(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xs({peers:a,localToken:n}))}async function ys(t,e,a){try{let n=t.method==="GET"?void 0:await ru(t),r=Vp(),o={"GET /api/admin/graph/state":()=>Yp(r),"POST /api/admin/graph/classifications/approve":()=>Qp(r,n),"POST /api/admin/graph/classifications/reject":()=>Zp(r,n),"POST /api/admin/graph/nodes":()=>eu(r,n),"PATCH /api/admin/graph/nodes":()=>tu(r,n),"DELETE /api/admin/graph/nodes":()=>au(r,n),"PUT /api/admin/graph/schema":()=>nu(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Fa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Fa(e,200,l)}catch(n){Fa(e,400,{error:n?.message||"graph op failed"})}}function Vp(){let t=X(),e=Jp(process.cwd(),t.graph.baseDir);return new zn({baseDir:e})}function Yp(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 Qp(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=Ua(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Zp(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 eu(t,e){let a=bs(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?bs(String(e.parentId)):null,o=Ua({[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 tu(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ua({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function au(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 Ua(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 bs(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Fa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ru(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 ks=`
5902
5902
  <section class="apv__req" id="req-section" aria-labelledby="req-h">
5903
5903
  <h2 id="req-h">Open requests <span id="req-n"></span></h2>
5904
5904
  <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>
@@ -5920,7 +5920,7 @@ refresh();
5920
5920
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5921
5921
  </form>
5922
5922
  </details>
5923
- </section>`,ws=`
5923
+ </section>`,_s=`
5924
5924
  .apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
5925
5925
  .apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
5926
5926
  .apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
@@ -5948,7 +5948,7 @@ refresh();
5948
5948
  .apv__plan .is-done { color: var(--ax-ok, inherit); }
5949
5949
  .apv__plan .is-blocked { color: var(--ax-err); }
5950
5950
  .apv__plan small { display: block; color: var(--ax-muted); }
5951
- `,ks=`
5951
+ `,Ss=`
5952
5952
  (function(){
5953
5953
  var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
5954
5954
  function $(id){ return document.getElementById(id); }
@@ -6113,7 +6113,7 @@ function busy(){
6113
6113
  }
6114
6114
  setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
6115
6115
  })();
6116
- `;function _s(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6116
+ `;function Es(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
6117
6117
  <header class="apv__head">
6118
6118
  <div>
6119
6119
  <h1>Approvals</h1>
@@ -6135,7 +6135,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
6135
6135
  <ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
6136
6136
  <p id="apv-snoozed" class="apv__foot"></p>
6137
6137
 
6138
- ${ys}
6138
+ ${ks}
6139
6139
 
6140
6140
  <details class="apv__settings" id="apv-settings">
6141
6141
  <summary>Settings: expiry, later, daily digest</summary>
@@ -6150,7 +6150,7 @@ ${ys}
6150
6150
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
6151
6151
  </form>
6152
6152
  </details>
6153
- </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:nu+ws,scripts:`${e}<script>${ru}</script><script>${ks}</script>`})}var nu=`
6153
+ </div>`;return I({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ou+_s,scripts:`${e}<script>${su}</script><script>${Ss}</script>`})}var ou=`
6154
6154
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
6155
6155
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
6156
6156
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -6207,7 +6207,7 @@ ${ys}
6207
6207
  @media (max-width: 560px) {
6208
6208
  .apv__acts .ax-btn { flex: 1 1 0; }
6209
6209
  }
6210
- `,ru=`
6210
+ `,su=`
6211
6211
  (function(){
6212
6212
  var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
6213
6213
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
@@ -6431,7 +6431,7 @@ $('apv-form').addEventListener('submit', async function(ev){
6431
6431
  load();
6432
6432
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within, .apv__item[data-touched]')) load(); }, 60000);
6433
6433
  })();
6434
- `;import{existsSync as ou,readFileSync as su}from"fs";var Me="/api/admin/approvals/requests";function Ss(t){let e=Xn(t);if(!ou(e))return[];try{let a=JSON.parse(su(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 Vt=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Es(t,e,a,n){try{return await iu(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function iu(t,e,a,n){if(t==="GET"&&e===Me){let o=St(n);return{status:200,body:{items:o?o.listOpen().map(s=>mr(s,o,dr(n))):[],agents:Ss(n.configPath),settings:_t(n.configPath)}}}let r=e===`${Me}/reply`?"reply":e===`${Me}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=St(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",p=Ss(n.configPath).find(f=>f.id===d);if(r==="handoff"&&!p)return{status:400,body:{error:`"${d}" is not an agent on this node`}};if(!_t(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,d,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=p?.name??d;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Me}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=St(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Me}/settings`){let o={},s=c=>{let d=a[c];if(d!==void 0){if(typeof d!="number"||!(d>0))throw new Error(`${c} must be a positive number`);return d}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=Vt(a.from),o.channels=Vt(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i={};if(typeof a.plansEnabled=="boolean"&&(i.enabled=a.plansEnabled),i.stallMinutes=s("stallMinutes"),a.maxNudges!==void 0){if(typeof a.maxNudges!="number"||!Number.isInteger(a.maxNudges)||a.maxNudges<0)throw new Error("maxNudges must be a whole number, 0 or more");i.maxNudges=a.maxNudges}i.approveKinds=Vt(a.approveKinds),i.disabledAgents=Vt(a.plansOffFor),Object.values(i).some(c=>c!==void 0)&&(o.plans=i);let l=await cr(o,{configPath:n.configPath,reload:n.reload});return l.success?{status:200,body:{ok:!0,settings:_t(n.configPath)}}:{status:400,body:{error:l.error}}}return{status:404,body:{error:"Not found"}}}var lu=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Yt(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 cu(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 Ts(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(_s({peers:e,localToken:a}))}async function As(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Me)){let i=await Es(o,a,o==="POST"?await Yt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=Et(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:Ae(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Yt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!lu.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let d=Ae(s.configPath),p=await Tt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:d.laterHours,by:"operator (dashboard)",...cu(i)});return p.ok?(te(e,200,{ok:!0,message:p.message}),!0):(te(e,409,{error:p.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Yt(t),l=fr(s,typeof i.key=="string"?i.key:"",!!Ae(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Yt(t),l={},c=p=>{let m=i[p];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${p} must be a positive number`);return m}};if(l.defaultExpiryDays=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 p=i.destination.trim();if(!p)l.destination=null;else{let m=qr(p);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let d=await Fr(l,{configPath:s.configPath,reload:s.reload});return d.success?(te(e,200,{ok:!0,settings:Ae(s.configPath)}),!0):(te(e,400,{error:d.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}va();function Cs(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=de({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."})+`
6434
+ `;import{existsSync as iu,readFileSync as lu}from"fs";var Me="/api/admin/approvals/requests";function Ts(t){let e=Xn(t);if(!iu(e))return[];try{let a=JSON.parse(lu(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 Vt=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function As(t,e,a,n){try{return await cu(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function cu(t,e,a,n){if(t==="GET"&&e===Me){let o=St(n);return{status:200,body:{items:o?o.listOpen().map(s=>hr(s,o,ur(n))):[],agents:Ts(n.configPath),settings:_t(n.configPath)}}}let r=e===`${Me}/reply`?"reply":e===`${Me}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=St(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",p=Ts(n.configPath).find(h=>h.id===d);if(r==="handoff"&&!p)return{status:400,body:{error:`"${d}" is not an agent on this node`}};if(!_t(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,d,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=p?.name??d;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Me}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=St(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Me}/settings`){let o={},s=c=>{let d=a[c];if(d!==void 0){if(typeof d!="number"||!(d>0))throw new Error(`${c} must be a positive number`);return d}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=Vt(a.from),o.channels=Vt(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i={};if(typeof a.plansEnabled=="boolean"&&(i.enabled=a.plansEnabled),i.stallMinutes=s("stallMinutes"),a.maxNudges!==void 0){if(typeof a.maxNudges!="number"||!Number.isInteger(a.maxNudges)||a.maxNudges<0)throw new Error("maxNudges must be a whole number, 0 or more");i.maxNudges=a.maxNudges}i.approveKinds=Vt(a.approveKinds),i.disabledAgents=Vt(a.plansOffFor),Object.values(i).some(c=>c!==void 0)&&(o.plans=i);let l=await pr(o,{configPath:n.configPath,reload:n.reload});return l.success?{status:200,body:{ok:!0,settings:_t(n.configPath)}}:{status:400,body:{error:l.error}}}return{status:404,body:{error:"Not found"}}}var du=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Yt(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 pu(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 Cs(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Es({peers:e,localToken:a}))}async function Is(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Me)){let i=await As(o,a,o==="POST"?await Yt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=Et(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:Ae(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Yt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!du.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let d=Ae(s.configPath),p=await Tt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:d.laterHours,by:"operator (dashboard)",...pu(i)});return p.ok?(te(e,200,{ok:!0,message:p.message}),!0):(te(e,409,{error:p.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Yt(t),l=gr(s,typeof i.key=="string"?i.key:"",!!Ae(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Yt(t),l={},c=p=>{let m=i[p];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${p} must be a positive number`);return m}};if(l.defaultExpiryDays=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 p=i.destination.trim();if(!p)l.destination=null;else{let m=Ur(p);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let d=await Wr(l,{configPath:s.configPath,reload:s.reload});return d.success?(te(e,200,{ok:!0,settings:Ae(s.configPath)}),!0):(te(e,400,{error:d.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}ba();function Ms(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=de({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."})+`
6435
6435
  <div class="pp">
6436
6436
  <div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
6437
6437
  <section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
@@ -6444,7 +6444,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6444
6444
  </ol>
6445
6445
  </section>
6446
6446
  <ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
6447
- </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:du,scripts:`${e}<script>${pu}</script>`})}var du=`
6447
+ </div>`;return I({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:uu,scripts:`${e}<script>${mu}</script>`})}var uu=`
6448
6448
  .pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
6449
6449
  .pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
6450
6450
  .pp-msg.is-bad { color: var(--ax-red-ink); }
@@ -6485,7 +6485,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6485
6485
  .pp-text { overflow-wrap: anywhere; }
6486
6486
  .pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
6487
6487
  @media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
6488
- `,pu=`
6488
+ `,mu=`
6489
6489
  (function () {
6490
6490
  var list = document.getElementById('pp-list');
6491
6491
  var msg = document.getElementById('pp-msg');
@@ -6623,7 +6623,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6623
6623
  load();
6624
6624
  setInterval(load, 30000);
6625
6625
  })();
6626
- `;var Wa="/api/admin/people";function uu(t,e){let a=Xr(t,e);return a?{...e,answer:a}:e}function mu(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function ge(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function fu(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&mu(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:mt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var hu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Is(t,e,a,n){if(a!=="/people"&&a!==Wa&&!a.startsWith(`${Wa}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(ge(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Cs({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return ge(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(d=>uu(n.root,d)),s=()=>fu(n.people(),o());if(r==="GET"&&a===Wa){let c=s();return ge(e,200,{people:c,paired:c.reduce((d,p)=>d+p.machines.active+p.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(f=>f.id===i[1]);if(!c)return ge(e,404,{error:`no person "${i[1]}"`}),!0;let d=n.db(),p=[],m=[];try{d&&(p=Ur(d,c.id))}catch{}try{d&&(m=jt(d,c.id,20))}catch{}return ge(e,200,{person:c,devices:o(c.id).sort(hu),requests:p,runs:m,database:!!d}),!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,d]=l,p=n.members.byToken(d);if(!p||p.personId!==c)return ge(e,404,{error:"no such machine for this person"}),!0;if(p.state==="removed")return ge(e,409,{error:"this machine's access has already ended"}),!0;let m=Jr({tokens:n.tokens??new G,members:n.members,now:n.now},d,"removed by the owner (dashboard)");return ge(e,200,{ok:!0,device:m}),!0}return ge(e,404,{error:"not found"}),!0}import{resolve as yu}from"path";import{existsSync as wu}from"fs";import ku from"better-sqlite3";var Ms=new WeakSet;function gu(t,e,a={}){if(Ms.has(t))return;Ms.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]=(...d)=>{let p=r();try{return c(...d)}finally{let m=r()-p;m>=n&&e({sql:s,ms:m})}}}return i}}function xu(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ke(t,e){gu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${xu(a)}`))}function Ls(t={}){let e=`<div class="ax-obs">
6626
+ `;var Wa="/api/admin/people";function fu(t,e){let a=Jr(t,e);return a?{...e,answer:a}:e}function hu(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function ge(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function gu(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&hu(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:mt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var xu=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Ls(t,e,a,n){if(a!=="/people"&&a!==Wa&&!a.startsWith(`${Wa}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(ge(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Ms({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return ge(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(d=>fu(n.root,d)),s=()=>gu(n.people(),o());if(r==="GET"&&a===Wa){let c=s();return ge(e,200,{people:c,paired:c.reduce((d,p)=>d+p.machines.active+p.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(h=>h.id===i[1]);if(!c)return ge(e,404,{error:`no person "${i[1]}"`}),!0;let d=n.db(),p=[],m=[];try{d&&(p=Gr(d,c.id))}catch{}try{d&&(m=jt(d,c.id,20))}catch{}return ge(e,200,{person:c,devices:o(c.id).sort(xu),requests:p,runs:m,database:!!d}),!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,d]=l,p=n.members.byToken(d);if(!p||p.personId!==c)return ge(e,404,{error:"no such machine for this person"}),!0;if(p.state==="removed")return ge(e,409,{error:"this machine's access has already ended"}),!0;let m=Yr({tokens:n.tokens??new G,members:n.members,now:n.now},d,"removed by the owner (dashboard)");return ge(e,200,{ok:!0,device:m}),!0}return ge(e,404,{error:"not found"}),!0}import{resolve as ku}from"path";import{existsSync as _u}from"fs";import Su from"better-sqlite3";var Rs=new WeakSet;function bu(t,e,a={}){if(Rs.has(t))return;Rs.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]=(...d)=>{let p=r();try{return c(...d)}finally{let m=r()-p;m>=n&&e({sql:s,ms:m})}}}return i}}function vu(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ke(t,e){bu(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${vu(a)}`))}function Ps(t={}){let e=`<div class="ax-obs">
6627
6627
  <header class="ax-obs__head">
6628
6628
  <h1>Health</h1>
6629
6629
  <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>
@@ -6745,7 +6745,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6745
6745
  </div>
6746
6746
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
6747
6747
  </section>
6748
- </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:vu,scripts:`<script>${bu}</script>`})}var vu=`
6748
+ </div>`;return I({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:yu,scripts:`<script>${wu}</script>`})}var yu=`
6749
6749
  .ax-obs { padding: 16px 24px; }
6750
6750
  .ax-obs__head { margin-bottom: 16px; }
6751
6751
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -6862,7 +6862,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6862
6862
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
6863
6863
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
6864
6864
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
6865
- `,bu=`
6865
+ `,wu=`
6866
6866
  (function(){
6867
6867
  var panes = document.querySelectorAll('.ax-obs__pane');
6868
6868
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -7246,7 +7246,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7246
7246
 
7247
7247
  load(current);
7248
7248
  })();
7249
- `;var $s={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 js(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ga(t){let e=$s[js(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 _u(){let t=yu(process.cwd(),".agentx/db.sqlite");if(!wu(t))return null;try{let e=new ku(t,{readonly:!0,fileMustExist:!0});return ke(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Os(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ls({peers:a}))}function Su(t){let e=new URL(t.url||"/","http://_"),a=parseInt(e.searchParams.get("limit")||"50",10),n=Number.isFinite(a)?Math.max(1,Math.min(500,a)):50,r=e.searchParams.get("agent")||void 0;return{limit:n,agent:r&&r.length>0?r:void 0}}function xe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Ns(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=_u();if(!r)return xe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Su(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
7249
+ `;var Os={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 Ns(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ga(t){let e=Os[Ns(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 Eu(){let t=ku(process.cwd(),".agentx/db.sqlite");if(!_u(t))return null;try{let e=new Su(t,{readonly:!0,fileMustExist:!0});return ke(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Ds(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ps({peers:a}))}function Tu(t){let e=new URL(t.url||"/","http://_"),a=parseInt(e.searchParams.get("limit")||"50",10),n=Number.isFinite(a)?Math.max(1,Math.min(500,a)):50,r=e.searchParams.get("agent")||void 0;return{limit:n,agent:r&&r.length>0?r:void 0}}function xe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Bs(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Eu();if(!r)return xe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Tu(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
7250
7250
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
7251
7251
  FROM route_traces
7252
7252
  ${i.length?"WHERE "+i.join(" AND "):""}
@@ -7261,8 +7261,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7261
7261
  FROM task_history
7262
7262
  WHERE ${i.join(" AND ")}
7263
7263
  ORDER BY started_at DESC LIMIT @limit
7264
- `,p=r.db.prepare(c).all(l).map(m=>({...m,plain:Ds(m.error)}));return xe(e,200,{rows:p}),!0}if(n==="summary"||n==="overview")return xe(e,200,Eu(r.db)),!0;if(n==="activity")return xe(e,200,Tu(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Rs(i.searchParams.get("range"));return xe(e,200,Ps(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Rs(i.searchParams.get("range")),c=Ps(r.db,l),d=Au(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(d),!0}return xe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return xe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Ds(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(`
7265
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Eu(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,d=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),p=b=>d.length?d[Math.min(d.length-1,Math.floor(d.length*b))].duration_ms:0,m=p(.5),f=p(.95),v=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((b,A)=>b+Ga(A),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((b,A)=>b+Ga(A),0),x=t.prepare(`
7264
+ `,p=r.db.prepare(c).all(l).map(m=>({...m,plain:Hs(m.error)}));return xe(e,200,{rows:p}),!0}if(n==="summary"||n==="overview")return xe(e,200,Au(r.db)),!0;if(n==="activity")return xe(e,200,Cu(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=$s(i.searchParams.get("range"));return xe(e,200,js(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=$s(i.searchParams.get("range")),c=js(r.db,l),d=Iu(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(d),!0}return xe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return xe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Hs(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(`
7265
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Au(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,d=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),p=g=>d.length?d[Math.min(d.length-1,Math.floor(d.length*g))].duration_ms:0,m=p(.5),h=p(.95),v=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((g,A)=>g+Ga(A),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((g,A)=>g+Ga(A),0),b=t.prepare(`
7266
7266
  SELECT agent_id,
7267
7267
  COUNT(*) AS tasks,
7268
7268
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -7272,7 +7272,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7272
7272
  WHERE started_at >= ?
7273
7273
  GROUP BY agent_id
7274
7274
  ORDER BY tasks DESC LIMIT 10
7275
- `).all(a),g=t.prepare(`
7275
+ `).all(a),x=t.prepare(`
7276
7276
  SELECT COALESCE(channel, 'unknown') AS channel,
7277
7277
  COUNT(*) AS tasks,
7278
7278
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -7280,12 +7280,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7280
7280
  WHERE started_at >= ?
7281
7281
  GROUP BY channel
7282
7282
  ORDER BY tasks DESC
7283
- `).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(b=>b.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(b=>b.agent_id)),w=u.filter(b=>!h.has(b)),T=t.prepare(`
7283
+ `).all(a),u=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(g=>g.agent_id),f=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(g=>g.agent_id)),w=u.filter(g=>!f.has(g)),T=t.prepare(`
7284
7284
  SELECT started_at, agent_id, channel, message_preview, error
7285
7285
  FROM task_history
7286
7286
  WHERE status='error' AND started_at >= ?
7287
7287
  ORDER BY started_at DESC LIMIT 5
7288
- `).all(o).map(b=>({...b,plain:Ds(b.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:f,spendToday:v,spendDelta:v-E,idleAgentCount:w.length},perAgent:x,perChannel:g,idleAgents:w,recentErrors:T}}function Tu(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(`
7288
+ `).all(o).map(g=>({...g,plain:Hs(g.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:v,spendDelta:v-E,idleAgentCount:w.length},perAgent:b,perChannel:x,idleAgents:w,recentErrors:T}}function Cu(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(`
7289
7289
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
7290
7290
  COUNT(*) AS tasks,
7291
7291
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -7312,7 +7312,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7312
7312
  WHERE started_at >= @since
7313
7313
  GROUP BY agent_id
7314
7314
  ORDER BY tasks_24h DESC, tasks_7d DESC
7315
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Rs(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 Ps(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7315
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function $s(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 js(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
7316
7316
  SELECT day, agent_id, model,
7317
7317
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
7318
7318
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -7320,20 +7320,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7320
7320
  FROM usage_daily
7321
7321
  ${a}
7322
7322
  ORDER BY day
7323
- `).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,d=0,p=0,m=0,f=0,_=0,v=0,E=0,x={},g={};for(let S of n){let L=Ga(S),j=js(S.model),$=$s[j],O=(S.tier2_input_tokens||0)/1e6*$.input*.5+(S.tier2_output_tokens||0)/1e6*$.output*.5+(S.tier2_cache_read_tokens||0)/1e6*$.cacheRead*.5+(S.tier2_cache_create_tokens||0)/1e6*$.cacheCreate*.5,W=(S.input_tokens||0)+(S.tier2_input_tokens||0),le=(S.output_tokens||0)+(S.tier2_output_tokens||0),Q=(S.cache_read_tokens||0)+(S.tier2_cache_read_tokens||0),re=(S.cache_create_tokens||0)+(S.tier2_cache_create_tokens||0);p+=L,S.day>=s&&(d+=L,_+=S.tasks||0),S.day>=i&&S.day<s&&(E+=L,v+=S.tasks||0),S.day===r&&(l+=L),S.day===o&&(c+=L),S.day===r&&(m+=O),S.day>=s&&(f+=O);let Z=x[S.day]||(x[S.day]={date:S.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=S.tasks||0,Z.input+=W,Z.output+=le,Z.cacheRead+=Q,Z.cacheCreate+=re,Z.cost+=L,Z.tier2+=O;let F=Z.agents[S.agent_id]||(Z.agents[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});F.tasks+=S.tasks||0,F.cost+=L,F.tier2+=O,F.input+=W,F.output+=le,F.cacheRead+=Q,F.cacheCreate+=re,S.model&&(F.model=S.model);let N=g[S.agent_id]||(g[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});N.tasks+=S.tasks||0,N.cost+=L,N.tier2+=O,N.input+=W,N.output+=le,N.cacheRead+=Q,N.cacheCreate+=re,S.model&&(N.model=S.model)}let u=Object.values(x).sort((S,L)=>S.date<L.date?-1:1),h=0,w=0,y=0,T=0,b=0,A=0;for(let S of u)h+=S.tasks,w+=S.input,y+=S.output,T+=S.cacheRead,b+=S.cacheCreate,A+=S.cost;let R=Object.entries(g).map(([S,L])=>({agent_id:S,...L,tokens:L.input+L.output+L.cacheRead+L.cacheCreate})).sort((S,L)=>L.cost-S.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:d,spend30d:p,tier2Today:m,tier2_7d:f,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:h,tokensRange:w+y+T+b,cacheHitRange:T+w>0?T/(T+w):0,costPerTaskRange:h>0?A/h:0,spendDeltaWoW:E>0?(d-E)/E:0,tasksDeltaWoW:v>0?(_-v)/v:0},days:u,perAgent:R}}function Au(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+`
7323
+ `).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,d=0,p=0,m=0,h=0,S=0,v=0,E=0,b={},x={};for(let _ of n){let L=Ga(_),j=Ns(_.model),$=Os[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),le=(_.output_tokens||0)+(_.tier2_output_tokens||0),Q=(_.cache_read_tokens||0)+(_.tier2_cache_read_tokens||0),re=(_.cache_create_tokens||0)+(_.tier2_cache_create_tokens||0);p+=L,_.day>=s&&(d+=L,S+=_.tasks||0),_.day>=i&&_.day<s&&(E+=L,v+=_.tasks||0),_.day===r&&(l+=L),_.day===o&&(c+=L),_.day===r&&(m+=O),_.day>=s&&(h+=O);let Z=b[_.day]||(b[_.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+=le,Z.cacheRead+=Q,Z.cacheCreate+=re,Z.cost+=L,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+=L,F.tier2+=O,F.input+=W,F.output+=le,F.cacheRead+=Q,F.cacheCreate+=re,_.model&&(F.model=_.model);let N=x[_.agent_id]||(x[_.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:_.model});N.tasks+=_.tasks||0,N.cost+=L,N.tier2+=O,N.input+=W,N.output+=le,N.cacheRead+=Q,N.cacheCreate+=re,_.model&&(N.model=_.model)}let u=Object.values(b).sort((_,L)=>_.date<L.date?-1:1),f=0,w=0,y=0,T=0,g=0,A=0;for(let _ of u)f+=_.tasks,w+=_.input,y+=_.output,T+=_.cacheRead,g+=_.cacheCreate,A+=_.cost;let R=Object.entries(x).map(([_,L])=>({agent_id:_,...L,tokens:L.input+L.output+L.cacheRead+L.cacheCreate})).sort((_,L)=>L.cost-_.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:d,spend30d:p,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:A,avgDailyRange:u.length?A/u.length:0,tasksRange:f,tokensRange:w+y+T+g,cacheHitRange:T+w>0?T/(T+w):0,costPerTaskRange:f>0?A/f:0,spendDeltaWoW:E>0?(d-E)/E:0,tasksDeltaWoW:v>0?(S-v)/v:0},days:u,perAgent:R}}function Iu(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+`
7324
7324
  `+a.join(`
7325
7325
  `)+`
7326
- `}import{resolve as Cu}from"path";import{existsSync as Iu}from"fs";import Mu from"better-sqlite3";function Lu(){let t=Cu(process.cwd(),".agentx/intent/ledger.sqlite");if(!Iu(t))return null;try{let e=new Mu(t,{readonly:!0,fileMustExist:!0});return ke(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Bs>6e4&&(Bs=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Bs=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ru(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 Hs(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Lu();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=Ru(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),d=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let p=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",f=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),_=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,v=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${p}`).get({since:s}).n,x=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),g=r.db.prepare(`
7326
+ `}import{resolve as Mu}from"path";import{existsSync as Lu}from"fs";import Ru from"better-sqlite3";function Pu(){let t=Mu(process.cwd(),".agentx/intent/ledger.sqlite");if(!Lu(t))return null;try{let e=new Ru(t,{readonly:!0,fileMustExist:!0});return ke(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-zs>6e4&&(zs=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var zs=0;function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $u(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 qs(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Pu();if(!r)return Le(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=$u(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),d=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let p=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,v=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${p}`).get({since:s}).n,b=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${p} GROUP BY source ORDER BY n DESC`).all({since:s}),x=r.db.prepare(`
7327
7327
  SELECT COUNT(*) AS n FROM intent_decisions d
7328
7328
  LEFT JOIN intent_resolutions r
7329
7329
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7330
7330
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
7331
- `).get().n;return Le(e,200,{since:s??null,eventsBySource:f,totalDecisions:_,decisionsByOutcome:v,totalDivergences:E,divergencesBySource:x,inFlight:g}),!0}if(n==="events"){let p=[],m={limit:d};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i),l&&(p.push("project = @project"),m.project=l);let f=`
7331
+ `).get().n;return Le(e,200,{since:s??null,eventsBySource:h,totalDecisions:S,decisionsByOutcome:v,totalDivergences:E,divergencesBySource:b,inFlight:x}),!0}if(n==="events"){let p=[],m={limit:d};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i),l&&(p.push("project = @project"),m.project=l);let h=`
7332
7332
  SELECT id, ts, source, source_event_id, project, subject, intent
7333
7333
  FROM intent_events
7334
7334
  ${p.length?"WHERE "+p.join(" AND "):""}
7335
7335
  ORDER BY ts DESC LIMIT @limit
7336
- `;return Le(e,200,{rows:r.db.prepare(f).all(m)}),!0}if(n==="divergences"){let p=[],m={limit:d};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i);let f=`
7336
+ `;return Le(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="divergences"){let p=[],m={limit:d};s!==void 0&&(p.push("ts >= @since"),m.since=s),i&&(p.push("source = @source"),m.source=i);let h=`
7337
7337
  SELECT ts, source, decided_by,
7338
7338
  legacy_agent_id, legacy_outcome, legacy_reason,
7339
7339
  ledger_agent_id, ledger_outcome, ledger_reason,
@@ -7341,7 +7341,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7341
7341
  FROM intent_divergences
7342
7342
  ${p.length?"WHERE "+p.join(" AND "):""}
7343
7343
  ORDER BY ts DESC LIMIT @limit
7344
- `;return Le(e,200,{rows:r.db.prepare(f).all(m)}),!0}if(n==="active"){let p=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:d};i&&(p.push("e.source = @source"),m.source=i);let f=`
7344
+ `;return Le(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="active"){let p=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:d};i&&(p.push("e.source = @source"),m.source=i);let h=`
7345
7345
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
7346
7346
  d.decided_by, d.decided_at, d.agent_id, d.reason
7347
7347
  FROM intent_decisions d
@@ -7350,7 +7350,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7350
7350
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
7351
7351
  WHERE ${p.join(" AND ")}
7352
7352
  ORDER BY d.decided_at DESC LIMIT @limit
7353
- `;return Le(e,200,{rows:r.db.prepare(f).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 zs(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7353
+ `;return Le(e,200,{rows:r.db.prepare(h).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 Fs(t={}){return I({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
7354
7354
  <header class="ax-led__head">
7355
7355
  <h1>Intent ledger</h1>
7356
7356
  <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>
@@ -7555,7 +7555,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7555
7555
  }
7556
7556
  load();
7557
7557
  })();
7558
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function qs(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7558
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Us(t={}){return I({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7559
7559
  <header class="ax-cost__head">
7560
7560
  <div>
7561
7561
  <h1>Cost</h1>
@@ -8128,7 +8128,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8128
8128
  load();
8129
8129
  setInterval(load, 30000);
8130
8130
  })();
8131
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Fs(t={}){let e=`<div class="ax-pj__root">
8131
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Ws(t={}){let e=`<div class="ax-pj__root">
8132
8132
  <aside class="ax-pj__list">
8133
8133
  <header>
8134
8134
  <h2>Projects</h2>
@@ -8155,7 +8155,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8155
8155
  </header>
8156
8156
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
8157
8157
  </section>
8158
- </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Pu,scripts:`<script>${$u}</script>`})}var Pu=`
8158
+ </div>`;return I({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ju,scripts:`<script>${Ou}</script>`})}var ju=`
8159
8159
  .ax-pj__root {
8160
8160
  display: grid;
8161
8161
  grid-template-columns: 360px 1fr;
@@ -8342,7 +8342,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8342
8342
  }
8343
8343
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
8344
8344
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
8345
- `,$u=`
8345
+ `,Ou=`
8346
8346
  (function(){
8347
8347
  const $ = (sel) => document.querySelector(sel);
8348
8348
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -8992,20 +8992,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8992
8992
  load();
8993
8993
  });
8994
8994
  })();
8995
- `;import{resolve as Ya,join as Vu}from"path";import{existsSync as Qa,readdirSync as Yu,readFileSync as Qu}from"fs";import Zu from"better-sqlite3";var Ws=String.raw`[\w.-]+(?:/[\w.-]+)+`,ju=new RegExp(`^(?:chat:)?(${Ws}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Ou=new RegExp(`^\\[(?:GitLab|GitHub) (${Ws}) `);function Us(t){if(!t)return null;let e=t.match(ju);return e?e[1]:null}function Xa(t){if(!t)return null;let e=t.trimStart().match(Ou);return e?e[1]:null}function Qt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Us(typeof n?.chatId=="string"?n.chatId:null)??Us(e)??Xa(a)}function Nu(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Zt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Du=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Bu=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Hu=t=>/^issue/i.test(t)?"issue":"mr";function zu(t){let e=t.subject.match(Du)??t.inputPreview.trimStart().match(Bu);return e?{kind:Hu(e[1]),n:Number(e[2])}:null}function qu(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function Gs(t){if(!Nu(t.projectId))return[];let e=zu(t);return e?[e]:qu(t.inputPreview)}var Fu=6e4,Uu=5*6e4,Wu=40,Xs=6,Ks=new Map;function Js(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 Gs(n)){let s=Zt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Wu)return[...e.values()]}}return[...e.values()]}async function Vs(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Zt(s.project,s.ref),l=Ks.get(i);l&&n-l.at<(s.github?Uu:Fu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Xs)await Promise.all(o.slice(s,s+Xs).map(async i=>{let l=Zt(i.project,i.ref),c=null;try{c=i.github?await Xu(i,e,a):await Gu(i,e,a)}catch{}Ks.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Ys(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 Gu(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 Ys(`${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 Xu(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 Ys(`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}Pn();var Ka=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Qs(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=pt(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Ka(o.from,80);if(s){a.callback={from:s,status:Ka(o.status,20)??"done"};let i=Ka(o.peer,80);i&&(a.callback.peer=i)}}return a}Pn();va();var Zs={kind:"agentx",id:"agentx",name:"AgentX"},Ja={kind:"person",id:"unknown",name:"Unknown"},Ku=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),Re=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Ju(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Re(o?.id)??(e==="whatsapp"?Re(n?.from):void 0),i=Re(o?.username)??Re(o?.login);return s||i?{id:s,username:i,name:Re(o?.name)}:null}function ti(t){let e=s=>({kind:"person",id:`person:${s}`,name:Dn(t.people,s)}),a=(s,i)=>i||Ku.has(s)?Zs:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Re(n.person)??Hn(t.people,s)?.id;if(i)return e(i);let l=pt(s),c=l?.channel??t.channel;if(Rn(s)==="human")return ei(s?.senderUsername)?a(c,!1):Ja;let d=!!Re(n.senderAgentId)||fa(l?l.sender:s?.sender);return c==="desktop"&&!d?Ja:a(c,d)}let r=Ju(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Bn(t.people,t.channel,r);return o?e(o.id):fa(r.name)?Zs:Ln.has(t.channel)&&!ei(r.username)?Ja:a(t.channel,!1)}function Za(){let t=Ya(process.cwd(),".agentx/intent/ledger.sqlite");if(!Qa(t))return null;try{let e=new Zu(t,{readonly:!0,fileMustExist:!0});return ke(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 ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function em(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Pe)return s}return"workflow"}return t}function oi(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 tm(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 si(t,e,a){return Qn(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 am(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&&!Va(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Va(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:rm(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&&!Va(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",p=ni(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:p}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,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:ni(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 nm={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function rm(t,e){let a=nm[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ni(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Va(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 ii(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}
8995
+ `;import{resolve as Ya,join as Qu}from"path";import{existsSync as Qa,readdirSync as Zu,readFileSync as em}from"fs";import tm from"better-sqlite3";var Xs=String.raw`[\w.-]+(?:/[\w.-]+)+`,Nu=new RegExp(`^(?:chat:)?(${Xs}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Du=new RegExp(`^\\[(?:GitLab|GitHub) (${Xs}) `);function Gs(t){if(!t)return null;let e=t.match(Nu);return e?e[1]:null}function Xa(t){if(!t)return null;let e=t.trimStart().match(Du);return e?e[1]:null}function Qt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Gs(typeof n?.chatId=="string"?n.chatId:null)??Gs(e)??Xa(a)}function Bu(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Zt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Hu=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,zu=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,qu=t=>/^issue/i.test(t)?"issue":"mr";function Fu(t){let e=t.subject.match(Hu)??t.inputPreview.trimStart().match(zu);return e?{kind:qu(e[1]),n:Number(e[2])}:null}function Uu(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 Ks(t){if(!Bu(t.projectId))return[];let e=Fu(t);return e?[e]:Uu(t.inputPreview)}var Wu=6e4,Gu=5*6e4,Xu=40,Js=6,Vs=new Map;function Ys(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 Ks(n)){let s=Zt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Xu)return[...e.values()]}}return[...e.values()]}async function Qs(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Zt(s.project,s.ref),l=Vs.get(i);l&&n-l.at<(s.github?Gu:Wu)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Js)await Promise.all(o.slice(s,s+Js).map(async i=>{let l=Zt(i.project,i.ref),c=null;try{c=i.github?await Ju(i,e,a):await Ku(i,e,a)}catch{}Vs.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Zs(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 Ku(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 Zs(`${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 Ju(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 Zs(`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}Pn();var Ka=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function ei(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=pt(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Ka(o.from,80);if(s){a.callback={from:s,status:Ka(o.status,20)??"done"};let i=Ka(o.peer,80);i&&(a.callback.peer=i)}}return a}Pn();ba();var ti={kind:"agentx",id:"agentx",name:"AgentX"},Ja={kind:"person",id:"unknown",name:"Unknown"},Vu=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),ai=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Re=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Yu(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Re(o?.id)??(e==="whatsapp"?Re(n?.from):void 0),i=Re(o?.username)??Re(o?.login);return s||i?{id:s,username:i,name:Re(o?.name)}:null}function ni(t){let e=s=>({kind:"person",id:`person:${s}`,name:Dn(t.people,s)}),a=(s,i)=>i||Vu.has(s)?ti:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Re(n.person)??Hn(t.people,s)?.id;if(i)return e(i);let l=pt(s),c=l?.channel??t.channel;if(Rn(s)==="human")return ai(s?.senderUsername)?a(c,!1):Ja;let d=!!Re(n.senderAgentId)||fa(l?l.sender:s?.sender);return c==="desktop"&&!d?Ja:a(c,d)}let r=Yu(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=Bn(t.people,t.channel,r);return o?e(o.id):fa(r.name)?ti:Ln.has(t.channel)&&!ai(r.username)?Ja:a(t.channel,!1)}function Za(){let t=Ya(process.cwd(),".agentx/intent/ledger.sqlite");if(!Qa(t))return null;try{let e=new tm(t,{readonly:!0,fileMustExist:!0});return ke(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ri>6e4&&(ri=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ri=0;function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function am(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Pe)return s}return"workflow"}return t}function ii(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 li(t,e,a){return er(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 rm(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&&!Va(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Va(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:sm(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&&!Va(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",p=oi(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:p}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,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:oi(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 om={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function sm(t,e){let a=om[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function oi(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Va(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function ci(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
8996
8996
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
8997
- ${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 om(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 li(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
8997
+ ${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 im(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 di(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
8998
8998
  SELECT id, ts, source, project, subject, intent, raw_json
8999
8999
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
9000
- `).all(r),s=new Map,i=new Map;if(o.length>0){let b=o.map(j=>j.id),A=b.map((j,$)=>`@id${$}`).join(","),R=Object.fromEntries(b.map((j,$)=>[`id${$}`,j])),S=t.prepare(`
9000
+ `).all(r),s=new Map,i=new Map;if(o.length>0){let g=o.map(j=>j.id),A=g.map((j,$)=>`@id${$}`).join(","),R=Object.fromEntries(g.map((j,$)=>[`id${$}`,j])),_=t.prepare(`
9001
9001
  SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
9002
9002
  FROM intent_decisions WHERE event_id IN (${A}) ORDER BY decided_at ASC
9003
- `).all(R);for(let j of S)s.has(j.event_id)||s.set(j.event_id,[]),s.get(j.event_id).push(j);let L=t.prepare(`
9003
+ `).all(R);for(let j of _)s.has(j.event_id)||s.set(j.event_id,[]),s.get(j.event_id).push(j);let L=t.prepare(`
9004
9004
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
9005
9005
  FROM intent_resolutions WHERE decision_event_id IN (${A})
9006
- `).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,c=new Map,d=new Map,p=new Map,m=[],f=e?.business?.projects??[],_=e?.business?.contactMap??[],v=wa(e?.business??{}),E=e?.people??[];for(let b of o){let A=null;try{A=JSON.parse(b.raw_json)}catch{}let R=si(b.source,A,_),S=ii(b.source,A),L=Qs(A),j=b.project??Qt(A,b.subject,S),$=null,O=null;R?($=R.client,O=R.project||`${R.client}/_chat`):j&&($=vt(j,f),O=j);let W=em(b.source,b.intent||"",A),le=Pe[W]||{label:W,color:"#6b7280"};d.has(W)||d.set(W,{id:W,label:le.label,color:le.color});let Q=ti({source:b.source,channel:W,raw:A,people:E,channelLabel:N=>Pe[N]?.label??N}),re="__system",Z,F=am(b.source,b.intent||"",A);if(F){re=F.id,Z=F.kind;let N=R?.displayName||F.name;(!p.has(F.id)||R?.displayName)&&p.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else p.has("__system")||p.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(b.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let Fc=`${b.id}|${N.decided_by}`,ct=i.get(Fc),An=N.decided_at,Cn=ct?.resolved_at??null,ua=Cn===null,Uc=ct?.duration_ms??(ua?n-An:0),Wc=ua?"active":ct?.status==="error"||ct?.status==="fail"?"error":"completed",ee,Ye;if($)ee=$,Ye=O;else{let ma=v.get(N.agent_id);ma?(ee=ma,Ye=`${ma}/_${b.source}`):(ee="unmapped",Ye=`unmapped/_${b.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:oi(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ye),m.push({id:`${b.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:Ye,channelId:W,initiatorId:re,initiatorKind:Z,subject:om(b.subject),intent:b.intent||"",startedAt:An,resolvedAt:Cn,duration:Uc,active:ua,outcome:Wc,tokens:0,inputPreview:S,system:tm(N.agent_id,e),...L,starter:Q})}}let x=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,A)=>b.id.localeCompare(A.id)),g=[],u=new Set;if(e){let b=e.business??{},A=R=>{let S=b.orgChart?.[R]?.role,L=S?b.roles?.[S]?.title:void 0;return typeof L=="string"&&L.trim()?L.trim():void 0};for(let[R,S]of Object.entries(e.agents||{})){let L={id:R,name:S.name||R,tier:S.tier==="claude-code"?"lead":"worker",model:S.model||"",role:S.systemPrompt?S.systemPrompt.split(/[.\n]/)[0].slice(0,60):S.tier||"",title:A(R)};g.push(L),u.add(R)}}for(let b of m)u.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),u.add(b.agentId));g.sort((b,A)=>b.id.localeCompare(A.id));let h=[],w=new Set;for(let[b,A]of Object.entries(Pe))h.push({id:b,label:A.label,color:A.color}),w.add(b);for(let b of d.values())w.has(b.id)||h.push(b);let y=[...p.values()];y.find(b=>b.id==="__system")||y.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:x,agents:g,channels:h,initiators:y,dispatches:m,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function en(t){let e=Za();if(!e)return null;try{return li(e.db,di(),t)}finally{e.close()}}function ci(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:d}of t){l.gitlab??=d.forges?.gitlab,l.github??=d.forges?.github,d.now>s&&(s=d.now),d.windowH>i&&(i=d.windowH);for(let p of d.clients){let m=e.get(p.id);if(!m)e.set(p.id,{...p,projects:[...p.projects]});else{let f=Array.from(new Set([...m.projects,...p.projects])).sort();e.set(p.id,{...m,projects:f})}}for(let p of d.agents)a.has(p.id)||a.set(p.id,p);for(let p of d.channels)n.has(p.id)||n.set(p.id,p);for(let p of d.initiators)r.has(p.id)||r.set(p.id,p);for(let p of d.dispatches){let m=sm(p);if(m.clientId!==p.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:oi(m.clientId),projects:[]}),m.projectId!==p.projectId){let f=e.get(m.clientId);f.projects.includes(m.projectId)||e.set(m.clientId,{...f,projects:[...f.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,d)=>c.id.localeCompare(d.id)),agents:[...a.values()].sort((c,d)=>c.id.localeCompare(d.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,d)=>d.startedAt-c.startedAt)}}function sm(t){if(t.clientId!=="unmapped")return t;let e=Xa(t.inputPreview);if(!e)return t;let a=be?.business?.projects??[];return{...t,projectId:e,clientId:vt(e,a)}}async function ea(t){let e=be?.channels?.gitlab,a=await Vs(Js(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 be=null;function di(){return be&&{...be,people:et(be.people)}}function pi(t){be=t}async function ui(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Za();if(!n)return ve(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=mi(parseInt(r.searchParams.get("hours")||"6",10));ve(e,200,await ea(li(n.db,di(),o)))}catch(r){ve(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var im=5e3;async function tn(t,e,a,n=en){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
9006
+ `).all(R);for(let j of L)i.set(`${j.decision_event_id}|${j.decision_decided_by}`,j)}let l=new Map,c=new Map,d=new Map,p=new Map,m=[],h=e?.business?.projects??[],S=e?.business?.contactMap??[],v=wa(e?.business??{}),E=e?.people??[];for(let g of o){let A=null;try{A=JSON.parse(g.raw_json)}catch{}let R=li(g.source,A,S),_=ci(g.source,A),L=ei(A),j=g.project??Qt(A,g.subject,_),$=null,O=null;R?($=R.client,O=R.project||`${R.client}/_chat`):j&&($=bt(j,h),O=j);let W=am(g.source,g.intent||"",A),le=Pe[W]||{label:W,color:"#6b7280"};d.has(W)||d.set(W,{id:W,label:le.label,color:le.color});let Q=ni({source:g.source,channel:W,raw:A,people:E,channelLabel:N=>Pe[N]?.label??N}),re="__system",Z,F=rm(g.source,g.intent||"",A);if(F){re=F.id,Z=F.kind;let N=R?.displayName||F.name;(!p.has(F.id)||R?.displayName)&&p.set(F.id,{id:F.id,name:N,avatar:J(N),kind:F.kind})}else p.has("__system")||p.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(g.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let Wc=`${g.id}|${N.decided_by}`,ct=i.get(Wc),An=N.decided_at,Cn=ct?.resolved_at??null,ua=Cn===null,Gc=ct?.duration_ms??(ua?n-An:0),Xc=ua?"active":ct?.status==="error"||ct?.status==="fail"?"error":"completed",ee,Ye;if($)ee=$,Ye=O;else{let ma=v.get(N.agent_id);ma?(ee=ma,Ye=`${ma}/_${g.source}`):(ee="unmapped",Ye=`unmapped/_${g.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:ii(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ye),m.push({id:`${g.id}|${N.decided_by}`,agentId:N.agent_id,clientId:ee,projectId:Ye,channelId:W,initiatorId:re,initiatorKind:Z,subject:im(g.subject),intent:g.intent||"",startedAt:An,resolvedAt:Cn,duration:Gc,active:ua,outcome:Xc,tokens:0,inputPreview:_,system:nm(N.agent_id,e),...L,starter:Q})}}let b=[...l.values()].map(g=>({...g,projects:[...c.get(g.id)||[]].sort()})).sort((g,A)=>g.id.localeCompare(A.id)),x=[],u=new Set;if(e){let g=e.business??{},A=R=>{let _=g.orgChart?.[R]?.role,L=_?g.roles?.[_]?.title:void 0;return typeof L=="string"&&L.trim()?L.trim():void 0};for(let[R,_]of Object.entries(e.agents||{})){let L={id:R,name:_.name||R,tier:_.tier==="claude-code"?"lead":"worker",model:_.model||"",role:_.systemPrompt?_.systemPrompt.split(/[.\n]/)[0].slice(0,60):_.tier||"",title:A(R)};x.push(L),u.add(R)}}for(let g of m)u.has(g.agentId)||(x.push({id:g.agentId,name:g.agentId,tier:"worker",model:"",role:""}),u.add(g.agentId));x.sort((g,A)=>g.id.localeCompare(A.id));let f=[],w=new Set;for(let[g,A]of Object.entries(Pe))f.push({id:g,label:A.label,color:A.color}),w.add(g);for(let g of d.values())w.has(g.id)||f.push(g);let y=[...p.values()];y.find(g=>g.id==="__system")||y.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:b,agents:x,channels:f,initiators:y,dispatches:m,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function en(t){let e=Za();if(!e)return null;try{return di(e.db,ui(),t)}finally{e.close()}}function pi(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:d}of t){l.gitlab??=d.forges?.gitlab,l.github??=d.forges?.github,d.now>s&&(s=d.now),d.windowH>i&&(i=d.windowH);for(let p of d.clients){let m=e.get(p.id);if(!m)e.set(p.id,{...p,projects:[...p.projects]});else{let h=Array.from(new Set([...m.projects,...p.projects])).sort();e.set(p.id,{...m,projects:h})}}for(let p of d.agents)a.has(p.id)||a.set(p.id,p);for(let p of d.channels)n.has(p.id)||n.set(p.id,p);for(let p of d.initiators)r.has(p.id)||r.set(p.id,p);for(let p of d.dispatches){let m=lm(p);if(m.clientId!==p.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:ii(m.clientId),projects:[]}),m.projectId!==p.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,d)=>c.id.localeCompare(d.id)),agents:[...a.values()].sort((c,d)=>c.id.localeCompare(d.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,d)=>d.startedAt-c.startedAt)}}function lm(t){if(t.clientId!=="unmapped")return t;let e=Xa(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:bt(e,a)}}async function ea(t){let e=ve?.channels?.gitlab,a=await Qs(Ys(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ve=null;function ui(){return ve&&{...ve,people:et(ve.people)}}function mi(t){ve=t}async function fi(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Za();if(!n)return be(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=hi(parseInt(r.searchParams.get("hours")||"6",10));be(e,200,await ea(di(n.db,ui(),o)))}catch(r){be(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var cm=5e3;async function tn(t,e,a,n=en){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
9007
9007
 
9008
- `);let r=new URL(t.url||"/","http://_"),o=mi(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
9008
+ `);let r=new URL(t.url||"/","http://_"),o=hi(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
9009
9009
 
9010
9010
  `)}catch{i()}},25e3);try{for(;!s;){try{let d=await n(o),p=d&&await ea(d);if(s)break;p?(e.write(`event: snapshot
9011
9011
  `),e.write(`data: ${JSON.stringify(p)}
@@ -9016,7 +9016,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
9016
9016
  `)}catch(d){e.write(`event: error
9017
9017
  data: ${JSON.stringify({error:d?.message??String(d)})}
9018
9018
 
9019
- `)}let c=Date.now();for(;!s&&Date.now()-c<im;)await new Promise(d=>setTimeout(d,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function mi(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function lm(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Ya(process.cwd(),".agentx/task-history",t,n);if(!Qa(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Ya(process.cwd(),".agentx/task-history",t,o);return Qa(s)?ri(s,e,a):null}return ri(r,e,a)}function ri(t,e,a){let n=null,r=1/0;for(let o of Yu(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Qu(Vu(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let d=Date.parse(i);if(!Number.isFinite(d))continue;l=d}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function fi(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 ve(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Za();if(!l)return ve(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 ve(e,404,{error:"event not found"}),!0;let d=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(!d)return ve(e,404,{error:"decision not found"}),!0;let p=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let f=ii(c.source,m),_=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||f,v=null,E=null;if(d.agent_id){let y=lm(d.agent_id,d.decided_at);if(y){typeof y.responseText=="string"&&(v=y.responseText);let T=y.transcript;Array.isArray(T)&&(E=T.length)}}let x=be?.business?.projects??[],g=be?.business?.contactMap??[],u=wa(be?.business??{}),h={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},w=si(c.source,m,g);if(w)h={client:w.client,project:w.project||`${w.client}/_chat`,via:`contactMap (channel=${w.channel??"*"}${w.username?` username=${w.username}`:""}${w.chatId?` chatId=${w.chatId}`:""})`};else if(c.project||Qt(m,c.subject,f)){let y=c.project||Qt(m,c.subject,f);h={client:vt(y,x),project:y,via:c.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(d.agent_id){let y=u.get(d.agent_id);y&&(h={client:y,project:`${y}/_${c.source}`,via:`orgChart fallback (agent ${d.agent_id} reports up to a PM whose project belongs to ${y})`})}ve(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:d.decided_by,agentId:d.agent_id,outcome:d.outcome,reason:d.reason,startedAt:d.decided_at,resolvedAt:p?.resolved_at??null,durationMs:p?.duration_ms??null,input:_,response:v,transcriptLen:E,resolutionStatus:p?.status??null,resultSummary:p?.result_summary??null,attribution:h})}catch(c){ve(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as um,readFileSync as mm}from"fs";import{resolve as gi}from"path";ft();function hi(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=cm.replace(/__AGENT_ID__/g,B(e));return I({title:`AgentX \xB7 ${B(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${B(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:dm,headExtras:'<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">',scripts:`${n}${a}<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script><script>${pm}</script>`})}var cm=`
9019
+ `)}let c=Date.now();for(;!s&&Date.now()-c<cm;)await new Promise(d=>setTimeout(d,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function hi(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function dm(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Ya(process.cwd(),".agentx/task-history",t,n);if(!Qa(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Ya(process.cwd(),".agentx/task-history",t,o);return Qa(s)?si(s,e,a):null}return si(r,e,a)}function si(t,e,a){let n=null,r=1/0;for(let o of Zu(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(em(Qu(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let d=Date.parse(i);if(!Number.isFinite(d))continue;l=d}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function gi(t,e,a){let n=a.match(/^\/api\/admin\/activity-graph\/dispatch\/([^/?]+)(?:\?.*)?$/);if(!n)return!1;let r=decodeURIComponent(n[1]),o=r.indexOf("|");if(o<0)return be(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Za();if(!l)return be(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 be(e,404,{error:"event not found"}),!0;let d=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(!d)return be(e,404,{error:"decision not found"}),!0;let p=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=ci(c.source,m),S=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,v=null,E=null;if(d.agent_id){let y=dm(d.agent_id,d.decided_at);if(y){typeof y.responseText=="string"&&(v=y.responseText);let T=y.transcript;Array.isArray(T)&&(E=T.length)}}let b=ve?.business?.projects??[],x=ve?.business?.contactMap??[],u=wa(ve?.business??{}),f={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},w=li(c.source,m,x);if(w)f={client:w.client,project:w.project||`${w.client}/_chat`,via:`contactMap (channel=${w.channel??"*"}${w.username?` username=${w.username}`:""}${w.chatId?` chatId=${w.chatId}`:""})`};else if(c.project||Qt(m,c.subject,h)){let y=c.project||Qt(m,c.subject,h);f={client:bt(y,b),project:y,via:c.project?`project namespace prefix (${y})`:`forge path in chat id / message (${y})`}}else if(d.agent_id){let y=u.get(d.agent_id);y&&(f={client:y,project:`${y}/_${c.source}`,via:`orgChart fallback (agent ${d.agent_id} reports up to a PM whose project belongs to ${y})`})}be(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:d.decided_by,agentId:d.agent_id,outcome:d.outcome,reason:d.reason,startedAt:d.decided_at,resolvedAt:p?.resolved_at??null,durationMs:p?.duration_ms??null,input:S,response:v,transcriptLen:E,resolutionStatus:p?.status??null,resultSummary:p?.result_summary??null,attribution:f})}catch(c){be(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as fm,readFileSync as hm}from"fs";import{resolve as bi}from"path";ft();function xi(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=pm.replace(/__AGENT_ID__/g,B(e));return I({title:`AgentX \xB7 ${B(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${B(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:um,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>${mm}</script>`})}var pm=`
9020
9020
  <!-- Breadcrumb -->
9021
9021
  <div class="ax-crumb">
9022
9022
  <a href="/admin">Settings</a>
@@ -9605,7 +9605,7 @@ data: ${JSON.stringify({error:d?.message??String(d)})}
9605
9605
  </div>
9606
9606
  </div>
9607
9607
  </div>
9608
- `,dm=`
9608
+ `,um=`
9609
9609
  /* Agent-specific layout + legacy styles for bits the migration left in
9610
9610
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
9611
9611
  * primitives live in components.css.ts. */
@@ -9724,7 +9724,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
9724
9724
 
9725
9725
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
9726
9726
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
9727
- `,pm=`
9727
+ `,mm=`
9728
9728
  const $ = (id) => document.getElementById(id);
9729
9729
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
9730
9730
 
@@ -10580,15 +10580,15 @@ document.addEventListener('keydown', (e) => {
10580
10580
  /* ===== Boot ===== */
10581
10581
  initOptsToggles();
10582
10582
  loadAgent();
10583
- `;function xi(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hi({agentId:a,peers:n,localToken:r}))}async function vi(t,e,a){try{let n=t.method==="GET"?void 0:await jm(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){ta(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,p={"GET ":()=>nt(i),"PATCH ":()=>fm(i,n),"PATCH capability":()=>xm(i,n),"POST mcp":()=>hm(i,n),"DELETE mcp":()=>gm(i,n),"GET identity":()=>vm(i),"GET identity/file":()=>bm(i,String(o.path||"")),"PUT identity/file":()=>ym(i,n),"GET skills":()=>wm(i),"POST skills":()=>km(i,n),"DELETE skills":()=>_m(i,n),"GET skills/tree":()=>Sm(i,String(o.slug||"")),"GET skills/file":()=>Em(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Tm(i,n),"GET skills/deps":()=>Am(i,String(o.slug||"")),"POST skills/install":()=>Cm(i,n,t),"POST skills/deps":()=>Im(i,n,t),"GET channels":()=>Mm(i),"GET activity":()=>Lm(i,t),"GET handovers":()=>Rm(i),"POST handovers":()=>Pm(i,n),"DELETE handovers":()=>$m(n)}[c];if(!p){ta(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await p();ta(e,200,m)}catch(n){ta(e,400,{error:n?.message||"agent op failed"})}}function bi(){let t=gi(process.cwd(),"agentx.json");return um(t)?JSON.parse(mm(t,"utf-8")):null}function V(t){let e=bi();if(!e)throw new Error("agentx.json not found");let a=e.agents?.[t];if(!a)throw new Error(`Agent "${t}" not found`);return{def:a,cfg:e}}function nt(t){let{def:e,cfg:a}=V(t),n=e.workspace?He(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function fm(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function hm(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:nt(t)}}function gm(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:nt(t)}}function xm(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function vm(t){let{def:e}=V(t);return He(e.workspace)}function bm(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Ct(a.workspace,e)}function ym(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return It(n.workspace,a,String(e?.content??""))}function wm(t){let{def:e}=V(t),a=He(e.workspace);return{skills:a.skills,workspace:a.workspace}}function km(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Mt(n.workspace,a,{title:e?.title,content:e?.content})}function _m(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Lt(n.workspace,a)}function Sm(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Cr(a.workspace,e),r=Rt(a.workspace,e);return{slug:e,tree:n,deps:r}}function Em(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Ir(n.workspace,e,a)}function Tm(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 Mr(r.workspace,a,n,String(e?.content??""))}function Am(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Rt(a.workspace,e)}async function Cm(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=yi(e?.worker),{def:o}=V(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
10584
- `);return wi(a,r,s,`install-${n}:${Date.now()}`)}async function Im(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=yi(e?.worker),{def:o}=V(t),s=Rt(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=gi(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(`
10585
- `);return wi(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function yi(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 wi(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(),d;try{d=JSON.parse(c)}catch{d={content:c}}if(!l.ok)throw new Error(d?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:d?.taskId,content:d?.content,duration:d?.duration,error:d?.error}}function Mm(t){let e=bi(),a=[],n=e?.channels?.telegram?.accounts||{};for(let[o,s]of Object.entries(n))s?.agentBinding===t&&a.push({channel:"telegram",account:o,detail:s?.botUsername||o});e?.channels?.slack?.agentBinding===t&&a.push({channel:"slack",detail:"bound"}),e?.channels?.discord?.agentBinding===t&&a.push({channel:"discord",detail:"bound"});let r=e?.channels?.gitlab?.agentMappings||[];for(let o of r)o?.agentId===t&&a.push({channel:"gitlab",detail:(o?.gitlabUsernames||[]).join(", ")||"mapped"});return{bindings:a}}async function Lm(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 an(){return new qn}function Rm(t){let e=an(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Pm(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=an().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 $m(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:an().remove(e,a,n)?"Released":"No active handover for that chat"}}function ta(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function jm(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var $e={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var ki=[{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 nn(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify($e)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10583
+ `;function vi(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xi({agentId:a,peers:n,localToken:r}))}async function yi(t,e,a){try{let n=t.method==="GET"?void 0:await Nm(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){ta(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,p={"GET ":()=>nt(i),"PATCH ":()=>gm(i,n),"PATCH capability":()=>vm(i,n),"POST mcp":()=>xm(i,n),"DELETE mcp":()=>bm(i,n),"GET identity":()=>ym(i),"GET identity/file":()=>wm(i,String(o.path||"")),"PUT identity/file":()=>km(i,n),"GET skills":()=>_m(i),"POST skills":()=>Sm(i,n),"DELETE skills":()=>Em(i,n),"GET skills/tree":()=>Tm(i,String(o.slug||"")),"GET skills/file":()=>Am(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Cm(i,n),"GET skills/deps":()=>Im(i,String(o.slug||"")),"POST skills/install":()=>Mm(i,n,t),"POST skills/deps":()=>Lm(i,n,t),"GET channels":()=>Rm(i),"GET activity":()=>Pm(i,t),"GET handovers":()=>$m(i),"POST handovers":()=>jm(i,n),"DELETE handovers":()=>Om(n)}[c];if(!p){ta(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await p();ta(e,200,m)}catch(n){ta(e,400,{error:n?.message||"agent op failed"})}}function wi(){let t=bi(process.cwd(),"agentx.json");return fm(t)?JSON.parse(hm(t,"utf-8")):null}function V(t){let e=wi();if(!e)throw new Error("agentx.json not found");let a=e.agents?.[t];if(!a)throw new Error(`Agent "${t}" not found`);return{def:a,cfg:e}}function nt(t){let{def:e,cfg:a}=V(t),n=e.workspace?He(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function gm(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function xm(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=C(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:nt(t)}}function bm(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:nt(t)}}function vm(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=C(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:nt(t)}}function ym(t){let{def:e}=V(t);return He(e.workspace)}function wm(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return Ct(a.workspace,e)}function km(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return It(n.workspace,a,String(e?.content??""))}function _m(t){let{def:e}=V(t),a=He(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Sm(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Mt(n.workspace,a,{title:e?.title,content:e?.content})}function Em(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Lt(n.workspace,a)}function Tm(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Mr(a.workspace,e),r=Rt(a.workspace,e);return{slug:e,tree:n,deps:r}}function Am(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return Lr(n.workspace,e,a)}function Cm(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 Rr(r.workspace,a,n,String(e?.content??""))}function Im(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Rt(a.workspace,e)}async function Mm(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=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
10584
+ `);return _i(a,r,s,`install-${n}:${Date.now()}`)}async function Lm(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=Rt(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=bi(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(`
10585
+ `);return _i(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 _i(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(),d;try{d=JSON.parse(c)}catch{d={content:c}}if(!l.ok)throw new Error(d?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:d?.taskId,content:d?.content,duration:d?.duration,error:d?.error}}function Rm(t){let e=wi(),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 Pm(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 an(){return new qn}function $m(t){let e=an(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function jm(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=an().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 Om(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:an().remove(e,a,n)?"Released":"No active handover for that chat"}}function ta(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Nm(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var $e={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var Si=[{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 nn(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify($e)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10586
10586
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
10587
10587
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
10588
10588
  <section id="statstrip" class="ax-statstrip"></section>
10589
10589
  <main id="grid" class="ax-live__body"></main>
10590
10590
  </div>
10591
- `;return I({title:`${$e.brand} \xB7 ${$e.subtitle}`,activeTab:"live",subtitle:$e.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Om,scripts:e+`<script>${Nm}</script>`,headExtras:`<script>
10591
+ `;return I({title:`${$e.brand} \xB7 ${$e.subtitle}`,activeTab:"live",subtitle:$e.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Dm,scripts:e+`<script>${Bm}</script>`,headExtras:`<script>
10592
10592
  // rightExtras for the topbar are injected at runtime \u2014 they reference
10593
10593
  // IDs (#ts, #conn-dot) that the script below addresses directly.
10594
10594
  document.addEventListener('DOMContentLoaded', () => {
@@ -10599,7 +10599,7 @@ loadAgent();
10599
10599
  extras.innerHTML = ${JSON.stringify(a)};
10600
10600
  right.insertBefore(extras, right.firstChild);
10601
10601
  });
10602
- </script>`})}var Om=`
10602
+ </script>`})}var Dm=`
10603
10603
  /* --- Page frame --- */
10604
10604
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
10605
10605
 
@@ -10806,7 +10806,7 @@ loadAgent();
10806
10806
  border-top-color: var(--ax-accent); border-radius: 50%;
10807
10807
  animation: ax-spin 800ms linear infinite; display: inline-block;
10808
10808
  }
10809
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,Nm=`
10809
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,Bm=`
10810
10810
  'use strict';
10811
10811
 
10812
10812
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -11377,7 +11377,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11377
11377
  });
11378
11378
  }
11379
11379
 
11380
- `;var _i=`
11380
+ `;var Ei=`
11381
11381
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
11382
11382
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
11383
11383
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -11551,7 +11551,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11551
11551
  .mx-summary{max-width:56vw}
11552
11552
  }
11553
11553
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
11554
- `;var Si=`<script>
11554
+ `;var Ti=`<script>
11555
11555
  window.MX=(function(){
11556
11556
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
11557
11557
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -11660,7 +11660,7 @@ window.MX=(function(){
11660
11660
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
11661
11661
  setHealth:setHealth,get:get};
11662
11662
  })();
11663
- </script>`;var Ei=`<script>
11663
+ </script>`;var Ai=`<script>
11664
11664
  window.MXD=(function(){
11665
11665
  function el(id){return document.getElementById(id)}
11666
11666
  function tz(){return -new Date().getTimezoneOffset()}
@@ -11874,7 +11874,7 @@ window.MXD=(function(){
11874
11874
 
11875
11875
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
11876
11876
  })();
11877
- </script>`;var Ti=`<script>
11877
+ </script>`;var Ci=`<script>
11878
11878
  (function(){
11879
11879
  var LANES=[
11880
11880
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -12190,7 +12190,7 @@ window.MXD=(function(){
12190
12190
  window.addEventListener('scroll',hideTip,{passive:true});
12191
12191
  load();
12192
12192
  })();
12193
- </script>`;var Ai=`<script>
12193
+ </script>`;var Ii=`<script>
12194
12194
  (function(){
12195
12195
  var showAll=document.getElementById('mx-show-all'),expanded=false;
12196
12196
  var esc=MX.esc;
@@ -12368,7 +12368,7 @@ window.MXD=(function(){
12368
12368
  }
12369
12369
  load();setInterval(load,5000);
12370
12370
  })();
12371
- </script>`;var Ci=`
12371
+ </script>`;var Mi=`
12372
12372
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
12373
12373
  .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}
12374
12374
  .mx-rt-wrap > .mx-empty{border:0}
@@ -12409,7 +12409,7 @@ window.MXD=(function(){
12409
12409
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
12410
12410
  .mx-rt-name{max-width:100%}
12411
12411
  }
12412
- `,Ii=`<script>
12412
+ `,Li=`<script>
12413
12413
  (function(){
12414
12414
  var root=document.getElementById('mx-routines');
12415
12415
  var bar=document.getElementById('mx-rt-filter');
@@ -12536,7 +12536,7 @@ window.MXD=(function(){
12536
12536
  syncBar();
12537
12537
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
12538
12538
  })();
12539
- </script>`;var Mi=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Li=`<script>
12539
+ </script>`;var Ri=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Pi=`<script>
12540
12540
  (function(){
12541
12541
  var root=document.getElementById('mx-feed');
12542
12542
  if(!root)return;
@@ -12611,12 +12611,12 @@ window.MXD=(function(){
12611
12611
  }
12612
12612
  load();setInterval(load,5000);
12613
12613
  })();
12614
- </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 Dm=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Bm=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Hm=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Ri(t){let e=de({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Pt([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
12614
+ </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 Hm=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],zm=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],qm=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function $i(t){let e=de({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Pt([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
12615
12615
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
12616
- ${Bm.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("")}
12616
+ ${zm.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("")}
12617
12617
  </div>
12618
12618
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
12619
- ${Hm.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12619
+ ${qm.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12620
12620
  </div>
12621
12621
  </div>
12622
12622
  <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">
@@ -12669,7 +12669,7 @@ window.MXD=(function(){
12669
12669
  <section class="mx-section" aria-labelledby="mx-routines-title">
12670
12670
  ${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>')}
12671
12671
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
12672
- ${Dm.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12672
+ ${Hm.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12673
12673
  </div>
12674
12674
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
12675
12675
  </section>
@@ -12677,7 +12677,7 @@ window.MXD=(function(){
12677
12677
  <section class="mx-section" aria-labelledby="mx-feed-title">
12678
12678
  ${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>')}
12679
12679
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
12680
- ${Mi.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12680
+ ${Ri.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12681
12681
  </div>
12682
12682
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
12683
12683
  </section>
@@ -12710,7 +12710,7 @@ window.MXD=(function(){
12710
12710
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
12711
12711
  </header>
12712
12712
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
12713
- </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:_i+Ci,scripts:Si+zm+Ei+Ti+Ii+Ai+Li})}var zm=`<script>
12713
+ </aside>`;return I({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ei+Mi,scripts:Ti+Fm+Ai+Ci+Li+Ii+Pi})}var Fm=`<script>
12714
12714
  (function(){
12715
12715
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
12716
12716
  var range=document.getElementById('mx-range');
@@ -12738,10 +12738,10 @@ window.MXD=(function(){
12738
12738
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
12739
12739
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
12740
12740
  })();
12741
- </script>`;function Pi(t){let e=de({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."})+`
12741
+ </script>`;function ji(t){let e=de({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."})+`
12742
12742
  <div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
12743
12743
  <ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
12744
- <p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent &lt;id&gt;</code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return I({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:qm,scripts:`<script>${Fm}</script>`})}var qm=`
12744
+ <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:Um,scripts:`<script>${Wm}</script>`})}var Um=`
12745
12745
  .gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
12746
12746
  .gm-empty { color: var(--ax-text-2); }
12747
12747
  .gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
@@ -12759,7 +12759,7 @@ window.MXD=(function(){
12759
12759
  .gm-msg { min-height: 1.4em; margin: 8px 0 0; }
12760
12760
  .gm-msg.is-bad { color: var(--ax-red-ink); }
12761
12761
  .gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
12762
- `,Fm=`
12762
+ `,Wm=`
12763
12763
  (function () {
12764
12764
  var list = document.getElementById('gm-list');
12765
12765
  var msg = document.getElementById('gm-msg');
@@ -12806,7 +12806,7 @@ window.MXD=(function(){
12806
12806
  load();
12807
12807
  setInterval(load, 30000);
12808
12808
  })();
12809
- `;async function $i(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 Um(s,e.days)}function Um(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,d=0,p=0,m=0,f=0,_=0;for(let{node:E,data:x}of t)if(x){a.runs+=x.totals.runs,a.errors+=x.totals.errors,a.hours+=x.totals.hours,a.agents+=x.totals.agents,a.threads+=x.totals.threads;for(let g of x.days){let u=n.get(g.day)||{day:g.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])u[h][0]+=g[h]?.[0]||0,u[h][1]+=g[h]?.[1]||0;n.set(g.day,u)}for(let g of x.origins){let u=r.get(g.channel)||{channel:g.channel,runs:0,errors:0,hours:0};u.runs+=g.runs,u.errors+=g.errors,u.hours+=g.hours,r.set(g.channel,u)}for(let g of x.causes){let u=o.get(g.cause)||{cause:g.cause,count:0,agents:[],example:""};u.count+=g.count;for(let h of g.agents)u.agents.includes(h)||u.agents.push(h);u.example||(u.example=g.example),o.set(g.cause,u)}for(let g of x.rotations.byReason)s.set(g.reason,(s.get(g.reason)||0)+g.count);c+=x.rotations.total,d+=x.rotations.tokenSum||0,p+=x.rotations.tokenSamples||0,m=Math.max(m,x.rotations.maxTokens),f+=x.retention.traces,_+=x.retention.tracesWithSteps;for(let g of x.jobs)i.push({...g,node:E.name,nodeUrl:E.url});for(let g of x.threads)l.push({...g,node:E.name,nodeUrl:E.url})}let v=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:v.length?Math.min(...v):Date.now()-e*864e5,nodes:t.map(E=>({name:E.node.name,url:E.node.url,ok:!!E.data,error:E.error,runs:E.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((E,x)=>E.day.localeCompare(x.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,x)=>x.runs-E.runs),causes:[...o.values()].sort((E,x)=>x.count-E.count),jobs:i.sort((E,x)=>x.hours-E.hours),threads:l.sort((E,x)=>x.lastAt-x.firstAt-(E.lastAt-E.firstAt)||x.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,x])=>({reason:E,count:x})).sort((E,x)=>x.count-E.count),tokenSum:d,tokenSamples:p,maxTokens:m},retention:{traces:f,tracesWithSteps:_}}}async function ji(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 Oi(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 Wm(s,e.day)}function Wm(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 Ni(t={}){let e=`
12809
+ `;async function Oi(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 Gm(s,e.days)}function Gm(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,d=0,p=0,m=0,h=0,S=0;for(let{node:E,data:b}of t)if(b){a.runs+=b.totals.runs,a.errors+=b.totals.errors,a.hours+=b.totals.hours,a.agents+=b.totals.agents,a.threads+=b.totals.threads;for(let x of b.days){let u=n.get(x.day)||{day:x.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let f of["cron","workflow","direct"])u[f][0]+=x[f]?.[0]||0,u[f][1]+=x[f]?.[1]||0;n.set(x.day,u)}for(let x of b.origins){let u=r.get(x.channel)||{channel:x.channel,runs:0,errors:0,hours:0};u.runs+=x.runs,u.errors+=x.errors,u.hours+=x.hours,r.set(x.channel,u)}for(let x of b.causes){let u=o.get(x.cause)||{cause:x.cause,count:0,agents:[],example:""};u.count+=x.count;for(let f of x.agents)u.agents.includes(f)||u.agents.push(f);u.example||(u.example=x.example),o.set(x.cause,u)}for(let x of b.rotations.byReason)s.set(x.reason,(s.get(x.reason)||0)+x.count);c+=b.rotations.total,d+=b.rotations.tokenSum||0,p+=b.rotations.tokenSamples||0,m=Math.max(m,b.rotations.maxTokens),h+=b.retention.traces,S+=b.retention.tracesWithSteps;for(let x of b.jobs)i.push({...x,node:E.name,nodeUrl:E.url});for(let x of b.threads)l.push({...x,node:E.name,nodeUrl:E.url})}let v=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:v.length?Math.min(...v):Date.now()-e*864e5,nodes:t.map(E=>({name:E.node.name,url:E.node.url,ok:!!E.data,error:E.error,runs:E.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((E,b)=>E.day.localeCompare(b.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,b)=>b.runs-E.runs),causes:[...o.values()].sort((E,b)=>b.count-E.count),jobs:i.sort((E,b)=>b.hours-E.hours),threads:l.sort((E,b)=>b.lastAt-b.firstAt-(E.lastAt-E.firstAt)||b.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,b])=>({reason:E,count:b})).sort((E,b)=>b.count-E.count),tokenSum:d,tokenSamples:p,maxTokens:m},retention:{traces:h,tracesWithSteps:S}}}async function Ni(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 Di(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 Xm(s,e.day)}function Xm(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 Bi(t={}){let e=`
12810
12810
  <select id="boardPicker" title="Switch board"></select>
12811
12811
  <div class="search">
12812
12812
  <span class="icon">\u2315</span>
@@ -12907,7 +12907,7 @@ window.MXD=(function(){
12907
12907
  </footer>
12908
12908
  </div>
12909
12909
  </div>
12910
- <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:Gm,scripts:`<script>${Xm}</script>`,headExtras:`<script>
12910
+ <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:Km,scripts:`<script>${Jm}</script>`,headExtras:`<script>
12911
12911
  // The boards page has its own connection dot + wants body height:100%
12912
12912
  // for the full-viewport kanban layout. Inject the dot into the topbar
12913
12913
  // and override body height at runtime so the shared shell doesn't
@@ -12923,7 +12923,7 @@ window.MXD=(function(){
12923
12923
  right.insertBefore(dot, right.firstChild);
12924
12924
  }
12925
12925
  });
12926
- </script>`})}var Gm=`
12926
+ </script>`})}var Km=`
12927
12927
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
12928
12928
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
12929
12929
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -13176,7 +13176,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
13176
13176
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
13177
13177
  .draft-box .draft-row .hint.err { color: var(--red); }
13178
13178
  .draft-box .draft-row .hint.ok { color: var(--green); }
13179
- `,Xm=`
13179
+ `,Jm=`
13180
13180
  'use strict';
13181
13181
  const state = {
13182
13182
  boards: [], current: null, items: {},
@@ -14229,9 +14229,9 @@ function appendEvents(events) {
14229
14229
  }
14230
14230
 
14231
14231
  loadBoards().catch(e => toast('Init failed: ' + e.message));
14232
- `;function Di(t={}){let a=`<h1>Plain-English glossary</h1>
14232
+ `;function Hi(t={}){let a=`<h1>Plain-English glossary</h1>
14233
14233
  <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>
14234
- ${ki.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${B(n.alias)}</span>`:"";return`<article class="term"><h3>${B(n.term)}${r}</h3><p>${B(n.definition)}</p></article>`}).join("")}`;return I({title:`${$e.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Km})}var Km=`
14234
+ ${Si.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${B(n.alias)}</span>`:"";return`<article class="term"><h3>${B(n.term)}${r}</h3><p>${B(n.definition)}</p></article>`}).join("")}`;return I({title:`${$e.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Vm})}var Vm=`
14235
14235
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
14236
14236
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
14237
14237
  .lead {
@@ -14261,7 +14261,7 @@ article.term .alias {
14261
14261
  }
14262
14262
  article.term p {
14263
14263
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
14264
- }`;function Bi(t={}){let e=`<div class="ax-wf__root">
14264
+ }`;function zi(t={}){let e=`<div class="ax-wf__root">
14265
14265
  <aside class="ax-wf__list">
14266
14266
  <header>
14267
14267
  <h2>Workflows</h2>
@@ -14276,6 +14276,14 @@ article.term p {
14276
14276
  <option value="">All projects</option>
14277
14277
  </select>
14278
14278
  </div>
14279
+ <section class="ax-wf__followups" aria-labelledby="wf-followups-title">
14280
+ <header>
14281
+ <h3 id="wf-followups-title">Follow-ups</h3>
14282
+ <span class="hint" id="wf-followups-note"></span>
14283
+ </header>
14284
+ <p class="hint">Workflows agents started for your requests, grouped by who or what they concern. Open a group to see which step each one is on and what it waits for.</p>
14285
+ <div id="wf-followups-body" aria-live="polite"><span class="hint">Loading&hellip;</span></div>
14286
+ </section>
14279
14287
  <ul id="wf-list" class="ax-wf__cards" aria-live="polite"></ul>
14280
14288
  <div id="wf-empty" class="ax-wf__empty" hidden>
14281
14289
  <p><b>No workflows yet.</b></p>
@@ -14338,7 +14346,7 @@ article.term p {
14338
14346
  </aside>
14339
14347
  </div>
14340
14348
 
14341
- <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:Jm,scripts:`<script>${q({workflowHealth:Yn})}${Vm}</script>`})}var Jm=`
14349
+ <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:Ym,scripts:`<script>${q({workflowHealth:Zn})}${Qm}</script>`})}var Ym=`
14342
14350
  .ax-wf__root {
14343
14351
  display: grid;
14344
14352
  grid-template-columns: 340px 1fr;
@@ -14393,6 +14401,28 @@ article.term p {
14393
14401
  .ax-wf__state--quiet,
14394
14402
  .ax-wf__state--never { color: var(--ax-text-2); }
14395
14403
 
14404
+ .ax-wf__followups {
14405
+ border-bottom: var(--ax-border-w) solid var(--ax-border);
14406
+ padding: 12px 16px; display: flex; flex-direction: column; gap: 6px;
14407
+ }
14408
+ .ax-wf__followups header { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
14409
+ .ax-wf__followups h3 { font-size: 13px; font-weight: 600; margin: 0; }
14410
+ .ax-wf__followups details { border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-sm); }
14411
+ .ax-wf__followups summary {
14412
+ cursor: pointer; padding: 6px 8px; font-size: 12px; font-weight: 600;
14413
+ display: flex; justify-content: space-between; gap: 8px;
14414
+ }
14415
+ .ax-wf__followups summary:focus-visible, .ax-wf__fu-row:focus-visible { outline: 2px solid var(--ax-accent); outline-offset: 2px; }
14416
+ .ax-wf__followups ul { list-style: none; margin: 0; padding: 0 4px 4px; display: flex; flex-direction: column; gap: 2px; }
14417
+ .ax-wf__fu-row {
14418
+ width: 100%; text-align: left; background: none; border: 0; border-radius: 4px;
14419
+ padding: 6px; color: inherit; font: inherit; font-size: 12px; cursor: pointer;
14420
+ display: flex; flex-direction: column; gap: 2px; min-width: 0;
14421
+ }
14422
+ .ax-wf__fu-row:hover { background: var(--ax-surface-2); }
14423
+ .ax-wf__fu-row b { overflow-wrap: anywhere; }
14424
+ .ax-wf__fu-row .hint { overflow-wrap: anywhere; }
14425
+ .ax-wf__fu-row.is-blocked b::before { content: "\u26A0 "; color: var(--ax-err); }
14396
14426
  .ax-wf__n8n {
14397
14427
  border-top: var(--ax-border-w) solid var(--ax-border);
14398
14428
  padding: 14px 16px; display: flex; flex-direction: column; gap: 8px;
@@ -14722,7 +14752,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14722
14752
  font-size: 12px; z-index: 50;
14723
14753
  }
14724
14754
  .hint { color: var(--ax-muted); font-size: 11px; }
14725
- `,Vm=`
14755
+ `,Qm=`
14726
14756
  (() => {
14727
14757
  const $ = (sel) => document.querySelector(sel)
14728
14758
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -15422,6 +15452,42 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15422
15452
  } catch (e) {
15423
15453
  toast("Failed to load workflows: " + e.message)
15424
15454
  }
15455
+ loadFollowUps()
15456
+ }
15457
+
15458
+ // Follow-ups (#788): running workflows grouped by tag. A group is a
15459
+ // <details>, closed by default past the first three, so a long list
15460
+ // stays one line per tag until opened.
15461
+ async function loadFollowUps() {
15462
+ const body = $("#wf-followups-body")
15463
+ const note = $("#wf-followups-note")
15464
+ if (!body) return
15465
+ let data
15466
+ try {
15467
+ data = await fetchJSON("/api/workflows/follow-ups")
15468
+ } catch (e) {
15469
+ body.innerHTML = '<span class="hint">Could not load follow-ups: ' + esc(e.message) + '</span>'
15470
+ return
15471
+ }
15472
+ const groups = data.groups || []
15473
+ const runs = new Set()
15474
+ for (const g of groups) for (const r of g.rows) runs.add(r.runId)
15475
+ note.textContent = runs.size ? runs.size + " running" : ""
15476
+ if (data.unreachable && data.unreachable.length) note.textContent += (runs.size ? " \xB7 " : "") + data.unreachable.length + " node(s) not reachable"
15477
+ if (!groups.length) {
15478
+ body.innerHTML = '<span class="hint">Nothing is being followed right now.</span>'
15479
+ return
15480
+ }
15481
+ body.innerHTML = groups.map((g, i) => {
15482
+ const blocked = g.rows.some((r) => r.blocked)
15483
+ return '<details' + (i < 3 || blocked ? ' open' : '') + '><summary><span>' + esc(g.tag) + '</span><span class="hint">' + g.rows.length + (blocked ? ' \xB7 blocked' : '') + '</span></summary><ul>' +
15484
+ g.rows.map((r) => '<li><button type="button" class="ax-wf__fu-row' + (r.blocked ? ' is-blocked' : '') + '" data-runid="' + esc(r.runId) + '">' +
15485
+ '<b>' + esc(r.title) + '</b>' +
15486
+ '<span class="hint">Step ' + esc(r.step) + ' \xB7 waiting on ' + esc(r.waitingOn) + '</span>' +
15487
+ '<span class="hint">since ' + esc(relTime(r.since)) + (r.startedBy ? ' \xB7 started by ' + esc(r.startedBy) : '') + '</span>' +
15488
+ '</button></li>').join("") + '</ul></details>'
15489
+ }).join("")
15490
+ body.querySelectorAll("[data-runid]").forEach((b) => b.addEventListener("click", () => openRun(b.getAttribute("data-runid"))))
15425
15491
  }
15426
15492
 
15427
15493
  function toast(msg) {
@@ -15511,7 +15577,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15511
15577
  setInterval(refresh, 15000)
15512
15578
  })
15513
15579
  })();
15514
- `;function Hi(t={}){let e=`<div class="ax-proc__root">
15580
+ `;function qi(t={}){let e=`<div class="ax-proc__root">
15515
15581
  <header class="ax-proc__header">
15516
15582
  <h1>Procedures</h1>
15517
15583
  <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>
@@ -15555,7 +15621,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15555
15621
  <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>
15556
15622
  <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>
15557
15623
  </section>
15558
- </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ym,scripts:`<script>${Qm}</script>`})}var Ym=`
15624
+ </div>`;return I({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Zm,scripts:`<script>${ef}</script>`})}var Zm=`
15559
15625
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
15560
15626
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
15561
15627
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -15581,7 +15647,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15581
15647
  .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); }
15582
15648
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
15583
15649
  .ax-proc__link:hover { text-decoration: underline; }
15584
- `,Qm=`
15650
+ `,ef=`
15585
15651
  (function(){
15586
15652
  function $(sel){ return document.querySelector(sel) }
15587
15653
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -15681,7 +15747,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15681
15747
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
15682
15748
  else bootAll()
15683
15749
  })();
15684
- `;function zi(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
15750
+ `;function Fi(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
15685
15751
  data-task-id="${B(t.taskId)}"
15686
15752
  data-agent-id="${B(t.agentId)}"
15687
15753
  data-node-url="${B(t.nodeUrl)}"
@@ -15724,7 +15790,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15724
15790
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
15725
15791
  </div>
15726
15792
  </footer>
15727
- </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Zm,scripts:`<script>${ef}</script>`})}var Zm=`
15793
+ </div>`;return I({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:tf,scripts:`<script>${af}</script>`})}var tf=`
15728
15794
  /* The shell gives <main> no padding, so page content butted straight against
15729
15795
  the sticky topbar. Breathe. */
15730
15796
  .ax-task-page {
@@ -15866,7 +15932,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15866
15932
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
15867
15933
  }
15868
15934
 
15869
- `,ef=`
15935
+ `,af=`
15870
15936
  (function () {
15871
15937
  var root = document.querySelector('.ax-task-page');
15872
15938
  if (!root) return;
@@ -16251,7 +16317,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16251
16317
  });
16252
16318
 
16253
16319
  })();
16254
- `;function qi(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16320
+ `;function Ui(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
16255
16321
  data-agent-id="${B(t.agentId)}"
16256
16322
  data-agent-name="${B(e)}"
16257
16323
  data-node-url="${B(t.nodeUrl)}">
@@ -16280,7 +16346,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16280
16346
  <div class="ax-history__list" id="hist-list">
16281
16347
  <div class="ax-history__empty">loading\u2026</div>
16282
16348
  </div>
16283
- </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:tf,scripts:`<script>${af}</script>`})}var tf=`
16349
+ </div>`;return I({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:nf,scripts:`<script>${rf}</script>`})}var nf=`
16284
16350
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
16285
16351
  flush against the sticky topbar. */
16286
16352
  .ax-history {
@@ -16332,7 +16398,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16332
16398
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
16333
16399
  }
16334
16400
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
16335
- `,af=`
16401
+ `,rf=`
16336
16402
  (function () {
16337
16403
  var root = document.querySelector('.ax-history');
16338
16404
  if (!root) return;
@@ -16432,11 +16498,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
16432
16498
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
16433
16499
  });
16434
16500
  })();
16435
- `;function Ui(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 Ge(t,e,l=>Fi(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:rf(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?Ge(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"])?Ge(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"])?Ge(t,e,l=>{let c=ba.safeParse(l);if(!c.success)return P(e,200,{ok:!1,issues:c.error.issues.map(p=>({path:p.path.join("."),message:p.message}))});let d=ya(c.data).map(p=>({path:"",message:p}));return P(e,200,{ok:d.length===0,issues:d,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 Ge(t,e,d=>Fi(e,a,d,{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 nf=["mesh"];function Fi(t,e,a,n){let r=ba.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=ya(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 d of nf)!(d in l)&&d in c&&(o[d]=c[d])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),d=l?.yamlPath,p=!!d||/yaml round-trip failed/.test(c);return P(t,p?409:500,{error:p?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:p?"yaml-authored":"save-failed",...d?{path:d}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function rf(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,d=r.get("summary")==="1"||r.get("summary")==="true",p=a.runs.list({workflowId:c,limit:l});if(!d)return P(e,200,{runs:p});let m=p.map(f=>({id:f.id,workflowId:f.workflowId,workflowVersion:f.workflowVersion,homeNode:f.homeNode,status:f.status,pending:f.pending,entityRef:f.entityRef,history:(f.history||[]).slice(-5),parentRunId:f.parentRunId,parentNodeId:f.parentNodeId,rootRunId:f.rootRunId,depth:f.depth,createdAt:f.createdAt,updatedAt:f.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 Ge(t,e,c=>{let d=c?.status;return d!=="paused"&&d!=="running"&&d!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,d)?P(e,200,{ok:!0,runId:l,status:d}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return of(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 of(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)}
16501
+ `;function Gi(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 Ge(t,e,l=>Wi(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:sf(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?Ge(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"])?Ge(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"])?Ge(t,e,l=>{let c=va.safeParse(l);if(!c.success)return P(e,200,{ok:!1,issues:c.error.issues.map(p=>({path:p.path.join("."),message:p.message}))});let d=ya(c.data).map(p=>({path:"",message:p}));return P(e,200,{ok:d.length===0,issues:d,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 Ge(t,e,d=>Wi(e,a,d,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),P(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return P(e,404,{error:"unknown workflows endpoint",path:n})}var of=["mesh"];function Wi(t,e,a,n){let r=va.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=ya(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 d of of)!(d in l)&&d in c&&(o[d]=c[d])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),d=l?.yamlPath,p=!!d||/yaml round-trip failed/.test(c);return P(t,p?409:500,{error:p?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:p?"yaml-authored":"save-failed",...d?{path:d}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),P(t,200,{workflow:i})}function sf(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,d=r.get("summary")==="1"||r.get("summary")==="true",p=a.runs.list({workflowId:c,limit:l});if(!d)return P(e,200,{runs:p});let m=p.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return 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 Ge(t,e,c=>{let d=c?.status;return d!=="paused"&&d!=="running"&&d!=="canceled"?P(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,d)?P(e,200,{ok:!0,runId:l,status:d}):P(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return lf(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 lf(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)}
16436
16502
 
16437
16503
  `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(d);try{e.end()}catch{}};t.on("close",s);let i=p=>{if(!o)try{e.write(`data: ${JSON.stringify(p)}
16438
16504
 
16439
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,d=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==c&&(c=p.updatedAt,i(p))},2e3);return!0}function Ge(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 Qf}from"fs";import{createRequire as Zf}from"module";jn();var Gi=50,sf=280;async function Xi(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=lf(await o.recent(Gi))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Wi(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Wi(e,404,{error:"not found"})}function Ki(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled)return null;if(n.relayTo)return wt();let r=ut();return r?new nr(r):null}}}function lf(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:rn(typeof n.summary=="string"?n.summary:"",sf),by:typeof n.agentId=="string"?rn(n.agentId,100):null,node:rn(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,Gi)}function rn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Wi(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var cf="operator",df=50,Ji=4,Vi=500;function pf(t){let e={channel:"app",chatId:t.chatId,sender:cf,...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 Yi(t,e,a,n){let{path:r,body:o}=pf(e),s="",i=!1,l=[],c=new Map,d=(p,m,f)=>{let _=p!=="done",v=i?{text:xt(m,_),artifacts:[]}:gt(m,ce.perMessage,_),{cleanText:E,ui:x}=p==="done"?bt(v.text):{cleanText:v.text,ui:void 0},g=i?void 0:on(x);return{status:p,text:E,tools:l,files:v.artifacts,...g?{ui:g}:{},...f?{error:f}:{}}};try{let p=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let m=await p.json().then(f=>f?.error).catch(()=>"");return d("error",s,m||`AgentX answered HTTP ${p.status}.`)}for await(let m of mf(p.body)){n(m.event,m.data);let f=m.data??{};if(m.event==="start")i=f.rich===!1;else if(m.event==="text"&&typeof f.text=="string")s+=f.text;else if(m.event==="tool"&&f.status==="start"&&l.length<df){let _={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};l.push(_),f.id&&c.set(String(f.id),_)}else if(m.event==="tool"&&f.status==="result"&&f.error===!0&&c.has(String(f.id)))c.get(String(f.id)).error=!0;else{if(m.event==="done")return d("done",typeof f.content=="string"&&f.content?f.content:s);if(m.event==="error")return d("error",s,uf(f.error))}}return a.aborted?d("stopped",s):d("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?d("stopped",s):d("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function uf(t){let e=String(t||"The agent could not answer.");return Fn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function on(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,Ji).map(s=>s.slice(0,Vi));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Ji).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Vi)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*mf(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,`
16505
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,d=setInterval(()=>{if(o)return;let p=a.runs.get(n);p&&p.updatedAt!==c&&(c=p.updatedAt,i(p))},2e3);return!0}function Ge(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 eh}from"fs";import{createRequire as th}from"module";jn();var Ki=50,cf=280;async function Ji(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=df(await o.recent(Ki))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Xi(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Xi(e,404,{error:"not found"})}function Vi(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled)return null;if(n.relayTo)return wt();let r=ut();return r?new or(r):null}}}function df(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:rn(typeof n.summary=="string"?n.summary:"",cf),by:typeof n.agentId=="string"?rn(n.agentId,100):null,node:rn(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,Ki)}function rn(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Xi(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var pf="operator",uf=50,Yi=4,Qi=500;function mf(t){let e={channel:"app",chatId:t.chatId,sender:pf,...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 Zi(t,e,a,n){let{path:r,body:o}=mf(e),s="",i=!1,l=[],c=new Map,d=(p,m,h)=>{let S=p!=="done",v=i?{text:xt(m,S),artifacts:[]}:gt(m,ce.perMessage,S),{cleanText:E,ui:b}=p==="done"?vt(v.text):{cleanText:v.text,ui:void 0},x=i?void 0:on(b);return{status:p,text:E,tools:l,files:v.artifacts,...x?{ui:x}:{},...h?{error:h}:{}}};try{let p=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let m=await p.json().then(h=>h?.error).catch(()=>"");return d("error",s,m||`AgentX answered HTTP ${p.status}.`)}for await(let m of hf(p.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<uf){let S={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(S),h.id&&c.set(String(h.id),S)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return d("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return d("error",s,ff(h.error))}}return a.aborted?d("stopped",s):d("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?d("stopped",s):d("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function ff(t){let e=String(t||"The agent could not answer.");return Fn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function on(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,Yi).map(s=>s.slice(0,Qi));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Yi).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Qi)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*hf(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,`
16440
16506
  `);let s;for(;(s=n.indexOf(`
16441
16507
 
16442
16508
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let d of i.split(`
@@ -16446,17 +16512,17 @@ data: ${JSON.stringify(s)}
16446
16512
 
16447
16513
  `)},r=setInterval(()=>{a()&&e.write(`: ping
16448
16514
 
16449
- `)},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 Zi(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=ff(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:sn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function sn(t,e=120){for(let a of t.split(`
16450
- `)){let n=el(a);if(n)return ln(n,e)}return""}function ff(t,e=120){let a=t.split(`
16451
- `).map(el).filter(Boolean);return a.length?ln(a[a.length-1],e):""}function el(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ln(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var na=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 ra(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Qi=140;function oa(t,e,a,n,r){let o=a==="error"?`Could not answer: ${sn(r||"",Qi-18)||"something went wrong."}`:sn(n,Qi)||"Answered.";return{deviceId:t,title:ln(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var al=8e3,gf=/^[A-Za-z0-9_.:-]{1,64}$/,je=new Map,cn=new Map,un=new na;function nl(){return un}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??un;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await ol(o)});let i=o.store();if(!i)return H(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),H(e,200,{conversations:Zi(r.id,bf(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let d=i.get(r.id,decodeURIComponent(l[1]));if(!d)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,d.id);let p=je.get(d.id);return H(e,200,{...d,running:!!p,...p?{partial:{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=d&&je.get(d.id);if(!d||!p)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,d.id),sl(e);let{id:m,title:f,node:_,nodeName:v,agent:E,agentName:x}=d;return e.write(dn("conversation",{id:m,title:f,node:_,nodeName:v,agent:E,agentName:x})),e.write(dn("resume",{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await yt(t,64*1024)}catch(d){return H(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=i.get(r.id,String(c.conversationId??""));if(!d)return H(e,404,{error:"no such conversation"});let p=je.get(d.id);return p?(p.ac.abort(),pn(d,o,r.name),H(e,200,{stopped:!0})):await pn(d,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await vf(e,c,r,i,o),!0}function xf(t,e,a){let n=Xe(e.url),r=new Set,o=[];for(let s of t){let i=Xe(s.url),l=a.find(p=>Xe(p.peerUrl)===i);l&&r.add(l.peer);let c=i===n,d=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:d.map(p=>{let m=Array.isArray(p.runningTasks)?p.runningTasks.length:0;return{id:p.id,name:p.name||p.id,busy:m>0||(p.active??0)>0,running:m,...p.color?{color:p.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function ol(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return xf(e.nodes,t.daemon,a)}async function vf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>al){H(t,400,{error:`message must be 1\u2013${al} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let _=typeof e.node=="string"?e.node:"",v=typeof e.agent=="string"?e.agent:"";if(!gf.test(v)){H(t,400,{error:"pick an agent"});return}let E=(await ol(r)).find(g=>g.target===_);if(!E){H(t,400,{error:`unknown node "${_}"`});return}if(!E.online){H(t,409,{error:`${E.name} is offline`});return}let x=E.agents.find(g=>g.id===v);if(!x){H(t,400,{error:`no agent "${v}" on ${E.name}`});return}s=n.create(a.id,{node:_,nodeName:E.name,agent:v,agentName:x.name,...x.color?{color:x.color}:{}},o)}if(je.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new aa(r.orphanLimitMs??18e5);je.set(s.id,i);let{id:l,title:c,node:d,nodeName:p,agent:m,agentName:f}=s;cn.set(l,{id:l,deviceId:a.id,title:c,agent:m,...f?{agentName:f}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),sl(t),t.write(dn("conversation",{id:l,title:c,node:d,nodeName:p,agent:m,agentName:f})),i.attach(t);try{let _=e.spoken===!0,v=await Yi(r.daemon,{node:d,agent:m,message:o,chatId:`app:${l}`,spoken:_},i.ac.signal,(u,h)=>i.broadcast(u,h));i.orphaned&&(v.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,pn(s,r,a.name));let E=n.appendWithFiles(a.id,l,{role:"assistant",content:v.text,status:v.status,at:Date.now(),...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...v.tools.length?{tools:v.tools}:{}},v.files)??[];i.broadcast("final",{status:v.status,content:v.text,...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...E.length?{files:E}:{}});let x=i.watched();x&&n.markRead(a.id,l);let g={status:v.status,attached:x,appOpen:(r.presence??un).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&ra(g)&&r.notifyFinish(oa(a.id,s,v.status,v.text,v.error)).catch(()=>{})}finally{je.delete(l),cn.delete(l),i.finish()}}function bf(){let t=[];for(let[e,a]of cn){let n=je.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function sl(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function dn(t,e){return`event: ${t}
16515
+ `)},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=gf(i.text);r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:l?"answering":"thinking",preview:l||i.title.slice(0,120),updatedAt:i.startedAt})}for(let i of a){if(r.length>=n)break;o.has(i.id)||(o.add(i.id),r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:"done",status:i.status,preview:sn(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function sn(t,e=120){for(let a of t.split(`
16516
+ `)){let n=al(a);if(n)return ln(n,e)}return""}function gf(t,e=120){let a=t.split(`
16517
+ `).map(al).filter(Boolean);return a.length?ln(a[a.length-1],e):""}function al(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ln(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var na=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 ra(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var el=140;function oa(t,e,a,n,r){let o=a==="error"?`Could not answer: ${sn(r||"",el-18)||"something went wrong."}`:sn(n,el)||"Answered.";return{deviceId:t,title:ln(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var rl=8e3,bf=/^[A-Za-z0-9_.:-]{1,64}$/,je=new Map,cn=new Map,un=new na;function ol(){return un}async function sl(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??un;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await il(o)});let i=o.store();if(!i)return H(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),H(e,200,{conversations:tl(r.id,wf(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let d=i.get(r.id,decodeURIComponent(l[1]));if(!d)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,d.id);let p=je.get(d.id);return H(e,200,{...d,running:!!p,...p?{partial:{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=d&&je.get(d.id);if(!d||!p)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,d.id),ll(e);let{id:m,title:h,node:S,nodeName:v,agent:E,agentName:b}=d;return e.write(dn("conversation",{id:m,title:h,node:S,nodeName:v,agent:E,agentName:b})),e.write(dn("resume",{text:p.text,tools:p.tools,...p.plain?{plain:!0}:{}})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await yt(t,64*1024)}catch(d){return H(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=i.get(r.id,String(c.conversationId??""));if(!d)return H(e,404,{error:"no such conversation"});let p=je.get(d.id);return p?(p.ac.abort(),pn(d,o,r.name),H(e,200,{stopped:!0})):await pn(d,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await yf(e,c,r,i,o),!0}function vf(t,e,a){let n=Xe(e.url),r=new Set,o=[];for(let s of t){let i=Xe(s.url),l=a.find(p=>Xe(p.peerUrl)===i);l&&r.add(l.peer);let c=i===n,d=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:d.map(p=>{let m=Array.isArray(p.runningTasks)?p.runningTasks.length:0;return{id:p.id,name:p.name||p.id,busy:m>0||(p.active??0)>0,running:m,...p.color?{color:p.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function il(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return vf(e.nodes,t.daemon,a)}async function yf(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>rl){H(t,400,{error:`message must be 1\u2013${rl} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let S=typeof e.node=="string"?e.node:"",v=typeof e.agent=="string"?e.agent:"";if(!bf.test(v)){H(t,400,{error:"pick an agent"});return}let E=(await il(r)).find(x=>x.target===S);if(!E){H(t,400,{error:`unknown node "${S}"`});return}if(!E.online){H(t,409,{error:`${E.name} is offline`});return}let b=E.agents.find(x=>x.id===v);if(!b){H(t,400,{error:`no agent "${v}" on ${E.name}`});return}s=n.create(a.id,{node:S,nodeName:E.name,agent:v,agentName:b.name,...b.color?{color:b.color}:{}},o)}if(je.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new aa(r.orphanLimitMs??18e5);je.set(s.id,i);let{id:l,title:c,node:d,nodeName:p,agent:m,agentName:h}=s;cn.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),ll(t),t.write(dn("conversation",{id:l,title:c,node:d,nodeName:p,agent:m,agentName:h})),i.attach(t);try{let S=e.spoken===!0,v=await Zi(r.daemon,{node:d,agent:m,message:o,chatId:`app:${l}`,spoken:S},i.ac.signal,(u,f)=>i.broadcast(u,f));i.orphaned&&(v.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,pn(s,r,a.name));let E=n.appendWithFiles(a.id,l,{role:"assistant",content:v.text,status:v.status,at:Date.now(),...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...v.tools.length?{tools:v.tools}:{}},v.files)??[];i.broadcast("final",{status:v.status,content:v.text,...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...E.length?{files:E}:{}});let b=i.watched();b&&n.markRead(a.id,l);let x={status:v.status,attached:b,appOpen:(r.presence??un).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&ra(x)&&r.notifyFinish(oa(a.id,s,v.status,v.text,v.error)).catch(()=>{})}finally{je.delete(l),cn.delete(l),i.finish()}}function wf(){let t=[];for(let[e,a]of cn){let n=je.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function ll(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function dn(t,e){return`event: ${t}
16452
16518
  data: ${JSON.stringify(e)}
16453
16519
 
16454
- `}async function pn(t,e,a){try{let n=Xe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Xe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Xe(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 Xe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as yf}from"stream";var wf=/^\/api\/app\/files\/([^/]+)$/,kf=15e3;async function ll(t,e,a,n,r,o){let s=wf.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Oe(e,405,{error:"GET only"});let i=o.store();if(!i)return Oe(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return Oe(e,404,{error:"no such file"});let d=await _f(c.node,o);if(!d)return Oe(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let p=new AbortController;e.on("close",()=>p.abort());let m=setTimeout(()=>p.abort(),kf),f;try{let g=new URLSearchParams({agent:c.agent,file:c.path});f=await fetch(`${d.url}${hr}?${g}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return Oe(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(f.status!==200&&f.status!==206){let g=await f.json().then(h=>h?.error).catch(()=>""),u=[403,404,413,415,416].includes(f.status)?f.status:502;return Oe(e,u,{error:g||`The computer that made this file answered HTTP ${f.status}.`})}let _=Number(f.headers.get("content-length")||0);if(_>ce.bytes)return p.abort(),Oe(e,413,{error:"the file is too large"});let v=f.headers.get("content-range");if(e.writeHead(f.status,{...gr(c.mime,c.name,c.kind),...f.headers.get("content-length")?{"Content-Length":String(_)}:{},...f.status===206&&v?{"Content-Range":v}:{}}),n==="HEAD"||!f.body)return e.end(),!0;let E=0,x=yf.fromWeb(f.body);return x.on("data",g=>{E+=g.length,E>ce.bytes&&(x.destroy(),e.destroy())}),x.on("error",()=>e.destroy()),x.pipe(e),!0}async function _f(t,e){if(t==="local")return{url:il(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=il(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function il(t){return t.replace(/\/+$/,"")}function Oe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var dl=8e3;async function pl(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 f=String(t.headers["content-type"]||"");if(!Er(f))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let _=Sr(t.headers["x-audio-duration-ms"]);if(_)return t.resume(),Y(e,_.status,{error:_.error});let v=await Te(t,_r.bytes);if(!v)return Y(e,413,{error:Tr()});if(!v.length)return Y(e,400,{error:"The recording is empty."});let E={"Content-Type":f,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return cl(e,o.daemon,"/voice/transcribe",v,E,18e4)}let s,i=await Te(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Y(e,404,{error:"no such conversation"});let d=typeof s?.text=="string"?s.text.slice(0,dl):"";if(!d.trim())return Y(e,400,{error:"text is required"});if(!Ef(c.messages,d))return Y(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:p,...c.node!=="local"?{peer:c.node}:{}};return cl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function cl(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(Sf(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 Sf(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Ef(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===dl&&a.content.startsWith(e)))}var Tf=new Set(["ring","offer","answer","ice","hangup"]),Ke=/^[A-Za-z0-9_-]{4,64}$/,Af=128*1024,Cf=24,If=2*1024*1024,Ne=new Map;async function ml(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(),d=Qe(r.nodeName),p=(Array.isArray(c.peers)?c.peers:[]).filter(f=>Qe(String(f?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(f=>f&&typeof f.id=="string").map(f=>({id:f.id,name:typeof f.name=="string"&&f.name?f.name:f.id}));return M(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:p,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 Te(t,Af);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 d=Lf(c,r.nodeName);if(typeof d=="string")return M(e,400,{error:d});let p=fl(d.to);if(p&&d.kind==="ring"){let m=await De(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:p});return M(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(d),signal:AbortSignal.timeout(15e3)}),f=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:f?.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 Ke.test(l)?Rf(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Te(t,4096);if(!l)return M(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Ke.test(d))return M(e,400,{error:"callId is required"});let p=typeof c?.note=="string"?c.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:p},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await ul(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ke.test(c))return M(e,400,{error:"callId is required"});let d=Number(l.seconds??0);if(!Number.isFinite(d)||d<0)return M(e,400,{error:"seconds must be 0 or more"});let p=typeof l.note=="string"?l.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/stream`,{seconds:d,note:p});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await ul(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ke.test(c))return M(e,400,{error:"callId is required"});let d=await De(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(c)}`);if(d.status>=300)return M(e,d.status,{error:d.body.error});let p=(Array.isArray(d.body.watch?.replies)?d.body.watch.replies:[]).find(v=>v&&v.at===l.at);if(!p||typeof p.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(d.body.watch.agentId??""),f=JSON.stringify([c,p.at,m,p.text]),_=Ne.get(f);return _?(Ne.delete(f),Ne.set(f,_),hl(e,_.type,_.bytes)):Mf(e,o,s,{agent:m,text:p.text},(v,E)=>{if(!(E.length>If))for(Ne.set(f,{type:v,bytes:E});Ne.size>Cf;)Ne.delete(Ne.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await De(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.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 De(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Ke.test(l))return M(e,400,{error:"callId is required"});let c=await De(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 fl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function De(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}async function ul(t,e){let a=await Te(t,e);if(!a)return null;try{let n=JSON.parse(a.toString("utf8")||"{}");return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}async function Mf(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),hl(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 hl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function Lf(t,e){let a=String(t?.kind??"");if(!Tf.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Ke.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:")&&!fl(r))return"to must be bot:<agent id> for an agent";if(Qe(r)===Qe(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 Rf(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 Pf,readFileSync as $f,renameSync as jf,writeFileSync as Of}from"fs";import{dirname as Nf,isAbsolute as Df,resolve as Bf}from"path";import{randomBytes as Hf}from"crypto";var gl=60,xl=500,zf=200,yl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,qf=/^[A-Za-z0-9_-]{8,64}$/,Ff=/^[A-Za-z0-9._-]{1,64}$/;function wl(t,e){return Df(e)?e:Bf(t,e)}function vl(t){return`${t}_${Hf(6).toString("hex")}`}function bl(){return{places:[],rules:[],seen:[]}}function kl(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 _l(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!yl.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&&(!Ff.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 Sl(t){let e=typeof t.id=="string"?t.id:"";if(!qf.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!yl.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 sa=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse($f(this.path,"utf-8"));return!e||typeof e!="object"?bl():{places:Array.isArray(e.places)?e.places:[],rules:Array.isArray(e.rules)?e.rules:[],seen:Array.isArray(e.seen)?e.seen.filter(a=>typeof a=="string"):[]}}catch{return bl()}}write(e){Pf(Nf(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Of(a,JSON.stringify(e,null,2)+`
16455
- `,{mode:384}),jf(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:vl("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:vl("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(-zf);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}};Nn();function Uf(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function Wf(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(`
16456
- `)}async function El(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=Uf(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,Wf(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16520
+ `}async function pn(t,e,a){try{let n=Xe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Xe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Xe(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 Xe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as kf}from"stream";var _f=/^\/api\/app\/files\/([^/]+)$/,Sf=15e3;async function dl(t,e,a,n,r,o){let s=_f.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Oe(e,405,{error:"GET only"});let i=o.store();if(!i)return Oe(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return Oe(e,404,{error:"no such file"});let d=await Ef(c.node,o);if(!d)return Oe(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let p=new AbortController;e.on("close",()=>p.abort());let m=setTimeout(()=>p.abort(),Sf),h;try{let x=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${d.url}${xr}?${x}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:p.signal})}catch{return Oe(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let x=await h.json().then(f=>f?.error).catch(()=>""),u=[403,404,413,415,416].includes(h.status)?h.status:502;return Oe(e,u,{error:x||`The computer that made this file answered HTTP ${h.status}.`})}let S=Number(h.headers.get("content-length")||0);if(S>ce.bytes)return p.abort(),Oe(e,413,{error:"the file is too large"});let v=h.headers.get("content-range");if(e.writeHead(h.status,{...br(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(S)}:{},...h.status===206&&v?{"Content-Range":v}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let E=0,b=kf.fromWeb(h.body);return b.on("data",x=>{E+=x.length,E>ce.bytes&&(b.destroy(),e.destroy())}),b.on("error",()=>e.destroy()),b.pipe(e),!0}async function Ef(t,e){if(t==="local")return{url:cl(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=cl(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function cl(t){return t.replace(/\/+$/,"")}function Oe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var ul=8e3;async function ml(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 h=String(t.headers["content-type"]||"");if(!Ar(h))return Y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let S=Tr(t.headers["x-audio-duration-ms"]);if(S)return t.resume(),Y(e,S.status,{error:S.error});let v=await Te(t,Er.bytes);if(!v)return Y(e,413,{error:Cr()});if(!v.length)return Y(e,400,{error:"The recording is empty."});let E={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return pl(e,o.daemon,"/voice/transcribe",v,E,18e4)}let s,i=await Te(t,64*1024);if(!i)return Y(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Y(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Y(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Y(e,404,{error:"no such conversation"});let d=typeof s?.text=="string"?s.text.slice(0,ul):"";if(!d.trim())return Y(e,400,{error:"text is required"});if(!Af(c.messages,d))return Y(e,404,{error:"no such answer in this conversation"});let p=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:p,...c.node!=="local"?{peer:c.node}:{}};return pl(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function pl(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(Tf(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 Tf(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Af(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===ul&&a.content.startsWith(e)))}var Cf=new Set(["ring","offer","answer","ice","hangup"]),Ke=/^[A-Za-z0-9_-]{4,64}$/,If=128*1024,Mf=24,Lf=2*1024*1024,Ne=new Map;async function hl(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(),d=Qe(r.nodeName),p=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Qe(String(h?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return M(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:p,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 Te(t,If);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 d=Pf(c,r.nodeName);if(typeof d=="string")return M(e,400,{error:d});let p=gl(d.to);if(p&&d.kind==="ring"){let m=await De(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:p});return M(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(d),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return M(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.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 Ke.test(l)?$f(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):M(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await Te(t,4096);if(!l)return M(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return M(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Ke.test(d))return M(e,400,{error:"callId is required"});let p=typeof c?.note=="string"?c.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:p},18e4);return M(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/stream"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await fl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ke.test(c))return M(e,400,{error:"callId is required"});let d=Number(l.seconds??0);if(!Number.isFinite(d)||d<0)return M(e,400,{error:"seconds must be 0 or more"});let p=typeof l.note=="string"?l.note:"",m=await De(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(c)}/stream`,{seconds:d,note:p});return M(e,m.status,m.status<300?{watch:m.body.watch}:{error:m.body.error})}if(a==="/api/app/camera/speak"){if(n!=="POST")return M(e,405,{error:"POST"});let l=await fl(t,4096);if(!l)return M(e,400,{error:"expected JSON"});let c=String(l.callId??"");if(!Ke.test(c))return M(e,400,{error:"callId is required"});let d=await De(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(c)}`);if(d.status>=300)return M(e,d.status,{error:d.body.error});let p=(Array.isArray(d.body.watch?.replies)?d.body.watch.replies:[]).find(v=>v&&v.at===l.at);if(!p||typeof p.text!="string")return M(e,404,{error:"no such answer on this share"});let m=String(d.body.watch.agentId??""),h=JSON.stringify([c,p.at,m,p.text]),S=Ne.get(h);return S?(Ne.delete(h),Ne.set(h,S),xl(e,S.type,S.bytes)):Rf(e,o,s,{agent:m,text:p.text},(v,E)=>{if(!(E.length>Lf))for(Ne.set(h,{type:v,bytes:E});Ne.size>Mf;)Ne.delete(Ne.keys().next().value)})}if(a==="/api/app/camera/asks"){if(n!=="GET")return M(e,405,{error:"GET"});let l=await De(o,s,"GET","/calls/asking");if(l.status>=300)return M(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.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 De(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return M(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return M(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Ke.test(l))return M(e,400,{error:"callId is required"});let c=await De(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 gl(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function De(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}async function fl(t,e){let a=await Te(t,e);if(!a)return null;try{let n=JSON.parse(a.toString("utf8")||"{}");return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}async function Rf(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),xl(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 xl(t,e,a){return t.writeHead(200,{"Content-Type":e,"Content-Length":String(a.length),"Cache-Control":"no-store"}),t.end(a),!0}function Pf(t,e){let a=String(t?.kind??"");if(!Cf.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Ke.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:")&&!gl(r))return"to must be bot:<agent id> for an agent";if(Qe(r)===Qe(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 $f(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 jf,readFileSync as Of,renameSync as Nf,writeFileSync as Df}from"fs";import{dirname as Bf,isAbsolute as Hf,resolve as zf}from"path";import{randomBytes as qf}from"crypto";var bl=60,vl=500,Ff=200,kl=/^[a-z]{2,5}_[a-z0-9]{6,32}$/,Uf=/^[A-Za-z0-9_-]{8,64}$/,Wf=/^[A-Za-z0-9._-]{1,64}$/;function _l(t,e){return Hf(e)?e:zf(t,e)}function yl(t){return`${t}_${qf(6).toString("hex")}`}function wl(){return{places:[],rules:[],seen:[]}}function Sl(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>bl)return{ok:!1,error:`Keep the name under ${bl} 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 El(t,e){let a=typeof t.placeId=="string"?t.placeId:"";if(!kl.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>vl)return{ok:!1,error:`Keep it under ${vl} characters.`};let o=typeof t.agent=="string"?t.agent.trim():"";return o&&(!Wf.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 Tl(t){let e=typeof t.id=="string"?t.id:"";if(!Uf.test(e))return{ok:!1,error:"id must be 8 to 64 letters, digits, - or _"};let a=typeof t.place=="string"?t.place:"";if(!kl.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 sa=class{constructor(e,a=Date.now){this.path=e;this.now=a}read(){try{let e=JSON.parse(Of(this.path,"utf-8"));return!e||typeof e!="object"?wl():{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 wl()}}write(e){jf(Bf(this.path),{recursive:!0});let a=`${this.path}.${process.pid}.tmp`;Df(a,JSON.stringify(e,null,2)+`
16521
+ `,{mode:384}),Nf(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:yl("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:yl("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(-Ff);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}};Nn();function Gf(t,e){return e==="enter"?`Arrived at ${t.name}`:`Left ${t.name}`}function Xf(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(`
16522
+ `)}async function Al(t,e,a,n,r){await Promise.all(a.map(async o=>{let s=Gf(e,o.on),i=o.text;if(o.agent)try{i=(await r.task(o.agent,Xf(e,o,n),o.id)).trim()||`${o.agent} had nothing to add.`}catch(l){i=`${o.text}
16457
16523
 
16458
- (${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 Tl(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}
16459
- ${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?{[On]: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 Al(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Il(t,e,a.slice(15),n,o,r)}async function Cl(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Il(t,e,a.slice(11),n,r,null)}async function Il(t,e,a,n,r,o){if(n==="GET"&&a===""){let i=r.enabled?r.store.read():{places:[],rules:[]};return z(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 z(e,404,{error:"not found"});if(!r.enabled)return z(e,403,{error:"Place reminders are off on this computer (app.places.enabled)."});let s;try{s=await yt(t,4096)}catch(i){return z(e,400,{error:i.message})}if(a==="/event"){if(!o)return z(e,404,{error:"not found"});let i=Sl(s);if(!i.ok)return z(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?El(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"}`)),z(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=kl(s,r.limits);if(!i.ok)return z(e,400,{error:i.error});let l=r.store.addPlace(i.value,r.limits);return l.ok?z(e,200,{ok:!0,place:l.place}):z(e,409,{error:l.error})}if(a==="/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removePlace(i)?z(e,200,{ok:!0}):z(e,404,{error:"No such place."})}if(a==="/rules/add"){let i=new Set(r.agents()),l=_l(s,d=>i.has(d));if(!l.ok)return z(e,400,{error:l.error});let c=r.store.addRule(l.value,r.limits);return c.ok?z(e,200,{ok:!0,rule:c.rule}):z(e,409,{error:c.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return z(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?z(e,200,{ok:!0,rule:i}):z(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?z(e,200,{ok:!0}):z(e,404,{error:"No such reminder."})}return z(e,404,{error:"not found"})}function Ml(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new sa(wl(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function Ll(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 z(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Rl=`
16524
+ (${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 Cl(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}
16525
+ ${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?{[On]: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 Il(t,e,a,n,r,o){return a!=="/api/app/places"&&!a.startsWith("/api/app/places/")?!1:Ll(t,e,a.slice(15),n,o,r)}async function Ml(t,e,a,n,r){return a!=="/api/places"&&!a.startsWith("/api/places/")?!1:Ll(t,e,a.slice(11),n,r,null)}async function Ll(t,e,a,n,r,o){if(n==="GET"&&a===""){let i=r.enabled?r.store.read():{places:[],rules:[]};return z(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 z(e,404,{error:"not found"});if(!r.enabled)return z(e,403,{error:"Place reminders are off on this computer (app.places.enabled)."});let s;try{s=await yt(t,4096)}catch(i){return z(e,400,{error:i.message})}if(a==="/event"){if(!o)return z(e,404,{error:"not found"});let i=Tl(s);if(!i.ok)return z(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?Al(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"}`)),z(e,202,{ok:!0,status:l.status,fired:l.status==="fired"?l.rules.length:0})}if(a==="/add"){let i=Sl(s,r.limits);if(!i.ok)return z(e,400,{error:i.error});let l=r.store.addPlace(i.value,r.limits);return l.ok?z(e,200,{ok:!0,place:l.place}):z(e,409,{error:l.error})}if(a==="/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removePlace(i)?z(e,200,{ok:!0}):z(e,404,{error:"No such place."})}if(a==="/rules/add"){let i=new Set(r.agents()),l=El(s,d=>i.has(d));if(!l.ok)return z(e,400,{error:l.error});let c=r.store.addRule(l.value,r.limits);return c.ok?z(e,200,{ok:!0,rule:c.rule}):z(e,409,{error:c.error})}if(a==="/rules/enable"){if(typeof s.enabled!="boolean")return z(e,400,{error:"enabled must be true or false"});let i=r.store.setRuleEnabled(typeof s.id=="string"?s.id:"",s.enabled);return i?z(e,200,{ok:!0,rule:i}):z(e,404,{error:"No such reminder."})}if(a==="/rules/remove"){let i=typeof s.id=="string"?s.id:"";return r.store.removeRule(i)?z(e,200,{ok:!0}):z(e,404,{error:"No such reminder."})}return z(e,404,{error:"not found"})}function Rl(t,e,a,n){let r=t.app.places;return{enabled:r.enabled,limits:r,syncMinutes:r.syncMinutes,store:new sa(_l(e,r.file)),agents:()=>Object.keys(t.agents||{}).sort(),fire:a,pushReason:n,androidPackage:t.app.android.packageName,log:o=>console.error(o)}}function Pl(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 z(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var $l=`
16460
16526
  :root {
16461
16527
  --ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
16462
16528
  --ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
@@ -16470,7 +16536,7 @@ ${s}`,buttons:[{label:"Open",url:"/app#alerts"}]}),signal:AbortSignal.timeout(15
16470
16536
  --ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
16471
16537
  --phone-bubble: #1d2f52; --phone-green: #3dbe74;
16472
16538
  }
16473
- `,Pl=`
16539
+ `,jl=`
16474
16540
  [hidden] { display: none !important; }
16475
16541
  main > .sw-peek[hidden] { display: block !important; }
16476
16542
  main > #panel-chat.sw-peek[hidden] { display: flex !important; }
@@ -16576,7 +16642,7 @@ main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
16576
16642
  @media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
16577
16643
  @media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
16578
16644
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
16579
- `;var $l=`
16645
+ `;var Ol=`
16580
16646
  window.AXSheet = function (sheet, onClose) {
16581
16647
  var handle = document.createElement('button');
16582
16648
  handle.type = 'button'; handle.className = 'sheet-handle';
@@ -16605,7 +16671,7 @@ window.AXSheet = function (sheet, onClose) {
16605
16671
  handle.addEventListener('pointercancel', reset);
16606
16672
  sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
16607
16673
  };
16608
- `;var jl=`
16674
+ `;var Nl=`
16609
16675
  (function () {
16610
16676
  var fleetPanel = document.getElementById('panel-fleet');
16611
16677
  var activityPanel = document.getElementById('panel-activity');
@@ -16896,7 +16962,7 @@ window.AXSheet = function (sheet, onClose) {
16896
16962
  setInterval(refresh, 15000);
16897
16963
  refresh();
16898
16964
  })();
16899
- `;var Ol=`
16965
+ `;var Dl=`
16900
16966
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
16901
16967
  .fx-head h2 { margin: 4px 0 0; }
16902
16968
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -16961,7 +17027,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16961
17027
  .fx-opt em { font-style: normal; font-size: 12px; color: var(--ax-ok); white-space: nowrap; }
16962
17028
  .fx-error:empty { display: none; }
16963
17029
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
16964
- `;var Nl=`
17030
+ `;var Bl=`
16965
17031
  (function () {
16966
17032
  var panel = document.getElementById('panel-alerts');
16967
17033
  if (!panel) return;
@@ -17172,7 +17238,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17172
17238
  refresh();
17173
17239
  loadRecent();
17174
17240
  })();
17175
- `;var Dl=`
17241
+ `;var Hl=`
17176
17242
  (function () {
17177
17243
  var panel = document.getElementById('panel-alerts');
17178
17244
  if (!panel) return;
@@ -17324,7 +17390,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17324
17390
  document.addEventListener('visibilitychange', function () { if (!document.hidden && state) load(); });
17325
17391
  load();
17326
17392
  })();
17327
- `,Bl=`
17393
+ `,zl=`
17328
17394
  .pl-card { margin-top: 12px; }
17329
17395
  .pl-list { margin-top: 8px; }
17330
17396
  .pl-rules { list-style: none; margin: 6px 0 0; padding: 0; }
@@ -17343,7 +17409,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17343
17409
  .pl-check { display: flex; align-items: center; gap: 8px; font-size: var(--ax-fs-sm); }
17344
17410
  .pl-check input { width: 20px; height: 20px; }
17345
17411
  #pl-here { justify-self: start; }
17346
- `;function Hl(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 zl=`
17412
+ `;function ql(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 Fl=`
17347
17413
  (function () {
17348
17414
  var panel = document.getElementById('panel-alerts');
17349
17415
  if (!panel) return;
@@ -17456,7 +17522,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17456
17522
  }
17457
17523
  load();
17458
17524
  })();
17459
- `;var ql=`
17525
+ `;var Ul=`
17460
17526
  (function () {
17461
17527
  var panel = document.getElementById('panel-chat');
17462
17528
  var V = window.AXChatView;
@@ -17739,7 +17805,7 @@ details[open] > summary::before { transform: rotate(90deg); }
17739
17805
  var last = recall('ax-chat-conv');
17740
17806
  if (!fromHash() && last) openConversation(last);
17741
17807
  })();
17742
- `;var Fl=`
17808
+ `;var Wl=`
17743
17809
  window.AXChatView = (function () {
17744
17810
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
17745
17811
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -18020,7 +18086,7 @@ window.AXChatView = (function () {
18020
18086
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
18021
18087
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
18022
18088
  })();
18023
- `;var Ul=`
18089
+ `;var Gl=`
18024
18090
  window.AXChatSheets = function (o) {
18025
18091
  var V = o.V, picker = o.picker, hist = o.hist;
18026
18092
  function loadPicker() {
@@ -18066,7 +18132,7 @@ window.AXChatSheets = function (o) {
18066
18132
  });
18067
18133
  return { loadPicker: loadPicker, loadHistory: loadHistory };
18068
18134
  };
18069
- `;var Wl=`
18135
+ `;var Xl=`
18070
18136
  window.AXChatLog = function (o) {
18071
18137
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
18072
18138
  function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
@@ -18129,7 +18195,7 @@ window.AXChatLog = function (o) {
18129
18195
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
18130
18196
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
18131
18197
  };
18132
- `;var Gl=`
18198
+ `;var Kl=`
18133
18199
  (function () {
18134
18200
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
18135
18201
  var top = panel && panel.querySelector('.cx-top');
@@ -18279,7 +18345,7 @@ window.AXChatLog = function (o) {
18279
18345
  window.AXStrip = { poll: poll, update: update, banner: banner };
18280
18346
  poll();
18281
18347
  })();
18282
- `;var Xl=`
18348
+ `;var Jl=`
18283
18349
  .cs { margin: 0 -2px; }
18284
18350
  .cs[hidden] { display: none; }
18285
18351
  .cs-list {
@@ -18335,7 +18401,7 @@ window.AXChatLog = function (o) {
18335
18401
  @media (prefers-reduced-motion: reduce) {
18336
18402
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
18337
18403
  }
18338
- `;function Kl(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 Jl(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Vl=`
18404
+ `;function Vl(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 Yl(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Ql=`
18339
18405
  body { height: 100dvh; }
18340
18406
  main { min-height: 0; }
18341
18407
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -18445,7 +18511,7 @@ main { min-height: 0; }
18445
18511
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
18446
18512
  }
18447
18513
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
18448
- `;var Yl=`
18514
+ `;var Zl=`
18449
18515
  window.AXOrb = (function () {
18450
18516
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
18451
18517
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -18562,7 +18628,7 @@ window.AXOrb = (function () {
18562
18628
  }
18563
18629
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
18564
18630
  })();
18565
- `;var Ql=`
18631
+ `;var ec=`
18566
18632
  window.AXVoiceIO = (function () {
18567
18633
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
18568
18634
  var ac = null, playing = null;
@@ -18680,7 +18746,7 @@ window.AXVoiceIO = (function () {
18680
18746
 
18681
18747
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
18682
18748
  })();
18683
- `;var Zl=`
18749
+ `;var tc=`
18684
18750
  (function () {
18685
18751
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
18686
18752
  if (!panel || !C || !IO || !O) return;
@@ -18893,7 +18959,7 @@ window.AXVoiceIO = (function () {
18893
18959
  idle();
18894
18960
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
18895
18961
  })();
18896
- `;var ec=`
18962
+ `;var ac=`
18897
18963
  .vx {
18898
18964
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
18899
18965
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -18929,7 +18995,7 @@ window.AXVoiceIO = (function () {
18929
18995
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
18930
18996
  .cx-typing-on .vx-row { gap: 16px; }
18931
18997
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
18932
- `;var tc=`
18998
+ `;var nc=`
18933
18999
  <main class="card">
18934
19000
  <h1>This phone isn't paired</h1>
18935
19001
  <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>
@@ -18943,7 +19009,7 @@ window.AXVoiceIO = (function () {
18943
19009
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
18944
19010
  </form>
18945
19011
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
18946
- </main>`,ac=`
19012
+ </main>`,rc=`
18947
19013
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
18948
19014
  .pair-form label { font-weight: 600; }
18949
19015
  .pair-form input {
@@ -18965,7 +19031,7 @@ window.AXVoiceIO = (function () {
18965
19031
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
18966
19032
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
18967
19033
  }
18968
- `,nc=`
19034
+ `,oc=`
18969
19035
  (function () {
18970
19036
  var form = document.getElementById('pair-form');
18971
19037
  var input = document.getElementById('pair-code');
@@ -19057,7 +19123,7 @@ window.AXVoiceIO = (function () {
19057
19123
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
19058
19124
  }
19059
19125
  })();
19060
- `;var rc=`
19126
+ `;var sc=`
19061
19127
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
19062
19128
  <video id="scan-video" playsinline muted autoplay></video>
19063
19129
  <div class="scan-frame" aria-hidden="true"></div>
@@ -19066,7 +19132,7 @@ window.AXVoiceIO = (function () {
19066
19132
  <button type="button" id="scan-close" class="scan-close">Close</button>
19067
19133
  </div>
19068
19134
  <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>
19069
- </div>`,oc=`
19135
+ </div>`,ic=`
19070
19136
  .pair-form .scan-btn {
19071
19137
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
19072
19138
  }
@@ -19095,7 +19161,7 @@ window.AXVoiceIO = (function () {
19095
19161
  }
19096
19162
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
19097
19163
  body.scanning { overflow: hidden; }
19098
- `,sc=`
19164
+ `,lc=`
19099
19165
  (function () {
19100
19166
  var openBtn = document.getElementById('scan-btn');
19101
19167
  var box = document.getElementById('scan');
@@ -19320,7 +19386,7 @@ body.scanning { overflow: hidden; }
19320
19386
  @keyframes cam-pulse { 50% { opacity: .3; } }
19321
19387
  @media (prefers-reduced-motion: reduce) { .cam-live.is-stream .cam-dot { animation: none; } }
19322
19388
  #cam-stream[aria-pressed="true"] { border-color: var(--ax-red); color: var(--ax-red-ink); }
19323
- `;var ic='<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>',lc=`
19389
+ `;var cc='<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>',dc=`
19324
19390
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
19325
19391
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
19326
19392
  <span class="cam-dot" aria-hidden="true"></span>
@@ -19349,7 +19415,7 @@ body.scanning { overflow: hidden; }
19349
19415
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
19350
19416
  </div>
19351
19417
  </div>
19352
- </div>`,cc=`
19418
+ </div>`,pc=`
19353
19419
  (function () {
19354
19420
  var btn = document.getElementById('cam-btn');
19355
19421
  var sheet = document.getElementById('cam');
@@ -19823,7 +19889,7 @@ body.scanning { overflow: hidden; }
19823
19889
  });
19824
19890
  window.addEventListener('pagehide', function () { stop(); });
19825
19891
  })();
19826
- `;var dc=`
19892
+ `;var uc=`
19827
19893
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
19828
19894
  <div class="cam-askbar-text">
19829
19895
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -19833,7 +19899,7 @@ body.scanning { overflow: hidden; }
19833
19899
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
19834
19900
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
19835
19901
  </div>
19836
- </div>`,pc=`
19902
+ </div>`,mc=`
19837
19903
  .cam-askbar[hidden] { display: none; }
19838
19904
  .cam-askbar {
19839
19905
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -19848,7 +19914,7 @@ body.scanning { overflow: hidden; }
19848
19914
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
19849
19915
  }
19850
19916
  .cam-askbar-no { background: transparent; color: #fff; }
19851
- `,uc=`
19917
+ `,fc=`
19852
19918
  (function () {
19853
19919
  var bar = document.getElementById('cam-ask-bar');
19854
19920
  if (!bar) return;
@@ -19918,7 +19984,7 @@ body.scanning { overflow: hidden; }
19918
19984
  setInterval(poll, 5000);
19919
19985
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
19920
19986
  })();
19921
- `;function mc(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 hc(t){return t>=400?"send":"listen"}function gc(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var xc=`
19987
+ `;function hc(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 gc(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 xc(t){return t>=400?"send":"listen"}function bc(t){let e=Math.max(1,Math.round(t||60));return"Keep watching "+(e%60===0?e/60+" min":e+" s")}var vc=`
19922
19988
  (function () {
19923
19989
  var main = document.querySelector('main');
19924
19990
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
@@ -20037,7 +20103,7 @@ body.scanning { overflow: hidden; }
20037
20103
  main.addEventListener('touchend', function () { end(false); });
20038
20104
  main.addEventListener('touchcancel', function () { end(true); });
20039
20105
  })();
20040
- `,vc=`
20106
+ `,yc=`
20041
20107
  main { position: relative; }
20042
20108
  main.sw-on { overflow: hidden; }
20043
20109
  .sw-on > [role=tabpanel] { will-change: transform; }
@@ -20048,8 +20114,8 @@ main > .sw-peek {
20048
20114
  }
20049
20115
  main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
20050
20116
  @media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
20051
- `;function bc(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 yc(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function wc(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function kc(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 fn=`
20052
- ${q({afterUnauthorized:Ao})}
20117
+ `;function wc(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 kc(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function _c(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Sc(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 fn=`
20118
+ ${q({afterUnauthorized:Io})}
20053
20119
  var CACHE = 'agentx-app-v3';
20054
20120
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
20055
20121
  self.addEventListener('install', function (e) {
@@ -20140,7 +20206,7 @@ self.addEventListener('notificationclick', function (e) {
20140
20206
  return self.clients.openWindow(target);
20141
20207
  }));
20142
20208
  });
20143
- `;var Gf="<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 hn(t){return`<meta charset="utf-8">
20209
+ `;var Kf="<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 hn(t){return`<meta charset="utf-8">
20144
20210
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
20145
20211
  <meta name="theme-color" content="#2979FF">
20146
20212
  <meta name="referrer" content="no-referrer">
@@ -20151,40 +20217,40 @@ self.addEventListener('notificationclick', function (e) {
20151
20217
  <link rel="icon" type="image/png" href="/app/icon-192.png">
20152
20218
  <link rel="apple-touch-icon" href="/app/icon-192.png">
20153
20219
  <title>${t}</title>
20154
- ${Gf}
20155
- <style>${ze}${Rl}${Vf}</style>`}var Xf={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"},_c=[{id:"chat",label:"Chat",soon:"Loading your conversations\u2026"},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Loading notifications\u2026"}];function Sc(){let t=_c.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="${Xf[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=_c.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20220
+ ${Kf}
20221
+ <style>${ze}${$l}${Qf}</style>`}var Jf={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"},Ec=[{id:"chat",label:"Chat",soon:"Loading your conversations\u2026"},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Loading notifications\u2026"}];function Tc(){let t=Ec.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="${Jf[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=Ec.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
20156
20222
  <h2>${a.label}</h2>
20157
20223
  <p class="soon">${a.soon}</p>
20158
20224
  </section>`).join("");return`<!doctype html>
20159
20225
  <html lang="en">
20160
- <head>${hn("AgentX")}<style>${Yf}${Ol}${Vl}${Xl}${ec}${mn}${pc}${vc}${Bl}${Pl}</style></head>
20226
+ <head>${hn("AgentX")}<style>${Zf}${Dl}${Ql}${Jl}${ac}${mn}${mc}${yc}${zl}${jl}</style></head>
20161
20227
  <body>
20162
20228
  <header class="bar">
20163
20229
  <div>
20164
20230
  <h1>AgentX</h1>
20165
20231
  <p id="who" class="who">Connecting\u2026</p>
20166
20232
  </div>
20167
- <div class="bar-btns">${ic}<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>
20233
+ <div class="bar-btns">${cc}<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>
20168
20234
  </header>
20169
20235
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
20170
- ${dc}
20236
+ ${uc}
20171
20237
  <main>${e}</main>
20172
20238
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
20173
- ${lc}
20174
- <script>${Kf}</script>
20175
- <script>${q({swipeMayStart:bc,swipeAxis:yc,swipeOffset:wc,swipeLanding:kc})}${xc}</script>
20176
- <script>${$l}</script>
20177
- <script>${jl}</script>
20239
+ ${dc}
20240
+ <script>${Vf}</script>
20241
+ <script>${q({swipeMayStart:wc,swipeAxis:kc,swipeOffset:_c,swipeLanding:Sc})}${vc}</script>
20242
+ <script>${Ol}</script>
20178
20243
  <script>${Nl}</script>
20179
- <script>${q({locationErrorText:Hl})}${Dl}</script>
20180
- <script>${zl}</script>
20181
- <script>${q({markdownToHtml:ur})}${Fl}${Wl}${Ul}${ql}</script>
20182
- <script>${q({queueSpeech:Kl,nextSpeech:Jl})}${Yl}${Ql}${Zl}</script>
20183
- <script>${Gl}</script>
20184
- <script>${q({cameraConstraints:mc,shareClock:fc,streamLabel:gc,talkRelease:hc})}${cc}</script>
20185
- <script>${uc}</script>
20244
+ <script>${Bl}</script>
20245
+ <script>${q({locationErrorText:ql})}${Hl}</script>
20246
+ <script>${Fl}</script>
20247
+ <script>${q({markdownToHtml:fr})}${Wl}${Xl}${Gl}${Ul}</script>
20248
+ <script>${q({queueSpeech:Vl,nextSpeech:Yl})}${Zl}${ec}${tc}</script>
20249
+ <script>${Kl}</script>
20250
+ <script>${q({cameraConstraints:hc,shareClock:gc,streamLabel:bc,talkRelease:xc})}${pc}</script>
20251
+ <script>${fc}</script>
20186
20252
  </body>
20187
- </html>`}function Ec(){return`<!doctype html>
20253
+ </html>`}function Ac(){return`<!doctype html>
20188
20254
  <html lang="en">
20189
20255
  <head>${hn("Pair \xB7 AgentX")}</head>
20190
20256
  <body>
@@ -20192,17 +20258,17 @@ ${lc}
20192
20258
  <h1>Pairing this phone\u2026</h1>
20193
20259
  <p id="msg" role="status">One moment.</p>
20194
20260
  </main>
20195
- <script>${Jf}</script>
20261
+ <script>${Yf}</script>
20196
20262
  </body>
20197
- </html>`}function Tc(){return`<!doctype html>
20263
+ </html>`}function Cc(){return`<!doctype html>
20198
20264
  <html lang="en">
20199
- <head>${hn("Not paired \xB7 AgentX")}<style>${ac}${oc}</style></head>
20200
- <body>${tc}${rc}
20201
- <script>${q({mayBounce:Co,formatPairInput:qt,parsePairScan:Io})}</script>
20202
- <script>${nc}</script>
20203
- <script>${sc}</script>
20265
+ <head>${hn("Not paired \xB7 AgentX")}<style>${rc}${ic}</style></head>
20266
+ <body>${nc}${sc}
20267
+ <script>${q({mayBounce:Mo,formatPairInput:qt,parsePairScan:Lo})}</script>
20268
+ <script>${oc}</script>
20269
+ <script>${lc}</script>
20204
20270
  </body>
20205
- </html>`}function Ac(){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 Kf=`
20271
+ </html>`}function Ic(){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 Vf=`
20206
20272
  (function () {
20207
20273
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
20208
20274
  function select(tab, focus, keepHash) {
@@ -20274,7 +20340,7 @@ ${lc}
20274
20340
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
20275
20341
  }
20276
20342
  })();
20277
- `,Jf=`
20343
+ `,Yf=`
20278
20344
  (function () {
20279
20345
  var msg = document.getElementById('msg');
20280
20346
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -20291,7 +20357,7 @@ ${lc}
20291
20357
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
20292
20358
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
20293
20359
  })();
20294
- `,Vf=`
20360
+ `,Qf=`
20295
20361
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
20296
20362
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
20297
20363
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -20303,7 +20369,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
20303
20369
  .card h1 { font-size: 22px; margin: 0 0 12px; }
20304
20370
  .muted { color: var(--ax-text-2); }
20305
20371
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
20306
- `,Yf=`
20372
+ `,Zf=`
20307
20373
  body { display: flex; flex-direction: column; }
20308
20374
  .bar {
20309
20375
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -20341,8 +20407,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20341
20407
  }
20342
20408
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
20343
20409
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
20344
- `;var ia="agentx_app",eh=400*86400,th=new At,ah=new Ie;async function Cc(t,e,a,n,r={}){if(a==="/.well-known/assetlinks.json"&&n==="GET"){let i=r.assetLinks?.()??null;return i?ue(e,200,"application/json",JSON.stringify(i),"public, max-age=300"):_e(e,404,{error:"not found"})}if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new G;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ue(e,200,"application/manifest+json",Ac());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ue(e,200,"text/javascript; charset=utf-8",fn);if(a==="/app/icon-192.png")return ue(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ue(e,200,"image/png",Fe(512),"public, max-age=86400");if(a==="/app/pair")return ue(e,200,"text/html; charset=utf-8",Ec());if(a==="/app/qr.js"){let i=nh();return i?ue(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):_e(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=gn(ot(t),o);return i?(e.setHeader("Set-Cookie",xn(ot(t))),_e(e,200,{device:i.name})):_e(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await pr(t,{codes:r.pairCodes??new kt,limiter:r.pairLimiter??th,verify:l=>gn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",xn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),_e(e,i.status,i.body)}let s=gn(rh(t),o);if(!s){let i=ot(t);return(r.rejectLog??ah).record(a.slice(0,120),Bt(t,qe(vn(t,ia),o),i?qe(i,o):null)),a==="/app"?ue(e,401,"text/html; charset=utf-8",Tc()):_e(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=vn(t,ia);return i&&!ot(t)&&e.setHeader("Set-Cookie",xn(i)),ue(e,200,"text/html; charset=utf-8",Sc())}return n==="GET"&&a==="/api/app/me"?_e(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await rr(t,e,a,n,s.name,r.fleet)||r.push&&await or(t,e,a,n,s,r.push)||r.announce&&await Xi(t,e,a,n,s,r.announce)||r.chat&&await rl(t,e,a,n,s,r.chat)||r.chat&&await ll(t,e,a,n,s,r.chat)||r.voice&&await pl(t,e,a,n,s,r.voice)||r.camera&&await ml(t,e,a,n,r.camera)||r.places&&await Al(t,e,a,n,s,r.places)?!0:_e(e,404,{error:"not found"})}var rt;function nh(){if(rt!==void 0)return rt;try{let t=Zf(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
20345
- `;rt=Buffer.concat([Buffer.from(a),Qf(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),rt=null}return rt}function gn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ee(a,"app")?a:null}function xn(t){return`${ia}=${t}; Path=/; Max-Age=${eh}; HttpOnly; Secure; SameSite=Lax`}function rh(t){return ot(t)??vn(t,ia)}function ot(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function vn(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 ue(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 ue(t,e,"application/json",JSON.stringify(a))}function Ic(t){let e=de({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."})+`
20410
+ `;var ia="agentx_app",ah=400*86400,nh=new At,rh=new Ie;async function Mc(t,e,a,n,r={}){if(a==="/.well-known/assetlinks.json"&&n==="GET"){let i=r.assetLinks?.()??null;return i?ue(e,200,"application/json",JSON.stringify(i),"public, max-age=300"):_e(e,404,{error:"not found"})}if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new G;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ue(e,200,"application/manifest+json",Ic());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ue(e,200,"text/javascript; charset=utf-8",fn);if(a==="/app/icon-192.png")return ue(e,200,"image/png",Fe(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ue(e,200,"image/png",Fe(512),"public, max-age=86400");if(a==="/app/pair")return ue(e,200,"text/html; charset=utf-8",Ac());if(a==="/app/qr.js"){let i=oh();return i?ue(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):_e(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=gn(ot(t),o);return i?(e.setHeader("Set-Cookie",xn(ot(t))),_e(e,200,{device:i.name})):_e(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await mr(t,{codes:r.pairCodes??new kt,limiter:r.pairLimiter??nh,verify:l=>gn(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",xn(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),_e(e,i.status,i.body)}let s=gn(sh(t),o);if(!s){let i=ot(t);return(r.rejectLog??rh).record(a.slice(0,120),Bt(t,qe(bn(t,ia),o),i?qe(i,o):null)),a==="/app"?ue(e,401,"text/html; charset=utf-8",Cc()):_e(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=bn(t,ia);return i&&!ot(t)&&e.setHeader("Set-Cookie",xn(i)),ue(e,200,"text/html; charset=utf-8",Tc())}return n==="GET"&&a==="/api/app/me"?_e(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.push&&await ir(t,e,a,n,s,r.push)||r.announce&&await Ji(t,e,a,n,s,r.announce)||r.chat&&await sl(t,e,a,n,s,r.chat)||r.chat&&await dl(t,e,a,n,s,r.chat)||r.voice&&await ml(t,e,a,n,s,r.voice)||r.camera&&await hl(t,e,a,n,r.camera)||r.places&&await Il(t,e,a,n,s,r.places)?!0:_e(e,404,{error:"not found"})}var rt;function oh(){if(rt!==void 0)return rt;try{let t=th(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
20411
+ `;rt=Buffer.concat([Buffer.from(a),eh(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),rt=null}return rt}function gn(t,e){if(!t)return null;let a=e.verify(t);return a&&Ee(a,"app")?a:null}function xn(t){return`${ia}=${t}; Path=/; Max-Age=${ah}; HttpOnly; Secure; SameSite=Lax`}function sh(t){return ot(t)??bn(t,ia)}function ot(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function bn(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 ue(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 ue(t,e,"application/json",JSON.stringify(a))}function Lc(t){let e=de({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."})+`
20346
20412
  <div class="pl-wrap">
20347
20413
  <div id="pl-msg" class="pl-msg" role="status" aria-live="polite"></div>
20348
20414
  <form id="pl-add" class="pl-form" autocomplete="off">
@@ -20354,7 +20420,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20354
20420
  <button type="submit" class="ax-btn ax-btn--primary">Add place</button>
20355
20421
  </form>
20356
20422
  <ol id="pl-list" class="pl-list" aria-label="Places"><li class="pl-empty">Loading\u2026</li></ol>
20357
- </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:oh,scripts:`<script>${sh}</script>`})}var oh=`
20423
+ </div>`;return I({title:"AgentX \xB7 Places",activeTab:"admin",subtitle:"Places",peers:t.peers,body:e,css:ih,scripts:`<script>${lh}</script>`})}var ih=`
20358
20424
  .pl-wrap { max-width: 1040px; margin: 0 auto; padding: 0 24px 96px; box-sizing: border-box; }
20359
20425
  .pl-msg { min-height: 1.4em; margin: 8px 0 0; }
20360
20426
  .pl-msg.is-bad { color: var(--ax-red-ink); }
@@ -20377,7 +20443,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20377
20443
  .pl-rule-form { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
20378
20444
  .pl-rule-form input[name=text] { flex: 1 1 240px; }
20379
20445
  .pl-btns { margin-left: auto; display: flex; gap: 8px; }
20380
- `,sh=`
20446
+ `,lh=`
20381
20447
  (function () {
20382
20448
  var list = document.getElementById('pl-list');
20383
20449
  var msg = document.getElementById('pl-msg');
@@ -20456,7 +20522,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20456
20522
  });
20457
20523
  load();
20458
20524
  })();
20459
- `;import{randomBytes as Mc}from"crypto";var Be={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ce.perMessage},ih=/^[a-f0-9]{32}$/,lh=/^c[a-z0-9]{8,32}$/,ch=/^#[0-9a-fA-F]{6}$/;function bn(t){return lh.test(t)}var st=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
20525
+ `;import{randomBytes as Rc}from"crypto";var Be={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ce.perMessage},ch=/^[a-f0-9]{32}$/,dh=/^c[a-z0-9]{8,32}$/,ph=/^#[0-9a-fA-F]{6}$/;function vn(t){return dh.test(t)}var st=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
20460
20526
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
20461
20527
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
20462
20528
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -20469,39 +20535,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
20469
20535
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
20470
20536
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
20471
20537
  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 (
20472
- key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return bn(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)}${Mc(4).toString("hex")}`,{color:s,...i}=a,l=s&&ch.test(s)?s:void 0,c={id:o,title:ph(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
20473
- (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(!bn(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(dh);return{...Lc(n),messages:r}}list(e,a=Be.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
20538
+ key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return vn(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)}${Rc(4).toString("hex")}`,{color:s,...i}=a,l=s&&ph.test(s)?s:void 0,c={id:o,title:mh(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
20539
+ (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(!vn(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(uh);return{...Pc(n),messages:r}}list(e,a=Be.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
20474
20540
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
20475
20541
  (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
20476
- 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{...Lc(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){bn(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,
20542
+ 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{...Pc(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){vn(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,
20477
20543
  substr(m.content, 1, 240) AS answer, m.status, m.at
20478
20544
  FROM app_chat_conversations c
20479
20545
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
20480
20546
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
20481
20547
  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)+`
20482
20548
 
20483
- [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 f=m.filename.trim(),_=Kn(f);if(!_||!f||f.length>ce.pathChars||f.includes("\0"))continue;let v=(f.split(/[\\/]/).pop()||f).slice(0,120);l.push({id:Mc(16).toString("hex"),name:v,mime:_.mime,kind:_.kind,path:f})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),d=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
20549
+ [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 h=m.filename.trim(),S=Vn(h);if(!S||!h||h.length>ce.pathChars||h.includes("\0"))continue;let v=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Rc(16).toString("hex"),name:v,mime:S.mime,kind:S.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),d=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
20484
20550
  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),p=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
20485
20551
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)p.run(m.id,a,Number(d.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
20486
20552
  (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
20487
- (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(!ih.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
20553
+ (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(!ch.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
20488
20554
  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 = ?
20489
- 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 Lc(t){return{id:t.id,title:t.title,node:t.node,nodeName:t.node_name,agent:t.agent,...t.agent_name?{agentName:t.agent_name}:{},...t.color?{color:t.color}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function dh(t){let e=o=>{if(o)try{return JSON.parse(o)}catch{return}},a=e(t.ui),n=e(t.tools),r=e(t.files);return{role:t.role,content:t.content,at:t.at,...t.status?{status:t.status}:{},...t.error?{error:t.error}:{},...a?{ui:a}:{},...n?{tools:n}:{},...r?{files:r}:{}}}function ph(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var uh=4e3,yn=100,mh=15,Rc=t=>t.replace(/\/+$/,""),la=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=uh){this.timer||(this.timer=setInterval(()=>{this.tick()},e),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async tick(){if(this.running)return 0;this.running=!0;try{let e,a=!1;try{let o=await this.deps.recent(this.cursor,yn);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??mh)-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>=yn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${yn}); 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||Rc(l)!==Rc(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=fh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let p=c.row.status,m=!!this.deps.finishAlerts?.(s),f={status:p,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&ra(f)&&this.deps.notifyFinish(oa(s,i,p,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function fh(t,e){let a=t.plain?{text:xt(t.text,!1),artifacts:[]}:gt(t.text,ce.perMessage,!1),{cleanText:n,ui:r}=bt(a.text),o=t.plain?void 0:on(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:hh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function hh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}jn();function Je(){let t=ut();return t&&ke(t,"dashboard"),t}function I0(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let f of a)try{s.set(f.id,Ah(f,t))}catch(_){console.error(` Board "${f.id}" failed to initialize: ${_.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?it(process.cwd(),t.workflows.dir):void 0,c=new Un(l?{baseDir:l}:void 0),d=new Wn(l?{baseDir:l,nodeId:i}:{nodeId:i}),p=new Gn(l?{baseDir:l}:void 0);pi(t),Je(),br({business:t.business?.enabled===!0});let m=gh(async(f,_)=>{try{await _h(f,_,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:d,workflowLayouts:p})}catch(v){k(_,500,{error:v.message||"internal error"})}});Uh(t).start(),m.listen(n,r,()=>{let f=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
20490
- Live dashboard: http://${f}:${n}
20555
+ 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 Pc(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 uh(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 mh(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var fh=4e3,yn=100,hh=15,$c=t=>t.replace(/\/+$/,""),la=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=fh){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,yn);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??hh)-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>=yn&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${yn}); 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||$c(l)!==$c(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=gh(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let p=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:p,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&ra(h)&&this.deps.notifyFinish(oa(s,i,p,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function gh(t,e){let a=t.plain?{text:xt(t.text,!1),artifacts:[]}:gt(t.text,ce.perMessage,!1),{cleanText:n,ui:r}=vt(a.text),o=t.plain?void 0:on(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:xh(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function xh(t){return t.replace(/\s+/g," ").trim().slice(0,300)}jn();function Je(){let t=ut();return t&&ke(t,"dashboard"),t}function R0(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let h of a)try{s.set(h.id,Ih(h,t))}catch(S){console.error(` Board "${h.id}" failed to initialize: ${S.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?it(process.cwd(),t.workflows.dir):void 0,c=new Un(l?{baseDir:l}:void 0),d=new Wn(l?{baseDir:l,nodeId:i}:{nodeId:i}),p=new Gn(l?{baseDir:l}:void 0);mi(t),Je(),wr({business:t.business?.enabled===!0});let m=bh(async(h,S)=>{try{await Eh(h,S,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:d,workflowLayouts:p})}catch(v){k(S,500,{error:v.message||"internal error"})}});Gh(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
20556
+ Live dashboard: http://${h}:${n}
20491
20557
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
20492
- Kanban dashboard: http://${f}:${n}
20493
- `),console.log(` Boards: ${a.map(_=>_.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var kh=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 _h(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){k(e,404,{error:"not found"});return}if(xr(t.headers)==="foreign"&&vr(o)){k(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Zo(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>et(a.config.people),members:$c(a.config.members.logRetentionDays),db:()=>Je(),linkFor:(u,h)=>wo(u,h,{gitlab:a.config.channels.gitlab?.host})})||await Cc(t,e,r,o,{nodeName:a.config.node?.name,fleet:Bc(a.config),push:Tn(a.config),announce:Ki(a.config),chat:Hc(a.config),voice:Wh(a.config),camera:Gh(a.config),places:Pc(a.config),assetLinks:()=>Ll(a.config)}))return;let s=o==="GET"?vo(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"&&kh.has(r)&&Qr("page",r),o==="GET"&&r==="/"){let u=Dr();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(nn({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ni({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(nn({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Se(a.config);if(!u){k(e,503,{error:"no node available"});return}let h=await new Promise(y=>{let T="";t.on("data",b=>T+=b),t.on("end",()=>y(T)),t.on("error",()=>y(""))}),w=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:h||"{}"});e.writeHead(w.status,{"Content-Type":"application/json"}),e.end(await w.text())}catch(u){k(e,502,{error:"could not reach the node",message:String(u?.message||u)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let u=await Se(a.config),h=o==="POST"?void 0:n.searchParams.get("node"),w=o==="POST"?await me(t):void 0,y=w?.node??h,T=y?u.find(R=>R.url===y):u[0];if(!T){k(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(T.url+r+b,{method:o,headers:{"Content-Type":"application/json",...T.token?{Authorization:`Bearer ${T.token}`}:{}},...o==="POST"?{body:JSON.stringify({...w,node:void 0})}:{}});k(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){k(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 me(t),h={"Content-Type":"application/json"};a.config.dashboard.token&&(h.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/api/workflows/editor/chat`,{method:"POST",headers:h,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Se(a.config);if(!u){k(e,200,{configured:!1,workflows:[]});return}let h=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});k(e,h.status,await h.json().catch(()=>({configured:!1,workflows:[]})))}catch{k(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lo({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(io({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(no({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,h=setTimeout(()=>u.abort(),8e3);try{let w=Vn(await Se(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(w.map(async S=>{try{let L=await fetch(S.url+"/monitor",{headers:S.token?{Authorization:`Bearer ${S.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:S.name,url:S.url,ok:!0,data:await L.json()}}catch(L){return{name:S.name,url:S.url,ok:!1,error:L.message}}}));k(e,200,{nodes:R});return}let y=w.find(R=>R.url===n.searchParams.get("node"));if(!y){k(e,400,{error:"Select a known node"});return}let T=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(T)||o==="POST"&&["register","ended","action","retry","clear"].includes(T))){k(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await Jn(t)):void 0,A=await fetch(y.url+"/monitor/"+T+(T==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):T==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:u.signal,headers:{"Content-Type":"application/json",...y.token?{Authorization:`Bearer ${y.token}`}:{}}});k(e,A.status,await A.json())}catch(w){k(e,502,{error:w.message})}finally{clearTimeout(h)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ri({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ic({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pi({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 h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),w=o==="POST"?await me(t).catch(()=>({})):void 0,y=await fetch(`${h}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...w!==void 0?{body:JSON.stringify(w??{})}:{}});k(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(u){k(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(Di({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hi({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nr({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",h=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(zi({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:h,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(qi({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"){Br(t,e);return}if(o==="POST"&&r==="/api/setup"){await Hr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await zr(t,e);return}if(o==="GET"&&r==="/admin"){ds(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Ts(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){xs(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}Os(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 Qh(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await tn(t,e,r,w=>qc(w,a.config));return}let h=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(h){let w=decodeURIComponent(h[1]),y=w.indexOf("::");if(y>0){let T=w.slice(0,y),b=w.slice(y+2),A=a.config.node?.id||a.config.node?.name||"local";if(T===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let R=(a.config.dashboard?.daemons||[]).find(S=>(S.name||S.url)===T);if(R){let S=lt(R.url.replace(/\/+$/,""),a.config);if(S){await Oc(t,e,S,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}k(e,404,{error:`unknown node "${T}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let h=lt(u,a.config);if(!h){k(e,404,{error:`unknown peer: ${u}`});return}let w=(n.search||"").replace(/[?&]peer=[^&]*/g,T=>T.startsWith("?")?"?":"");await Oc(t,e,h,r+(w==="?"?"":w));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ns(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Zh(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-G5TM5GVF.js"),w=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",y=await u({running:w});k(e,200,y)}catch(u){k(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(zs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Hs(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qs({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fs({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 Mh(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 ui(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await tn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await fi(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){xi(t,e,d[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let u=t.headers.authorization||"",h=u.startsWith("Bearer ")?u.slice(7):"";if(h!==a.token){let w=new G,y=h?w.verify(h):null;if(!y||!Ee(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ps(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){k(e,200,kr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await As(t,e,r,n);return}if(await Is(t,e,r,{people:()=>et(a.config.people),members:$c(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Je(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await vs(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await vi(t,e,r);return}if(r.startsWith("/api/admin/")){await us(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)){k(e,400,{error:"invalid asset name"});return}let h=Vh("web/"+u);try{let w=await Yh(h),y=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",T=n.searchParams.has("v");e.writeHead(200,{"Content-Type":y,"Cache-Control":T?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(w)}catch{k(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Ve(a.config);k(e,200,u)}catch(u){k(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),h=n.searchParams.get("timezone")||"UTC",w=await Ve(a.config,{date:u,timezone:h});k(e,200,w)}catch(u){k(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(h,w,y,T)=>{let b=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(b)?Math.max(y,Math.min(T,b)):w};try{let h=await Se(a.config);k(e,200,await $i(h,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(h){k(e,502,{error:h.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let u=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(u)){k(e,400,{error:"day=YYYY-MM-DD query param required"});return}let h=(w,y,T,b)=>{let A=parseInt(n.searchParams.get(w)||"",10);return Number.isFinite(A)?Math.max(T,Math.min(b,A)):y};try{let w=await Se(a.config);k(e,200,await Oi(w,{day:u,tzOffsetMinutes:h("tzOffset",0,-840,840),limit:h("limit",40,1,200)}))}catch(w){k(e,502,{error:w.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){k(e,400,{error:"node query param required"});return}let h=n.searchParams,w;if(r==="/api/mesh/thread"){let[y,T,b]=[h.get("agent"),h.get("channel"),h.get("chat")];if(!y||!T||!b){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/thread?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(h.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[y,T]=[h.get("kind"),h.get("key")];if(!y||!T){k(e,400,{error:"kind and key required"});return}w=`/analytics/job?kind=${encodeURIComponent(y)}&key=${encodeURIComponent(T)}&limit=${encodeURIComponent(h.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[y,T,b]=[h.get("agent"),h.get("channel"),h.get("chat")];if(!y||!T||!b){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/conversation?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(h.get("tzOffset")||"0")}`}else{let y=h.get("task");if(!y){k(e,400,{error:"task required"});return}w=`/analytics/run/${encodeURIComponent(y)}`}try{await ji(e,await Se(a.config),u,w)}catch(y){k(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){Nh(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task");if(!h||!w||!y){k(e,400,{error:"node, agent, task query params required"});return}await Dh(t,e,a,h,w,y);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task"),T=u.searchParams.get("limit")||"50";if(!h||!w){k(e,400,{error:"node and agent query params required"});return}await zh(e,a,h,w,y,T);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),h=u.searchParams.get("node"),w=u.searchParams.get("task"),y=u.searchParams.get("kind");if(!h||!w||y!=="cancel"&&y!=="followup"){k(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await qh(t,e,a,h,w,y);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await En(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 h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:u});if(!h.ok)throw new Error(`HTTP ${h.status}`);let w=await h.json();k(e,200,w)}catch(u){k(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 h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:u});if(!h.ok){k(e,h.status,{error:`HTTP ${h.status}`});return}k(e,200,await h.json())}catch(u){k(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await me(t);try{let h=await Kh(a.config,u);k(e,200,h)}catch(h){k(e,502,{error:h.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!Bh(t,e,[`agent:${u}`]))return;await Hh(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 h=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:u,signal:AbortSignal.timeout(3e3)});if(!h.ok)throw new Error(`HTTP ${h.status}`);k(e,200,wr(await h.json()))}catch(u){k(e,502,{error:u.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let u=t.headers.authorization||"",h=u.startsWith("Bearer ")?u.slice(7):"";if(h!==a.token){let w=new G,y=h?w.verify(h):null;if(!y||!Ee(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Lh(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"){k(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(await Cl(t,e,r,o,Pc(a.config)))return;if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await En(t,e,a,u,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let h=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let w=[{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},T=[];t.on("close",()=>{y.flag=!0;for(let A of T)try{A.abort()}catch{}});let b=setInterval(()=>{if(!y.flag)try{e.write(`: ping
20558
+ Kanban dashboard: http://${h}:${n}
20559
+ `),console.log(` Boards: ${a.map(S=>S.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Sh=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 Eh(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){k(e,404,{error:"not found"});return}if(vr(t.headers)==="foreign"&&yr(o)){k(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ts(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>et(a.config.people),members:Oc(a.config.members.logRetentionDays),db:()=>Je(),linkFor:(u,f)=>_o(u,f,{gitlab:a.config.channels.gitlab?.host})})||await Mc(t,e,r,o,{nodeName:a.config.node?.name,fleet:zc(a.config),push:Tn(a.config),announce:Vi(a.config),chat:qc(a.config),voice:Xh(a.config),camera:Kh(a.config),places:jc(a.config),assetLinks:()=>Pl(a.config)}))return;let s=o==="GET"?yo(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"&&Sh.has(r)&&eo("page",r),o==="GET"&&r==="/"){let u=Hr();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(nn({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bi({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(nn({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[u]=await Se(a.config);if(!u){k(e,503,{error:"no node available"});return}let f=await new Promise(y=>{let T="";t.on("data",g=>T+=g),t.on("end",()=>y(T)),t.on("error",()=>y(""))}),w=await fetch(u.url+r,{method:"POST",headers:{"Content-Type":"application/json",...u.token?{Authorization:`Bearer ${u.token}`}:{}},body:f||"{}"});e.writeHead(w.status,{"Content-Type":"application/json"}),e.end(await w.text())}catch(u){k(e,502,{error:"could not reach the node",message:String(u?.message||u)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let u=await Se(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),w=o==="POST"?await me(t):void 0,y=w?.node??f,T=y?u.find(R=>R.url===y):u[0];if(!T){k(e,400,{error:"unknown node"});return}let g=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",A=await fetch(T.url+r+g,{method:o,headers:{"Content-Type":"application/json",...T.token?{Authorization:`Bearer ${T.token}`}:{}},...o==="POST"?{body:JSON.stringify({...w,node:void 0})}:{}});k(e,A.status,await A.json().catch(()=>({error:`HTTP ${A.status}`})))}catch(u){k(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 me(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[u]=await Se(a.config);if(!u){k(e,200,{configured:!1,workflows:[]});return}let f=await fetch(u.url+"/api/n8n/workflows",{headers:u.token?{Authorization:`Bearer ${u.token}`}:{}});k(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{k(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(po({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(co({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(oo({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let u=new AbortController,f=setTimeout(()=>u.abort(),8e3);try{let w=Qn(await Se(a.config,u.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let R=await Promise.all(w.map(async _=>{try{let L=await fetch(_.url+"/monitor",{headers:_.token?{Authorization:`Bearer ${_.token}`}:{},signal:u.signal});if(!L.ok)throw new Error(`HTTP ${L.status}`);return{name:_.name,url:_.url,ok:!0,data:await L.json()}}catch(L){return{name:_.name,url:_.url,ok:!1,error:L.message}}}));k(e,200,{nodes:R});return}let y=w.find(R=>R.url===n.searchParams.get("node"));if(!y){k(e,400,{error:"Select a known node"});return}let T=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(T)||o==="POST"&&["register","ended","action","retry","clear"].includes(T))){k(e,405,{error:"Unknown monitor operation"});return}let g=o==="POST"?JSON.stringify(await Yn(t)):void 0,A=await fetch(y.url+"/monitor/"+T+(T==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):T==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:g,signal:u.signal,headers:{"Content-Type":"application/json",...y.token?{Authorization:`Bearer ${y.token}`}:{}}});k(e,A.status,await A.json())}catch(w){k(e,502,{error:w.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($i({peers:D(a.config)}));return}if(o==="GET"&&r==="/places"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lc({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ji({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(/\/+$/,""),w=o==="POST"?await me(t).catch(()=>({})):void 0,y=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:u,...w!==void 0?{body:JSON.stringify(w??{})}:{}});k(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(u){k(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(Hi({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zi({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qi({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Br({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let u=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!u){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fi({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(Ui({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"){zr(t,e);return}if(o==="POST"&&r==="/api/setup"){await qr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Fr(t,e);return}if(o==="GET"&&r==="/admin"){us(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Cs(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){vs(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}Ds(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 eg(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await tn(t,e,r,w=>Uc(w,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let w=decodeURIComponent(f[1]),y=w.indexOf("::");if(y>0){let T=w.slice(0,y),g=w.slice(y+2),A=a.config.node?.id||a.config.node?.name||"local";if(T===A)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(g)}`;else{let R=(a.config.dashboard?.daemons||[]).find(_=>(_.name||_.url)===T);if(R){let _=lt(R.url.replace(/\/+$/,""),a.config);if(_){await Dc(t,e,_,`/api/admin/activity-graph/dispatch/${encodeURIComponent(g)}`);return}}k(e,404,{error:`unknown node "${T}" in fleet dispatch id`});return}}}}else if(u&&u!=="primary"){let f=lt(u,a.config);if(!f){k(e,404,{error:`unknown peer: ${u}`});return}let w=(n.search||"").replace(/[?&]peer=[^&]*/g,T=>T.startsWith("?")?"?":"");await Dc(t,e,f,r+(w==="?"?"":w));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Bs(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await tg(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:u}=await import("./doctor-AU5TCOSG.js"),w=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",y=await u({running:w});k(e,200,y)}catch(u){k(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(Fs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await qs(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Us({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ws({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 Rh(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 fi(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await tn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await gi(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){vi(t,e,d[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 w=new G,y=f?w.verify(f):null;if(!y||!Ee(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await ms(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){k(e,200,Sr()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Is(t,e,r,n);return}if(await Ls(t,e,r,{people:()=>et(a.config.people),members:Oc(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Je(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await ys(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await yi(t,e,r);return}if(r.startsWith("/api/admin/")){await fs(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(as);return}if(o==="GET"&&r.startsWith("/assets/")){let u=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(u)){k(e,400,{error:"invalid asset name"});return}let f=Qh("web/"+u);try{let w=await Zh(f),y=u.endsWith(".map")?"application/json; charset=utf-8":u.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",T=n.searchParams.has("v");e.writeHead(200,{"Content-Type":y,"Cache-Control":T?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(w)}catch{k(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let u=await Ve(a.config);k(e,200,u)}catch(u){k(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",w=await Ve(a.config,{date:u,timezone:f});k(e,200,w)}catch(u){k(e,502,{error:u.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let u=(f,w,y,T)=>{let g=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(g)?Math.max(y,Math.min(T,g)):w};try{let f=await Se(a.config);k(e,200,await Oi(f,{days:u("days",30,0,180),tzOffsetMinutes:u("tzOffset",0,-840,840),limit:u("limit",60,1,200)}))}catch(f){k(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)){k(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(w,y,T,g)=>{let A=parseInt(n.searchParams.get(w)||"",10);return Number.isFinite(A)?Math.max(T,Math.min(g,A)):y};try{let w=await Se(a.config);k(e,200,await Di(w,{day:u,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(w){k(e,502,{error:w.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){k(e,400,{error:"node query param required"});return}let f=n.searchParams,w;if(r==="/api/mesh/thread"){let[y,T,g]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!y||!T||!g){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/thread?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(g)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[y,T]=[f.get("kind"),f.get("key")];if(!y||!T){k(e,400,{error:"kind and key required"});return}w=`/analytics/job?kind=${encodeURIComponent(y)}&key=${encodeURIComponent(T)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[y,T,g]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!y||!T||!g){k(e,400,{error:"agent, channel, chat required"});return}w=`/analytics/conversation?agent=${encodeURIComponent(y)}&channel=${encodeURIComponent(T)}&chat=${encodeURIComponent(g)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let y=f.get("task");if(!y){k(e,400,{error:"task required"});return}w=`/analytics/run/${encodeURIComponent(y)}`}try{await Ni(e,await Se(a.config),u,w)}catch(y){k(e,502,{error:y.message})}return}if(o==="GET"&&r==="/api/live/stream"){Bh(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"),w=u.searchParams.get("agent"),y=u.searchParams.get("task");if(!f||!w||!y){k(e,400,{error:"node, agent, task query params required"});return}await Hh(t,e,a,f,w,y);return}if(o==="GET"&&r==="/api/task/history"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),w=u.searchParams.get("agent"),y=u.searchParams.get("task"),T=u.searchParams.get("limit")||"50";if(!f||!w){k(e,400,{error:"node and agent query params required"});return}await Fh(e,a,f,w,y,T);return}if(o==="POST"&&r==="/api/task/action"){let u=new URL(t.url||"/","http://localhost"),f=u.searchParams.get("node"),w=u.searchParams.get("task"),y=u.searchParams.get("kind");if(!f||!w||y!=="cancel"&&y!=="followup"){k(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Uh(t,e,a,f,w,y);return}if(o==="POST"&&r==="/api/voice/stop"){let u=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await En(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 w=await f.json();k(e,200,w)}catch(u){k(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){k(e,f.status,{error:`HTTP ${f.status}`});return}k(e,200,await f.json())}catch(u){k(e,502,{error:u.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let u=await me(t);try{let f=await Vh(a.config,u);k(e,200,f)}catch(f){k(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let u=p[1];if(!zh(t,e,[`agent:${u}`]))return;await qh(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}`);k(e,200,_r(await f.json()))}catch(u){k(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 w=new G,y=f?w.verify(f):null;if(!y||!Ee(y,"dashboard:write")){k(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Ph(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"){k(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(await Ml(t,e,r,o,jc(a.config)))return;if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let u=n.searchParams.get("node");if(!u){k(e,400,{error:"node query param required"});return}await En(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 w=[{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},T=[];t.on("close",()=>{y.flag=!0;for(let A of T)try{A.abort()}catch{}});let g=setInterval(()=>{if(!y.flag)try{e.write(`: ping
20494
20560
 
20495
- `)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let A of w)(async()=>{let R={Accept:"text/event-stream"};A.token&&(R.Authorization=`Bearer ${A.token}`);let S=new AbortController;T.push(S);try{let L=await fetch(`${A.url.replace(/\/+$/,"")}/events${h?`?${h}`:""}`,{headers:R,signal:S.signal});if(!L.ok||!L.body)return;let j=L.body.getReader(),$=new TextDecoder,O="";for(;!y.flag;){let{done:W,value:le}=await j.read();if(W)break;O+=$.decode(le,{stream:!0});let Q;for(;(Q=O.indexOf(`
20561
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(g));for(let A of w)(async()=>{let R={Accept:"text/event-stream"};A.token&&(R.Authorization=`Bearer ${A.token}`);let _=new AbortController;T.push(_);try{let L=await fetch(`${A.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:R,signal:_.signal});if(!L.ok||!L.body)return;let j=L.body.getReader(),$=new TextDecoder,O="";for(;!y.flag;){let{done:W,value:le}=await j.read();if(W)break;O+=$.decode(le,{stream:!0});let Q;for(;(Q=O.indexOf(`
20496
20562
 
20497
20563
  `))>=0;){let re=O.slice(0,Q);if(O=O.slice(Q+2),y.flag)break;try{e.write(re+`
20498
20564
 
20499
- `)}catch{y.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let u=new URL(t.url||"/","http://localhost"),h=Math.max(1,Math.min(500,Number(u.searchParams.get("limit")||50))),w=u.searchParams.get("workflowId")||void 0,y=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",T=a.workflowRuns.list({limit:h,workflowId:w}),b=`?limit=${h}${w?`&workflowId=${encodeURIComponent(w)}`:""}${y?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],R=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let W=new AbortController,le=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let re=await Q.json();return Array.isArray(re.runs)?re.runs:[]}finally{clearTimeout(le)}}catch{return[]}})),S=new Map;for(let $ of T)S.set($.id,$);for(let $ of R)for(let O of $)S.set(O.id,O);let L=Array.from(S.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,h),j=y?L.map($=>Th($)):L;k(e,200,{runs:j})}catch(u){k(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let u=decodeURIComponent(f[1]),h=a.workflowRuns.get(u);if(h){k(e,200,{run:h});return}let w=[{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 w)try{let T={};y.token&&(T.Authorization=`Bearer ${y.token}`);let b=await fetch(`${y.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:T});if(b.ok){k(e,200,await b.json());return}}catch{}k(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 h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),w=await fetch(`${h}/api/actions/builtin`,{headers:u}),y=await w.json().catch(()=>({error:`HTTP ${w.status}`}));k(e,w.status,y)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let _=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(_){try{let u=await me(t).catch(()=>({})),h={"Content-Type":"application/json"};a.config.dashboard.token&&(h.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/workflows/${encodeURIComponent(_[1])}/run`,{method:"POST",headers:h,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(r.startsWith("/api/workflows")&&Ui(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(h,w,y)=>{if(a.token)return!0;let T=ka(h);if(!T)return!0;let b=new G().verify(T);if(!b)return k(w,401,{error:"invalid or revoked token"}),!1;for(let A of y)if(!Ee(b,A))return k(w,403,{error:`token missing scope: ${A}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){k(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 v=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(v&&o==="GET"){let u=a.sources.get(v[1]);if(!u){k(e,404,{error:"unknown board"});return}try{let h=typeof u.listMembers=="function"?await u.listMembers():[];k(e,200,h)}catch(h){k(e,502,{error:h.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(E&&o==="GET"){let u=a.sources.get(E[1]);if(!u){k(e,404,{error:"unknown board"});return}try{let h=typeof u.listMilestones=="function"?await u.listMilestones():[];k(e,200,h)}catch(h){k(e,502,{error:h.message})}return}let x=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(x&&o==="PATCH"){let[,u,h]=x,w=decodeURIComponent(h),y=a.boards.find(S=>S.id===u);if(!y){k(e,404,{error:`unknown board: ${u}`});return}let T=a.sources.get(u);if(!T){k(e,503,{error:`board "${u}" source unavailable`});return}let b=await me(t),A=y.columns.find(S=>S.id===b.to),R=y.columns.find(S=>S.id===b.from);if(!A){k(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await Eh(T,w,R,A),wn({actor:kn(t),action:"move",boardId:u,itemId:w,payload:{from:b.from,to:b.to}}),k(e,200,{ok:!0})}catch(S){k(e,502,{error:S.message||"transition failed"})}return}if(g){let[,u,h]=g,w=h?decodeURIComponent(h):void 0,y=a.boards.find(b=>b.id===u);if(!y){k(e,404,{error:`unknown board: ${u}`});return}let T=a.sources.get(u);if(!T){k(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!w){let{columns:b,totals:A}=await Sh(y,T,n.searchParams);k(e,200,{columns:b,totals:A});return}if(o==="GET"&&w){try{let b=typeof T.getItem=="function"?await T.getItem(w):null;if(!b){k(e,404,{error:"not found"});return}k(e,200,b)}catch(b){k(e,502,{error:b.message})}return}if(o==="PATCH"&&w){let b=await me(t);try{let A=typeof T.updateItem=="function"?await T.updateItem(w,b):null;if(!A){k(e,501,{error:"update unsupported"});return}wn({actor:kn(t),action:"update",boardId:u,itemId:w,payload:b}),k(e,200,A)}catch(A){k(e,502,{error:A.message})}return}if(o==="POST"&&!w){let b=await me(t);if(!b.title){k(e,400,{error:"title required"});return}if(!T.capabilities.create||!T.create){k(e,400,{error:`source ${T.type} does not support create`});return}try{let A=await T.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});wn({actor:kn(t),action:"create",boardId:u,itemId:A.id,payload:{title:b.title}}),k(e,201,A)}catch(A){k(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),w={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(w){e.writeHead(302,{Location:w}),e.end();return}}k(e,404,{error:"not found",path:r})}async function Sh(t,e,a){if(!e.capabilities.listAll||!e.listAll){let g={};for(let u of t.columns)g[u.id]=[];return{columns:g,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),d=t.columns.some(g=>g.kind!=="closed"),p=t.columns.some(g=>g.kind==="closed"),m=d?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],f=p?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let g of t.columns)_[g.id]=[];let v=t.columns.find(g=>g.kind==="closed");for(let g of f)v&&_[v.id].push({...g,stage:v.id});let E=t.columns.filter(g=>g.kind!=="closed");for(let g of m){let u=In(g,E);if(!u)continue;let h=_[u];h&&h.push({...g,stage:u})}if(i)for(let g of Object.keys(_))_[g]=_[g].filter(u=>u.assignee===i);for(let g of Object.keys(_))_[g].sort((u,h)=>{let w=(u.priority??99)-(h.priority??99);return w!==0?w:(h.updatedAt||"").localeCompare(u.updatedAt||"")});let x=Object.fromEntries(Object.entries(_).map(([g,u])=>[g,u.length]));return{columns:_,totals:x}}async function Eh(t,e,a,n){let r=Mn(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 Th(t){return{id:t.id,workflowId:t.workflowId,workflowVersion:t.workflowVersion,homeNode:t.homeNode,status:t.status,pending:t.pending,entityRef:t.entityRef,history:(t.history||[]).slice(-5),parentRunId:t.parentRunId,parentNodeId:t.parentNodeId,rootRunId:t.rootRunId,depth:t.depth,createdAt:t.createdAt,updatedAt:t.updatedAt}}function Ah(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 Ar(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function wn(t){try{let e=it(process.cwd(),".agentx");Nc(e)||vh(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
20500
- `;xh(it(e,"board-audit.jsonl"),a)}catch{}}function kn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Ch=2e3;async function Ih(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=x=>{let g=new AbortController,u=setTimeout(()=>g.abort(),Ch),h=()=>g.abort();return a?.addEventListener("abort",h,{once:!0}),fetch(t+x,{headers:r,signal:g.signal}).then(async w=>{let y=w.ok?await w.json().catch(()=>{}):void 0;return{ok:y!==void 0,json:async()=>y}}).catch(()=>null).finally(()=>{clearTimeout(u),a?.removeEventListener("abort",h)})},[l,c,d,p,m,f,_,v]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let E=await c.json();if(o.agents=E.map(x=>({id:x.id,name:x.name,tier:x.tier,model:x.model,...typeof x.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(x.color)?{color:x.color}:{},skillCount:Number.isFinite(x.skillCount)?x.skillCount:void 0,active:x.active||0,total:x.total||0,errors:x.errors||0,lastActive:x.lastActive,lastSummary:x.lastSummary,hourlyTasks:Array.isArray(x.hourlyTasks)?x.hourlyTasks:void 0,runningTasks:Array.isArray(x.runningTasks)?x.runningTasks:[]})),l&&l.ok){let x=await l.json().catch(()=>({}));o.uptimeSec=x.uptime,typeof x.inflight?.total=="number"&&(o.inflight=x.inflight.total),x.restart&&typeof x.restart.state=="string"&&(o.restart=x.restart),o.name=x.node?.name||x.node?.id||t,o.id=x.node?.id||t,x.usage&&(o.usage=x.usage)}if(p&&p.ok){let x=await p.json().then(g=>Array.isArray(g)?g:[],()=>[]);o.crons=x.map(g=>({id:g.id,enabled:g.enabled===!0,schedule:String(g.schedule||""),timezone:g.timezone,agent:String(g.agent||""),kind:typeof g.command=="string"&&g.command.trim()?"command":"agent",model:g.model,nextRun:g.nextRun,retryPending:g.retryPending===!0,consecutiveErrors:Number(g.consecutiveErrors)||0}))}if(m&&m.ok){let x=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(x.runs)?x.runs:[]}if(_&&_.ok){let x=await _.json().catch(()=>null);x&&Array.isArray(x.routines)&&(o.routines=x.routines.slice(0,Zn.routines))}if(f&&f.ok){let x=await f.json().catch(()=>null);x?.active&&x.kind==="lesson"&&(o.lesson={agentId:x.agentId??null,mode:String(x.mode||"teach"),goal:String(x.goal||""),step:Number(x.step)||0,saying:String(x.saying||""),startedAt:String(x.startedAt||"")})}if(v&&v.ok){let x=await v.json().catch(()=>null);x&&Array.isArray(x.sessions)&&Oh(o,x.sessions,x.saved??{})}o.reachable=!0,o._peers=Array.isArray(d?.ok?await d.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var ca=null;function Mh(t){if(ca)return ca;let e=it(process.cwd(),".agentx/wiki");return ca=to({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),ca}async function pa(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 Lh(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){k(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();k(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){k(t,502,{error:s.message||"daemon unreachable"})}}async function Se(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await pa(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 Rh=3e3,Ph=6e3,$h=5*6e4,Sn=new Map,da=new Map;function Ve(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=da.get(a);if(n)return n;let r=(async()=>{let o=await Se(t,AbortSignal.timeout(Rh)),s=await Promise.all(o.map(async i=>{let l=await Ih(i.url,i.token,AbortSignal.timeout(Ph),e);return e?l:jh(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>da.delete(a));return da.set(a,r),r}function jh(t,e,a=Date.now()){if(e.reachable&&!e.error)return Sn.set(t,{node:e,at:a}),e;let n=Sn.get(t);return!n||a-n.at>$h?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function M0(){Sn.clear(),da.clear()}function Oh(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 Nh(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}
20565
+ `)}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(g=>({url:g.url,token:g.token}))],f=[],w=await Promise.all(u.map(async g=>{let A={};g.token&&(A.Authorization=`Bearer ${g.token}`);try{let R=await fetch(`${g.url.replace(/\/+$/,"")}/api/workflows/runs?limit=500&summary=1`,{headers:A,signal:AbortSignal.timeout(5e3)});if(!R.ok)return f.push(g.url),[];let _=await R.json();return Array.isArray(_.runs)?_.runs:[]}catch{return f.push(g.url),[]}})),y=new Map;for(let g of a.workflowRuns.list({limit:500}))y.set(g.id,g);for(let g of w)for(let A of g)y.set(A.id,{...A,history:A.history??[],pending:A.pending??[]});let T=new Map(a.workflowStore.list().map(g=>[g.id,g.title]));k(e,200,{groups:Jn([...y.values()],g=>T.get(g)),unreachable:f});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))),w=u.searchParams.get("workflowId")||void 0,y=u.searchParams.get("summary")==="1"||u.searchParams.get("summary")==="true",T=a.workflowRuns.list({limit:f,workflowId:w}),g=`?limit=${f}${w?`&workflowId=${encodeURIComponent(w)}`:""}${y?"&summary=1":""}`,A=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map($=>({url:$.url,token:$.token}))],R=await Promise.all(A.map(async $=>{let O={};$.token&&(O.Authorization=`Bearer ${$.token}`);try{let W=new AbortController,le=setTimeout(()=>W.abort(),5e3);try{let Q=await fetch(`${$.url.replace(/\/+$/,"")}/api/workflows/runs${g}`,{headers:O,signal:W.signal});if(!Q.ok)return[];let re=await Q.json();return Array.isArray(re.runs)?re.runs:[]}finally{clearTimeout(le)}}catch{return[]}})),_=new Map;for(let $ of T)_.set($.id,$);for(let $ of R)for(let O of $)_.set(O.id,O);let L=Array.from(_.values()).sort(($,O)=>$.updatedAt<O.updatedAt?1:-1).slice(0,f),j=y?L.map($=>Ch($)):L;k(e,200,{runs:j})}catch(u){k(e,502,{error:"runs fetch failed",message:u.message||String(u)})}return}let h=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(h){let u=decodeURIComponent(h[1]),f=a.workflowRuns.get(u);if(f){k(e,200,{run:f});return}let w=[{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 w)try{let T={};y.token&&(T.Authorization=`Bearer ${y.token}`);let g=await fetch(`${y.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(u)}`,{headers:T});if(g.ok){k(e,200,await g.json());return}}catch{}k(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(/\/+$/,""),w=await fetch(`${f}/api/actions/builtin`,{headers:u}),y=await w.json().catch(()=>({error:`HTTP ${w.status}`}));k(e,w.status,y)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}let S=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(S){try{let u=await me(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let w=a.config.dashboard.daemonUrl.replace(/\/+$/,""),y=await fetch(`${w}/workflows/${encodeURIComponent(S[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(u??{})}),T=await y.json().catch(()=>({error:`HTTP ${y.status}`}));k(e,y.status,T)}catch(u){k(e,502,{error:"daemon unreachable",message:u.message||String(u)})}return}if(r.startsWith("/api/workflows")&&Gi(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,w,y)=>{if(a.token)return!0;let T=ka(f);if(!T)return!0;let g=new G().verify(T);if(!g)return k(w,401,{error:"invalid or revoked token"}),!1;for(let A of y)if(!Ee(g,A))return k(w,403,{error:`token missing scope: ${A}`,scopes:g.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){k(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 v=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(v&&o==="GET"){let u=a.sources.get(v[1]);if(!u){k(e,404,{error:"unknown board"});return}try{let f=typeof u.listMembers=="function"?await u.listMembers():[];k(e,200,f)}catch(f){k(e,502,{error:f.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(E&&o==="GET"){let u=a.sources.get(E[1]);if(!u){k(e,404,{error:"unknown board"});return}try{let f=typeof u.listMilestones=="function"?await u.listMilestones():[];k(e,200,f)}catch(f){k(e,502,{error:f.message})}return}let b=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),x=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(b&&o==="PATCH"){let[,u,f]=b,w=decodeURIComponent(f),y=a.boards.find(_=>_.id===u);if(!y){k(e,404,{error:`unknown board: ${u}`});return}let T=a.sources.get(u);if(!T){k(e,503,{error:`board "${u}" source unavailable`});return}let g=await me(t),A=y.columns.find(_=>_.id===g.to),R=y.columns.find(_=>_.id===g.from);if(!A){k(e,400,{error:`unknown 'to' column: ${g.to}`});return}try{await Ah(T,w,R,A),wn({actor:kn(t),action:"move",boardId:u,itemId:w,payload:{from:g.from,to:g.to}}),k(e,200,{ok:!0})}catch(_){k(e,502,{error:_.message||"transition failed"})}return}if(x){let[,u,f]=x,w=f?decodeURIComponent(f):void 0,y=a.boards.find(g=>g.id===u);if(!y){k(e,404,{error:`unknown board: ${u}`});return}let T=a.sources.get(u);if(!T){k(e,503,{error:`board "${u}" source unavailable`});return}if(o==="GET"&&!w){let{columns:g,totals:A}=await Th(y,T,n.searchParams);k(e,200,{columns:g,totals:A});return}if(o==="GET"&&w){try{let g=typeof T.getItem=="function"?await T.getItem(w):null;if(!g){k(e,404,{error:"not found"});return}k(e,200,g)}catch(g){k(e,502,{error:g.message})}return}if(o==="PATCH"&&w){let g=await me(t);try{let A=typeof T.updateItem=="function"?await T.updateItem(w,g):null;if(!A){k(e,501,{error:"update unsupported"});return}wn({actor:kn(t),action:"update",boardId:u,itemId:w,payload:g}),k(e,200,A)}catch(A){k(e,502,{error:A.message})}return}if(o==="POST"&&!w){let g=await me(t);if(!g.title){k(e,400,{error:"title required"});return}if(!T.capabilities.create||!T.create){k(e,400,{error:`source ${T.type} does not support create`});return}try{let A=await T.create({title:g.title,description:g.description,labels:g.labels,assigneeUsernames:g.assigneeUsernames,milestoneTitle:g.milestoneTitle,projectHint:g.projectHint});wn({actor:kn(t),action:"create",boardId:u,itemId:A.id,payload:{title:g.title}}),k(e,201,A)}catch(A){k(e,502,{error:A.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let u=r.replace(/^\/+|\/+$/g,""),w={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[u];if(w){e.writeHead(302,{Location:w}),e.end();return}}k(e,404,{error:"not found",path:r})}async function Th(t,e,a){if(!e.capabilities.listAll||!e.listAll){let x={};for(let u of t.columns)x[u.id]=[];return{columns:x,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),d=t.columns.some(x=>x.kind!=="closed"),p=t.columns.some(x=>x.kind==="closed"),m=d?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=p?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],S={};for(let x of t.columns)S[x.id]=[];let v=t.columns.find(x=>x.kind==="closed");for(let x of h)v&&S[v.id].push({...x,stage:v.id});let E=t.columns.filter(x=>x.kind!=="closed");for(let x of m){let u=In(x,E);if(!u)continue;let f=S[u];f&&f.push({...x,stage:u})}if(i)for(let x of Object.keys(S))S[x]=S[x].filter(u=>u.assignee===i);for(let x of Object.keys(S))S[x].sort((u,f)=>{let w=(u.priority??99)-(f.priority??99);return w!==0?w:(f.updatedAt||"").localeCompare(u.updatedAt||"")});let b=Object.fromEntries(Object.entries(S).map(([x,u])=>[x,u.length]));return{columns:S,totals:b}}async function Ah(t,e,a,n){let r=Mn(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 Ch(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:Kn(t.pausedAt)}:{},createdAt:t.createdAt,updatedAt:t.updatedAt}}function Ih(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 Ir(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function wn(t){try{let e=it(process.cwd(),".agentx");Bc(e)||yh(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
20566
+ `;vh(it(e,"board-audit.jsonl"),a)}catch{}}function kn(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Mh=2e3;async function Lh(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=b=>{let x=new AbortController,u=setTimeout(()=>x.abort(),Mh),f=()=>x.abort();return a?.addEventListener("abort",f,{once:!0}),fetch(t+b,{headers:r,signal:x.signal}).then(async w=>{let y=w.ok?await w.json().catch(()=>{}):void 0;return{ok:y!==void 0,json:async()=>y}}).catch(()=>null).finally(()=>{clearTimeout(u),a?.removeEventListener("abort",f)})},[l,c,d,p,m,h,S,v]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let E=await c.json();if(o.agents=E.map(b=>({id:b.id,name:b.name,tier:b.tier,model:b.model,...typeof b.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(b.color)?{color:b.color}:{},skillCount:Number.isFinite(b.skillCount)?b.skillCount:void 0,active:b.active||0,total:b.total||0,errors:b.errors||0,lastActive:b.lastActive,lastSummary:b.lastSummary,hourlyTasks:Array.isArray(b.hourlyTasks)?b.hourlyTasks:void 0,runningTasks:Array.isArray(b.runningTasks)?b.runningTasks:[]})),l&&l.ok){let b=await l.json().catch(()=>({}));o.uptimeSec=b.uptime,typeof b.inflight?.total=="number"&&(o.inflight=b.inflight.total),b.restart&&typeof b.restart.state=="string"&&(o.restart=b.restart),o.name=b.node?.name||b.node?.id||t,o.id=b.node?.id||t,b.usage&&(o.usage=b.usage)}if(p&&p.ok){let b=await p.json().then(x=>Array.isArray(x)?x:[],()=>[]);o.crons=b.map(x=>({id:x.id,enabled:x.enabled===!0,schedule:String(x.schedule||""),timezone:x.timezone,agent:String(x.agent||""),kind:typeof x.command=="string"&&x.command.trim()?"command":"agent",model:x.model,nextRun:x.nextRun,retryPending:x.retryPending===!0,consecutiveErrors:Number(x.consecutiveErrors)||0}))}if(m&&m.ok){let b=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(b.runs)?b.runs:[]}if(S&&S.ok){let b=await S.json().catch(()=>null);b&&Array.isArray(b.routines)&&(o.routines=b.routines.slice(0,tr.routines))}if(h&&h.ok){let b=await h.json().catch(()=>null);b?.active&&b.kind==="lesson"&&(o.lesson={agentId:b.agentId??null,mode:String(b.mode||"teach"),goal:String(b.goal||""),step:Number(b.step)||0,saying:String(b.saying||""),startedAt:String(b.startedAt||"")})}if(v&&v.ok){let b=await v.json().catch(()=>null);b&&Array.isArray(b.sessions)&&Dh(o,b.sessions,b.saved??{})}o.reachable=!0,o._peers=Array.isArray(d?.ok?await d.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var ca=null;function Rh(t){if(ca)return ca;let e=it(process.cwd(),".agentx/wiki");return ca=no({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),ca}async function pa(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 Ph(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){k(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();k(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){k(t,502,{error:s.message||"daemon unreachable"})}}async function Se(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await pa(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 $h=3e3,jh=6e3,Oh=5*6e4,Sn=new Map,da=new Map;function Ve(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=da.get(a);if(n)return n;let r=(async()=>{let o=await Se(t,AbortSignal.timeout($h)),s=await Promise.all(o.map(async i=>{let l=await Lh(i.url,i.token,AbortSignal.timeout(jh),e);return e?l:Nh(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>da.delete(a));return da.set(a,r),r}function Nh(t,e,a=Date.now()){if(e.reachable&&!e.error)return Sn.set(t,{node:e,at:a}),e;let n=Sn.get(t);return!n||a-n.at>Oh?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function P0(){Sn.clear(),da.clear()}function Dh(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 Bh(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}
20501
20567
  data: ${JSON.stringify(c)}
20502
20568
 
20503
- `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ve(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 Dh(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let _ of a.config.dashboard.daemons)i.add(_.url.replace(/\/+$/,""));try{let _=await pa(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let v of _)i.add(v.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){k(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 d=new AbortController,p;try{p=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:d.signal})}catch(_){k(e,502,{error:_.message||"upstream connect failed"});return}if(!p.ok||!p.body){k(e,p.status||502,{error:`upstream HTTP ${p.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=p.body.getReader();(async()=>{try{for(;;){let{value:_,done:v}=await m.read();if(v)break;_&&e.write(_)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{d.abort();try{e.end()}catch{}})}function Bh(t,e,a){let n=ka(t);if(!n)return k(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new G().verify(n);if(!r)return k(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!Ee(r,o))return k(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Hh(t,e,a,n){let r=a.agents?.[n];if(!r){k(e,404,{error:"unknown agent"});return}if(r.access!=="public"){k(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await me(t)}catch{k(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){k(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||{}}})}),d=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(d)}catch(c){k(e,502,{error:c.message||"upstream call failed"})}}async function zh(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let p of e.config.dashboard.daemons)i.add(p.url.replace(/\/+$/,""));try{let p=await pa(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of p)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){k(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 d=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let p=await fetch(`${s}${d}`,{headers:c}),m=await p.text();t.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(p){k(t,502,{error:p.message||"upstream fetch failed"})}}async function qh(t,e,a,n,r,o){await En(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function En(t,e,a,n,r){let o={};try{o=await me(t)??{}}catch{}let s=await Dc(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Dc(t,e,a,n){let r=(c,d)=>({status:c,text:JSON.stringify(d),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 pa(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let d of c)s.add(d.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 Tn(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo){let r=t.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(t.dashboard,r);return wt(),{...a(`Can't reach ${e.relayTo}, the computer that sends notifications`),async forward(s){let i=await fetch(`${r}/push/app`,{method:"POST",headers:{"Content-Type":"application/json",...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify({op:"app",call:s}),signal:AbortSignal.timeout(2e4)}),l=await i.json().catch(()=>({}));if(!i.ok||typeof l.status!="number")throw new Error(l.error||`the daemon answered ${i.status}`);return{status:l.status,body:l.body??{}}}}}let n=ir(e.keysFile);return{store:()=>{let r=Je();return r?new Pr(r):null},publicKey:()=>lr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Pc(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?Tl({url:a,token:U(t.dashboard,a),operatorKey:xa(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}.`:Tn(t).reason;return Ml(t,process.cwd(),n,r)}function Bc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ve(t,n),async nodePost(n,r,o){let s=await Dc(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=Et({root:process.cwd()}).items.map(jc)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=lt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(jc)}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 d=Ae(),p=await Tt({root:process.cwd()},r,o,{laterHours:d.laterHours,by:s,...i});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let c=lt(l,t);if(!c)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let d=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:d.status,body:a(await d.text())}}catch(d){return{status:502,body:{error:d.message||"peer dashboard unreachable"}}}}}}var _n=null;function $c(t){return _n?.days!==t&&(_n={days:t,store:new ht(process.cwd(),Date.now,t)}),_n.store}function Hc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=Bc(t);return{store:()=>{let r=Je();return r?new st(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:xa(process.cwd())??void 0},snapshot:()=>Ve(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(/\/+$/,"")),...Fh(t,e,a)}}function Fh(t,e,a){let n=Tn(t);return{finishAlerts:r=>{if(n.forward)return sr.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}
20504
- ${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 Uh(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=Hc(t);return new la({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 Ve(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:nl(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Wh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Je();return a?new st(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Gh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function jc(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires,...t.choices?{choices:t.choices}:{},...t.draft?{draft:t.draft}:{}}}var Xh=`
20569
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ve(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 Hh(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let S of a.config.dashboard.daemons)i.add(S.url.replace(/\/+$/,""));try{let S=await pa(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let v of S)i.add(v.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){k(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 d=new AbortController,p;try{p=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:d.signal})}catch(S){k(e,502,{error:S.message||"upstream connect failed"});return}if(!p.ok||!p.body){k(e,p.status||502,{error:`upstream HTTP ${p.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=p.body.getReader();(async()=>{try{for(;;){let{value:S,done:v}=await m.read();if(v)break;S&&e.write(S)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{d.abort();try{e.end()}catch{}})}function zh(t,e,a){let n=ka(t);if(!n)return k(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new G().verify(n);if(!r)return k(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!Ee(r,o))return k(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function qh(t,e,a,n){let r=a.agents?.[n];if(!r){k(e,404,{error:"unknown agent"});return}if(r.access!=="public"){k(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await me(t)}catch{k(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){k(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||{}}})}),d=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(d)}catch(c){k(e,502,{error:c.message||"upstream call failed"})}}async function Fh(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let p of e.config.dashboard.daemons)i.add(p.url.replace(/\/+$/,""));try{let p=await pa(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of p)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){k(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 d=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let p=await fetch(`${s}${d}`,{headers:c}),m=await p.text();t.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(p){k(t,502,{error:p.message||"upstream fetch failed"})}}async function Uh(t,e,a,n,r,o){await En(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function En(t,e,a,n,r){let o={};try{o=await me(t)??{}}catch{}let s=await Hc(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Hc(t,e,a,n){let r=(c,d)=>({status:c,text:JSON.stringify(d),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 pa(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let d of c)s.add(d.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 Tn(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo){let r=t.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(t.dashboard,r);return wt(),{...a(`Can't reach ${e.relayTo}, the computer that sends notifications`),async forward(s){let i=await fetch(`${r}/push/app`,{method:"POST",headers:{"Content-Type":"application/json",...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify({op:"app",call:s}),signal:AbortSignal.timeout(2e4)}),l=await i.json().catch(()=>({}));if(!i.ok||typeof l.status!="number")throw new Error(l.error||`the daemon answered ${i.status}`);return{status:l.status,body:l.body??{}}}}}let n=cr(e.keysFile);return{store:()=>{let r=Je();return r?new jr(r):null},publicKey:()=>dr(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function jc(t){let e=t.channels.push,a=t.dashboard.daemonUrl.replace(/\/+$/,""),n=e.enabled&&!e.relayTo?Cl({url:a,token:U(t.dashboard,a),operatorKey:xa(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}.`:Tn(t).reason;return Rl(t,process.cwd(),n,r)}function zc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ve(t,n),async nodePost(n,r,o){let s=await Hc(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=Et({root:process.cwd()}).items.map(Nc)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=lt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(Nc)}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 d=Ae(),p=await Tt({root:process.cwd()},r,o,{laterHours:d.laterHours,by:s,...i});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let c=lt(l,t);if(!c)return{status:403,body:{error:"node not in dashboard allowlist",target:l}};try{let d=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:d.status,body:a(await d.text())}}catch(d){return{status:502,body:{error:d.message||"peer dashboard unreachable"}}}}}}var _n=null;function Oc(t){return _n?.days!==t&&(_n={days:t,store:new ht(process.cwd(),Date.now,t)}),_n.store}function qc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=zc(t);return{store:()=>{let r=Je();return r?new st(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:xa(process.cwd())??void 0},snapshot:()=>Ve(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(/\/+$/,"")),...Wh(t,e,a)}}function Wh(t,e,a){let n=Tn(t);return{finishAlerts:r=>{if(n.forward)return lr.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}
20570
+ ${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 Gh(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=qc(t);return new la({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 Ve(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:ol(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function Xh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Je();return a?new st(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function Kh(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function Nc(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires,...t.choices?{choices:t.choices}:{},...t.draft?{draft:t.draft}:{}}}var Jh=`
20505
20571
  You are helping draft a new GitLab issue. Follow these conventions strictly.
20506
20572
 
20507
20573
  Title pattern:
@@ -20533,16 +20599,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
20533
20599
  Shape:
20534
20600
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
20535
20601
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
20536
- `;async function Kh(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):
20602
+ `;async function Vh(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):
20537
20603
  - ${r.knownLabels.slice(0,60).join(`
20538
20604
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
20539
- `),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:Xh}})});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 d=(c.content||"").toString(),p=Jh(d);if(!p||typeof p.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+d.slice(0,400));let m=Array.isArray(p.labels)?p.labels.filter(f=>typeof f=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:p.title.trim(),description:(p.description||"").toString(),labels:m,assigneeUsername:typeof p.assigneeUsername=="string"?p.assigneeUsername:void 0,kind:typeof p.kind=="string"?p.kind:void 0,raw:d}}function Jh(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 Vh(t){let e=wh(yh(import.meta.url));return it(e,t)}async function Yh(t){return bh(t)}function k(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function me(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 zc(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:zc(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 Qh(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;k(e,200,await ea(await qc(r,a.config)))}async function qc(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=en(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=lt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,d=setTimeout(()=>c.abort(),8e3);try{let p=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return p.ok?{nodeId:i.name||i.url,snap:await p.json()}:null}finally{clearTimeout(d)}}catch{return null}}));for(let i of s)i&&n.push(i);return ci(n)}async function Zh(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let p=process.env.HOME||"",m=[p&&`${p}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),f=m.find(_=>Nc(_));if(!f){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",f]}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}
20605
+ `),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:Jh}})});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 d=(c.content||"").toString(),p=Yh(d);if(!p||typeof p.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+d.slice(0,400));let m=Array.isArray(p.labels)?p.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:p.title.trim(),description:(p.description||"").toString(),labels:m,assigneeUsername:typeof p.assigneeUsername=="string"?p.assigneeUsername:void 0,kind:typeof p.kind=="string"?p.kind:void 0,raw:d}}function Yh(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 Qh(t){let e=_h(kh(import.meta.url));return it(e,t)}async function Zh(t){return wh(t)}function k(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function me(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 Fc(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:Fc(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 eg(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;k(e,200,await ea(await Uc(r,a.config)))}async function Uc(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=en(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=lt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,d=setTimeout(()=>c.abort(),8e3);try{let p=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return p.ok?{nodeId:i.name||i.url,snap:await p.json()}:null}finally{clearTimeout(d)}}catch{return null}}));for(let i of s)i&&n.push(i);return pi(n)}async function tg(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let p=process.env.HOME||"",m=[p&&`${p}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(S=>Bc(S));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:m}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
20540
20606
 
20541
20607
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=p=>{i+=p.toString("utf8");let m;for(;(m=i.indexOf(`
20542
- `))>=0;){let f=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
20543
- data: ${f.replace(/\n/g," ")}
20608
+ `))>=0;){let h=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
20609
+ data: ${h.replace(/\n/g," ")}
20544
20610
 
20545
20611
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
20546
20612
 
20547
- `)}catch{}},15e3),d=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",d),s.on("exit",d),s.on("error",d)}async function Oc(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((p,m)=>{let f=[];t.on("data",_=>f.push(_)),t.on("end",()=>p(Buffer.concat(f))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let d=t.headers["x-requested-with"];d&&(l["X-Requested-With"]=Array.isArray(d)?d[0]:d),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let p=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await p.arrayBuffer());e.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(p){k(e,502,{error:`proxy to peer failed: ${p?.message||p}`,target:r})}}function lt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:zc(n),token:n.dashboardToken||n.token}:null}export{Oh as applyAttachSessions,Ih as fetchDaemonAgents,_h as handleBoardRequest,M0 as resetLiveCaches,Se as resolveNodeTargets,I0 as startBoardDashboard,jh as withLastGood};
20548
- //# sourceMappingURL=board-dashboard-ZDJ4UDW4.js.map
20613
+ `)}catch{}},15e3),d=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",d),s.on("exit",d),s.on("error",d)}async function Dc(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((p,m)=>{let h=[];t.on("data",S=>h.push(S)),t.on("end",()=>p(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let d=t.headers["x-requested-with"];d&&(l["X-Requested-With"]=Array.isArray(d)?d[0]:d),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let p=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await p.arrayBuffer());e.writeHead(p.status,{"Content-Type":p.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(p){k(e,502,{error:`proxy to peer failed: ${p?.message||p}`,target:r})}}function lt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Fc(n),token:n.dashboardToken||n.token}:null}export{Dh as applyAttachSessions,Lh as fetchDaemonAgents,Eh as handleBoardRequest,P0 as resetLiveCaches,Se as resolveNodeTargets,R0 as startBoardDashboard,Nh as withLastGood};
20614
+ //# sourceMappingURL=board-dashboard-3AOENRSG.js.map