agentix-cli 0.62.0 → 0.63.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 (106) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/SettingsWindow.swift +48 -26
  2. package/dist/{App-OWUIYVPJ.js → App-B6WGWI3A.js} +2 -2
  3. package/dist/{ChatApp-6HZRTQ3D.js → ChatApp-BHRANF7Z.js} +2 -2
  4. package/dist/{agent-NPPA34M3.js → agent-D2BHFDUA.js} +2 -2
  5. package/dist/{board-dashboard-27XK4IL5.js → board-dashboard-SMCZBJKO.js} +472 -200
  6. package/dist/board-dashboard-SMCZBJKO.js.map +1 -0
  7. package/dist/{chunk-6YERP2RV.js → chunk-2ZKDZ4FM.js} +2 -2
  8. package/dist/{chunk-XYXYVZM6.js → chunk-33YJIUYL.js} +2 -2
  9. package/dist/{chunk-5Z4QLJ6A.js → chunk-5QP56S4O.js} +2 -2
  10. package/dist/{chunk-JZLCBA26.js → chunk-5UYXEO3I.js} +24 -24
  11. package/dist/{chunk-JZLCBA26.js.map → chunk-5UYXEO3I.js.map} +1 -1
  12. package/dist/{chunk-UIWQKR7G.js → chunk-5WMHW4A6.js} +2 -2
  13. package/dist/{chunk-H5VC7XG6.js → chunk-7LETLAIH.js} +153 -152
  14. package/dist/chunk-7LETLAIH.js.map +1 -0
  15. package/dist/{chunk-UHO7YMOU.js → chunk-AZBOYKQA.js} +2 -2
  16. package/dist/{chunk-YZ3RTZ5G.js → chunk-BHE5TJSN.js} +2 -2
  17. package/dist/chunk-BYJ3A55Y.js +13 -0
  18. package/dist/chunk-BYJ3A55Y.js.map +1 -0
  19. package/dist/{chunk-W7YVQGCO.js → chunk-EA7H3EUX.js} +2 -2
  20. package/dist/{chunk-NBFNAM5F.js → chunk-I2SD4XZ6.js} +2 -2
  21. package/dist/{chunk-7ACTZO5L.js → chunk-JZMKKDT3.js} +5 -5
  22. package/dist/{chunk-JZZLM6N6.js → chunk-LQ5J6COO.js} +2 -2
  23. package/dist/{chunk-V3LTLSCV.js → chunk-N42YWYIR.js} +7 -7
  24. package/dist/{chunk-V3LTLSCV.js.map → chunk-N42YWYIR.js.map} +1 -1
  25. package/dist/{chunk-HCFAFVUZ.js → chunk-OVF37EXJ.js} +9 -9
  26. package/dist/{chunk-HCFAFVUZ.js.map → chunk-OVF37EXJ.js.map} +1 -1
  27. package/dist/{chunk-GYUOAUYL.js → chunk-P4GOKVK2.js} +2 -2
  28. package/dist/{chunk-CLJQLSSQ.js → chunk-PMGPGMBZ.js} +2 -2
  29. package/dist/{chunk-MTBQONW5.js → chunk-PTB2TPOC.js} +2 -2
  30. package/dist/{chunk-RSPBTNCJ.js → chunk-TX3ZOO22.js} +2 -2
  31. package/dist/{chunk-RHGUWBXI.js → chunk-WGWNVLVW.js} +2 -2
  32. package/dist/{chunk-PFJZ6SQR.js → chunk-XT3E5MLX.js} +2 -2
  33. package/dist/{chunk-JB46DY2K.js → chunk-ZGWW6FZF.js} +214 -214
  34. package/dist/chunk-ZGWW6FZF.js.map +1 -0
  35. package/dist/cli.js +1 -1
  36. package/dist/client-YIBETZDJ.js +2 -0
  37. package/dist/{config-UGFFAXYA.js → config-EXNBBAZG.js} +2 -2
  38. package/dist/config-mutator-MFNZNWCZ.js +2 -0
  39. package/dist/doctor-IITNYJU5.js +2 -0
  40. package/dist/index.d.ts +8 -0
  41. package/dist/index.js +1 -1
  42. package/dist/program-NPPLJAQ7.js +2 -0
  43. package/dist/{promote-NTEGYFVS.js → promote-KPEOVZ5V.js} +2 -2
  44. package/dist/query-WRWFAW5G.js +2 -0
  45. package/dist/{registry-N5TDGYMN.js → registry-MRMQBYE4.js} +2 -2
  46. package/dist/{request-planner-GU77ZWEF.js → request-planner-PLBDCYKI.js} +2 -2
  47. package/dist/{review-candidates-7NZJEIQ7.js → review-candidates-LEO2N65G.js} +2 -2
  48. package/dist/{routing-TAUSISYI.js → routing-POORZC7A.js} +2 -2
  49. package/dist/schedule-tool-ZI4XBEN6.js +2 -0
  50. package/dist/scheduler-VPPKD4FY.js +2 -0
  51. package/dist/{seat-TEFB62NU.js → seat-PBFG5R7D.js} +2 -2
  52. package/dist/{select-GY4C2M53.js → select-WORPEXHN.js} +2 -2
  53. package/dist/{set-enabled-6KFM4ZL2.js → set-enabled-HGQWVDUD.js} +2 -2
  54. package/dist/{tool-FZXIYBKQ.js → tool-T2BIWDXP.js} +2 -2
  55. package/dist/wiki-KTDNYDOD.js +2 -0
  56. package/package.json +2 -1
  57. package/dist/board-dashboard-27XK4IL5.js.map +0 -1
  58. package/dist/chunk-H5VC7XG6.js.map +0 -1
  59. package/dist/chunk-JB46DY2K.js.map +0 -1
  60. package/dist/chunk-S7CVSKOX.js +0 -13
  61. package/dist/chunk-S7CVSKOX.js.map +0 -1
  62. package/dist/client-JPOD4A4G.js +0 -2
  63. package/dist/config-mutator-BRSI7NZ2.js +0 -2
  64. package/dist/doctor-47ZKWQZT.js +0 -2
  65. package/dist/program-EO2R3G65.js +0 -2
  66. package/dist/query-3WNSFLKI.js +0 -2
  67. package/dist/schedule-tool-Y26PGA26.js +0 -2
  68. package/dist/scheduler-UTKCOJ3M.js +0 -2
  69. package/dist/wiki-OFQC6OMS.js +0 -2
  70. /package/dist/{App-OWUIYVPJ.js.map → App-B6WGWI3A.js.map} +0 -0
  71. /package/dist/{ChatApp-6HZRTQ3D.js.map → ChatApp-BHRANF7Z.js.map} +0 -0
  72. /package/dist/{agent-NPPA34M3.js.map → agent-D2BHFDUA.js.map} +0 -0
  73. /package/dist/{chunk-6YERP2RV.js.map → chunk-2ZKDZ4FM.js.map} +0 -0
  74. /package/dist/{chunk-XYXYVZM6.js.map → chunk-33YJIUYL.js.map} +0 -0
  75. /package/dist/{chunk-5Z4QLJ6A.js.map → chunk-5QP56S4O.js.map} +0 -0
  76. /package/dist/{chunk-UIWQKR7G.js.map → chunk-5WMHW4A6.js.map} +0 -0
  77. /package/dist/{chunk-UHO7YMOU.js.map → chunk-AZBOYKQA.js.map} +0 -0
  78. /package/dist/{chunk-YZ3RTZ5G.js.map → chunk-BHE5TJSN.js.map} +0 -0
  79. /package/dist/{chunk-W7YVQGCO.js.map → chunk-EA7H3EUX.js.map} +0 -0
  80. /package/dist/{chunk-NBFNAM5F.js.map → chunk-I2SD4XZ6.js.map} +0 -0
  81. /package/dist/{chunk-7ACTZO5L.js.map → chunk-JZMKKDT3.js.map} +0 -0
  82. /package/dist/{chunk-JZZLM6N6.js.map → chunk-LQ5J6COO.js.map} +0 -0
  83. /package/dist/{chunk-GYUOAUYL.js.map → chunk-P4GOKVK2.js.map} +0 -0
  84. /package/dist/{chunk-CLJQLSSQ.js.map → chunk-PMGPGMBZ.js.map} +0 -0
  85. /package/dist/{chunk-MTBQONW5.js.map → chunk-PTB2TPOC.js.map} +0 -0
  86. /package/dist/{chunk-RSPBTNCJ.js.map → chunk-TX3ZOO22.js.map} +0 -0
  87. /package/dist/{chunk-RHGUWBXI.js.map → chunk-WGWNVLVW.js.map} +0 -0
  88. /package/dist/{chunk-PFJZ6SQR.js.map → chunk-XT3E5MLX.js.map} +0 -0
  89. /package/dist/{client-JPOD4A4G.js.map → client-YIBETZDJ.js.map} +0 -0
  90. /package/dist/{config-UGFFAXYA.js.map → config-EXNBBAZG.js.map} +0 -0
  91. /package/dist/{config-mutator-BRSI7NZ2.js.map → config-mutator-MFNZNWCZ.js.map} +0 -0
  92. /package/dist/{doctor-47ZKWQZT.js.map → doctor-IITNYJU5.js.map} +0 -0
  93. /package/dist/{program-EO2R3G65.js.map → program-NPPLJAQ7.js.map} +0 -0
  94. /package/dist/{promote-NTEGYFVS.js.map → promote-KPEOVZ5V.js.map} +0 -0
  95. /package/dist/{query-3WNSFLKI.js.map → query-WRWFAW5G.js.map} +0 -0
  96. /package/dist/{registry-N5TDGYMN.js.map → registry-MRMQBYE4.js.map} +0 -0
  97. /package/dist/{request-planner-GU77ZWEF.js.map → request-planner-PLBDCYKI.js.map} +0 -0
  98. /package/dist/{review-candidates-7NZJEIQ7.js.map → review-candidates-LEO2N65G.js.map} +0 -0
  99. /package/dist/{routing-TAUSISYI.js.map → routing-POORZC7A.js.map} +0 -0
  100. /package/dist/{schedule-tool-Y26PGA26.js.map → schedule-tool-ZI4XBEN6.js.map} +0 -0
  101. /package/dist/{scheduler-UTKCOJ3M.js.map → scheduler-VPPKD4FY.js.map} +0 -0
  102. /package/dist/{seat-TEFB62NU.js.map → seat-PBFG5R7D.js.map} +0 -0
  103. /package/dist/{select-GY4C2M53.js.map → select-WORPEXHN.js.map} +0 -0
  104. /package/dist/{set-enabled-6KFM4ZL2.js.map → set-enabled-HGQWVDUD.js.map} +0 -0
  105. /package/dist/{tool-FZXIYBKQ.js.map → tool-T2BIWDXP.js.map} +0 -0
  106. /package/dist/{wiki-OFQC6OMS.js.map → wiki-KTDNYDOD.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as Ia}from"./chunk-WWMFNLKD.js";import{a as Oa}from"./chunk-GUJB53QU.js";import{a as C,b as Da,c as Na,d as Ha,e as Ba,h as za,i as _e,j as qa,k as Ua,l as Wa,m as Ga,n as Xa}from"./chunk-XYXYVZM6.js";import{a as Fa}from"./chunk-Z3IP66SL.js";import{a as $a,b as me,c as La,d as $,e as P,j as Je,k as Ve,l as ee,m as U,n as Ye,o as Ra,p as ja,q as Pa}from"./chunk-KAFO5QZR.js";import{A as Ue,Aa as Xe,Ba as Ea,Ca as Ta,Da as Ca,Ea as Ke,G as ne,Ga as Aa,H as ga,I as xa,Ja as Ma,T as ya,U as wa,V as ka,a as la,c as ze,d as xt,e as da,i as ca,k as pa,m as Z,n as xe,na as _a,o as vt,pa as bt,ua as Sa,wa as ke,xa as Fe,ya as We,z as qe,za as Ge}from"./chunk-JZLCBA26.js";import{g as sa,h as ia}from"./chunk-5Z4QLJ6A.js";import{o as ua,r as ma}from"./chunk-S7CVSKOX.js";import{a as va,b as ba}from"./chunk-LQRBGQIR.js";import"./chunk-NBFNAM5F.js";import"./chunk-PFJZ6SQR.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as fa,c as ha}from"./chunk-2D3RYIDU.js";import{a as aa,c as ht,d as gt,h as na,i as ra,j as oa}from"./chunk-CLJQLSSQ.js";import"./chunk-WP6KLXTP.js";import{a as Be}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-YZ3RTZ5G.js";import"./chunk-W7YVQGCO.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-UHO7YMOU.js";import{b as ta}from"./chunk-RHGUWBXI.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-MTBQONW5.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as Zt,b as ea,c as yo,w as Q,z as ft}from"./chunk-HCFAFVUZ.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function yt(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 Ka(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:yt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var te={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"/>'},ve=(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>",Qe=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ve(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ja(t={}){return $({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as Oa}from"./chunk-WWMFNLKD.js";import{a as qa}from"./chunk-GUJB53QU.js";import{a as C,b as Ua,c as Fa,d as Wa,e as Ga,h as Xa,i as Se,j as Ka,k as Ja,l as Ya,m as Qa,n as Za}from"./chunk-33YJIUYL.js";import{a as Va}from"./chunk-Z3IP66SL.js";import{a as Da,b as ee,c as Na,d as $,e as P,j as Ye,k as Qe,l as te,m as U,n as Ze,o as Ha,p as Ba,q as za}from"./chunk-KAFO5QZR.js";import{A as Fe,Aa as Xe,B as We,Ba as Ke,Ca as Je,Da as $a,Ea as La,Fa as Ra,Ga as Ve,H as re,I as ka,Ia as ja,J as _a,La as Pa,U as Ta,V as Ca,W as Aa,a as ma,c as Ue,d as wt,e as fa,i as ha,k as ga,m as Z,n as xe,o as ba,p as kt,pa as Ma,ra as _t,wa as Ia,ya as _e,za as Ge}from"./chunk-5UYXEO3I.js";import{g as pa,h as ua}from"./chunk-5QP56S4O.js";import{p as xa,s as va}from"./chunk-BYJ3A55Y.js";import{a as Sa,b as Ea}from"./chunk-LQRBGQIR.js";import"./chunk-I2SD4XZ6.js";import"./chunk-XT3E5MLX.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ya,c as wa}from"./chunk-2D3RYIDU.js";import{a as ia,c as bt,d as yt,h as la,i as ca,j as da}from"./chunk-PMGPGMBZ.js";import"./chunk-WP6KLXTP.js";import{a as qe}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-BHE5TJSN.js";import"./chunk-EA7H3EUX.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-AZBOYKQA.js";import{b as sa}from"./chunk-WGWNVLVW.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-PTB2TPOC.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as ra,b as oa,c as Ro,w as Q,z as vt}from"./chunk-OVF37EXJ.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function St(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 en(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:St(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ae={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"/>'},ve=(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>",et=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ve(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function tn(t={}){return $({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
2
2
 
3
3
  <div class="bf-head">
4
4
  <div>
@@ -7,8 +7,8 @@ import{a as Ia}from"./chunk-WWMFNLKD.js";import{a as Oa}from"./chunk-GUJB53QU.js
7
7
  </div>
8
8
  <div class="bf-sync">
9
9
  <span class="bf-sync__t" id="synced">Gathering&hellip;</span>
10
- <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${ve(te.pulse,13)} Activity</a>
11
- <button class="ax-btn" id="refresh" title="Refresh now">${ve(te.refresh)} Refresh</button>
10
+ <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${ve(ae.pulse,13)} Activity</a>
11
+ <button class="ax-btn" id="refresh" title="Refresh now">${ve(ae.refresh)} Refresh</button>
12
12
  </div>
13
13
  </div>
14
14
 
@@ -21,24 +21,24 @@ import{a as Ia}from"./chunk-WWMFNLKD.js";import{a as Oa}from"./chunk-GUJB53QU.js
21
21
 
22
22
  <div class="bf-grid">
23
23
  <section class="bf-col">
24
- ${Qe(te.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
24
+ ${et(ae.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
25
25
  <div id="you" class="bf-col"></div>
26
26
 
27
- ${Qe(te.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed &mdash; not yet automatic</span>')}
27
+ ${et(ae.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed &mdash; not yet automatic</span>')}
28
28
  <div id="agents" class="bf-col"></div>
29
29
  <button class="ax-btn ax-btn--sm" id="more-actions" hidden></button>
30
30
 
31
31
  <div id="handled"></div>
32
32
  </section>
33
33
  <aside class="bf-col">
34
- ${Qe(te.pulse,"In motion","run-count")}
34
+ ${et(ae.pulse,"In motion","run-count")}
35
35
  <div id="running" class="bf-col"></div>
36
36
  </aside>
37
37
  </div>
38
38
 
39
- ${Qe(te.file,"Session briefings","brief-count")}
39
+ ${et(ae.file,"Session briefings","brief-count")}
40
40
  <div class="bf-toolbar">
41
- <div class="bf-search">${ve(te.search)}
41
+ <div class="bf-search">${ve(ae.search)}
42
42
  <input id="search" type="search" placeholder="Search sessions&hellip;" aria-label="Search sessions">
43
43
  </div>
44
44
  <div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
@@ -46,15 +46,15 @@ ${Qe(te.file,"Session briefings","brief-count")}
46
46
  <div id="reviews" class="bf-col"></div>
47
47
 
48
48
  <section class="ax-panel bf-connect">
49
- <div class="bf-connect__head">${ve(te.plug,17)}<h2>Connect a CLI session</h2>
49
+ <div class="bf-connect__head">${ve(ae.plug,17)}<h2>Connect a CLI session</h2>
50
50
  <span class="bf-connect__note">Daemon-owned processes only</span></div>
51
51
  <div class="bf-discover">
52
52
  <div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
53
- <button class="ax-btn" id="discover">${ve(te.search)} Discover CLIs</button>
53
+ <button class="ax-btn" id="discover">${ve(ae.search)} Discover CLIs</button>
54
54
  </div>
55
55
  <div class="bf-cli" id="discovered"></div>
56
56
  <details class="bf-manual">
57
- <summary>${ve(te.chev,12)} Register manually</summary>
57
+ <summary>${ve(ae.chev,12)} Register manually</summary>
58
58
  <div class="bf-forms">
59
59
  <form id="register" class="bf-form">
60
60
  <div class="ax-sec-label"><h3>Register a session</h3></div>
@@ -85,7 +85,7 @@ ${Qe(te.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:wo,scripts:`<script>${me({decayOf:yt,rankByDecay:Ka})}const ICON = ${JSON.stringify(te)};${ko}</script>`})}var wo=`
88
+ </div>`,css:jo,scripts:`<script>${ee({decayOf:St,rankByDecay:en})}const ICON = ${JSON.stringify(ae)};${Po}</script>`})}var jo=`
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
- }`,ko=String.raw`
364
+ }`,Po=String.raw`
365
365
  (function(){
366
366
  const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
367
367
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -776,22 +776,22 @@ if(document.querySelector('form :focus'))return;
776
776
  if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
777
777
  refresh();
778
778
  },15000);
779
- })();`;function wt(t,e=20*6e4,a=6){let n=[...t].sort((l,d)=>l.startedAt-d.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let d=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,d),p.runs++):r.push({from:l.startedAt,to:d,runs:1})}for(;r.length>a;){let l=0,d=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<d&&(d=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,d)=>l+d.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,d)=>l.from-r[d].to);return{bands:s,gaps:i}}function kt(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 Va(t,e=[],a){let{bands:n,gaps:r}=wt(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let d=o.get(l.runId);d?d.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let d=n.findIndex(T=>l.startedAt>=T.from&&l.startedAt<=T.to);if(d===-1)continue;let p=n[d],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,b=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:d,track:0,left:f,width:b,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((d,p)=>kt(l.runs.filter(u=>u.band===p))),1);return i.sort((l,d)=>d.runs.length-l.runs.length||l.label.localeCompare(d.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as _o}from"crypto";import{readFileSync as So,statSync as Eo}from"fs";import{resolve as To,dirname as Co}from"path";import{fileURLToPath as Ao}from"url";var Ya=new Map;function Ze(t){let e=Ya.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Co(Ao(import.meta.url)),r=To(n,"web",t),o=Eo(r),s=o.size<8e6?_o("sha1").update(So(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Ya.set(t,a),a}var re={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"/>'},et=(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>",Mo=[["agent","Agent",re.bot],["client","Client",re.user],["project","Project",re.folder],["channel","Channel",re.route],["node","Node",re.mesh]],Qa={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 Za(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return $({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function Et(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function Tt(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 an(t,e=[],a){let{bands:n,gaps:r}=Et(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(T=>l.startedAt>=T.from&&l.startedAt<=T.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,b=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:c,track:0,left:f,width:b,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>Tt(l.runs.filter(u=>u.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Oo}from"crypto";import{readFileSync as Do,statSync as No}from"fs";import{resolve as Ho,dirname as Bo}from"path";import{fileURLToPath as zo}from"url";var nn=new Map;function tt(t){let e=nn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Bo(zo(import.meta.url)),r=Ho(n,"web",t),o=No(r),s=o.size<8e6?Oo("sha1").update(Do(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return nn.set(t,a),a}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',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"/>'},at=(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>",qo=[["agent","Agent",oe.bot],["client","Client",oe.user],["project","Project",oe.folder],["channel","Channel",oe.route],["node","Node",oe.mesh]],rn={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 on(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return $({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">${Qa[e]}</p>
785
+ <p class="ac-sub" id="sub">${rn[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
789
- ${[["timeline","Timeline",re.timeline],["map","Map",re.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${et(o,13)}${r}</button>`).join("")}
789
+ ${[["timeline","Timeline",oe.timeline],["map","Map",oe.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${at(o,13)}${r}</button>`).join("")}
790
790
  </div>
791
791
  <div class="ac-seg" id="hours" role="radiogroup" aria-label="Window">
792
792
  ${[["6","6h"],["24","24h"],["72","3d"],["168","7d"]].map(([n,r],o)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${o===1}"${o===1?' class="is-on"':""}>${r}</button>`).join("")}
793
793
  </div>
794
- <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${et(re.refresh,13)} Refresh</button>
794
+ <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${at(oe.refresh,13)} Refresh</button>
795
795
  </div>
796
796
  </div>
797
797
 
@@ -799,14 +799,14 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${Mo.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${et(o,13)}${r}</button>`).join("")}
802
+ ${qo.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${at(o,13)}${r}</button>`).join("")}
803
803
  </div>
804
804
  <div class="ac-key">
805
805
  <span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
806
806
  <span class="ac-k"><i class="ac-d ac-d--warning"></i>warning</span>
807
807
  <span class="ac-k"><i class="ac-d ac-d--recommendation"></i>friction</span>
808
808
  <span class="ac-k"><i class="ac-d ac-d--later"></i>do later</span>
809
- <span class="ac-k">${et(re.x,11)}canceled</span>
809
+ <span class="ac-k">${at(oe.x,11)}canceled</span>
810
810
  </div>
811
811
  </div>
812
812
 
@@ -816,10 +816,10 @@ refresh();
816
816
  </div>
817
817
 
818
818
  <div id="view-map" class="ac-map"${a?"":" hidden"}>
819
- <div id="ax-fleet-root" data-hours="24" data-src="${Ze("activity-graph.global.js")}"></div>
819
+ <div id="ax-fleet-root" data-hours="24" data-src="${tt("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:Io,scripts:`<script>${me({computeBands:wt,packTracks:kt,buildTimeline:Va})}const ICON = ${JSON.stringify(re)};const SUB = ${JSON.stringify(Qa)};${$o}</script>`})}var Io=`
822
+ </div>`,css:Uo,scripts:`<script>${ee({computeBands:Et,packTracks:Tt,buildTimeline:an})}const ICON = ${JSON.stringify(oe)};const SUB = ${JSON.stringify(rn)};${Fo}</script>`})}var Uo=`
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
- `,$o=String.raw`
908
+ `,Fo=String.raw`
909
909
  const $=id=>document.getElementById(id);
910
910
  const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
911
911
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -1022,7 +1022,7 @@ history.replaceState(null,'',u);
1022
1022
  if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
1023
1023
  $('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
1024
1024
  show(view);
1025
- `;function en(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return $({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Lo,scripts:`<script src="${Ze("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Lo=`
1025
+ `;function sn(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return $({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Wo,scripts:`<script src="${tt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Wo=`
1026
1026
  /* Preload the fonts the redesign's CSS references. Placed in the shell so
1027
1027
  * they start fetching while the React bundle is still parsing. */
1028
1028
  @import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
@@ -1043,10 +1043,10 @@ body { margin: 0; overflow: hidden; }
1043
1043
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
1044
1044
  text-align: center;
1045
1045
  }
1046
- `;import{createServer as $d}from"http";import{appendFileSync as Ld,existsSync as mo,mkdirSync as Rd}from"fs";import{readFile as jd}from"fs/promises";import{fileURLToPath as Pd}from"url";import{dirname as Od,resolve as De}from"path";yo();var tn='/*! 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 tt,readFileSync as nn,writeFileSync as rn,rmSync as Nc,mkdirSync as No,copyFileSync as Ho,readdirSync as Bo}from"fs";import{resolve as Se}from"path";ft();var oe={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 an(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Je({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.`})+Ve([{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">');return $({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+jo()+Ra,css:Oo,scripts:`${e}<script>${ja}
1047
- ${Pa}
1048
- ${Ro}
1049
- ${Do}</script>`})}var Ro=`
1046
+ `;import{createServer as Xc}from"http";import{appendFileSync as Kc,existsSync as To,mkdirSync as Jc}from"fs";import{readFile as Vc}from"fs/promises";import{fileURLToPath as Yc}from"url";import{dirname as Qc,resolve as He}from"path";Ro();var ln='/*! 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 nt,readFileSync as dn,writeFileSync as pn,rmSync as ep,mkdirSync as Yo,copyFileSync as Qo,readdirSync as Zo}from"fs";import{resolve as Ee}from"path";vt();var se={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 cn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Ye({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.`})+Qe([{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">');return $({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Xo()+Ha,css:Jo,scripts:`${e}<script>${Ba}
1047
+ ${za}
1048
+ ${Go}
1049
+ ${Vo}</script>`})}var Go=`
1050
1050
  (function(){
1051
1051
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1052
1052
  async function refresh() {
@@ -1107,8 +1107,8 @@ ${Do}</script>`})}var Ro=`
1107
1107
  refresh();
1108
1108
  // Refresh again after the main admin script has had a chance to mutate config.
1109
1109
  document.addEventListener('ax-config-saved', refresh);
1110
- })();`;function jo(){let t=ba().business?`<button data-tab="business">Business</button>
1111
- `:"";return Po.replace("__BUSINESS_TABS__",t)}var Po=`
1110
+ })();`;function Xo(){let t=Ea().business?`<button data-tab="business">Business</button>
1111
+ `:"";return Ko.replace("__BUSINESS_TABS__",t)}var Ko=`
1112
1112
  <div id="peer-banner" class="peer-banner">
1113
1113
  <span class="label">Managing</span>
1114
1114
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -1251,8 +1251,8 @@ ${Do}</script>`})}var Ro=`
1251
1251
  <div id="global-msg" class="msg"></div>
1252
1252
 
1253
1253
  <section id="tab-agents" class="tab active">
1254
- ${U({icon:oe.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1255
- ${ee({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
1254
+ ${U({icon:se.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1255
+ ${te({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
1256
1256
  <div id="agent-list" class="ax-stack"></div>
1257
1257
  <div class="add-form">
1258
1258
  <h3>Add a new agent</h3>
@@ -1274,8 +1274,8 @@ ${Do}</script>`})}var Ro=`
1274
1274
  </section>
1275
1275
 
1276
1276
  <section id="tab-channels" class="tab">
1277
- ${U({icon:oe.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1278
- ${ee({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
1277
+ ${U({icon:se.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1278
+ ${te({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
1279
1279
 
1280
1280
  <details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
1281
1281
  <summary class="primary">\u2699 Notifications routing</summary>
@@ -1360,10 +1360,10 @@ ${Do}</script>`})}var Ro=`
1360
1360
  </div>
1361
1361
  </details>
1362
1362
 
1363
- <div id="ch-chatapps-label">${Ye({label:"Chat apps"})}</div>
1363
+ <div id="ch-chatapps-label">${Ze({label:"Chat apps"})}</div>
1364
1364
  <div class="ax-connectors" id="ch-chatapps"></div>
1365
1365
 
1366
- <div id="ch-devtools-label">${Ye({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
1366
+ <div id="ch-devtools-label">${Ze({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
1367
1367
  <div class="ax-connectors" id="ch-devtools"></div>
1368
1368
 
1369
1369
  <!-- Active-channel configuration panes. One shows at a time; clicking
@@ -1381,8 +1381,8 @@ ${Do}</script>`})}var Ro=`
1381
1381
  </section>
1382
1382
 
1383
1383
  <section id="tab-crons" class="tab">
1384
- ${U({icon:oe.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
1385
- ${ee({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
1384
+ ${U({icon:se.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
1385
+ ${te({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
1386
1386
  <div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
1387
1387
 
1388
1388
  <div class="ax-builder">
@@ -1479,8 +1479,8 @@ ${Do}</script>`})}var Ro=`
1479
1479
  </section>
1480
1480
 
1481
1481
  <section id="tab-webhooks" class="tab">
1482
- ${U({icon:oe.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
1483
- ${ee({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
1482
+ ${U({icon:se.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
1483
+ ${te({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
1484
1484
  <div id="webhook-list" class="ax-stack"></div>
1485
1485
  <div class="add-form">
1486
1486
  <h3>Add a webhook</h3>
@@ -1499,10 +1499,10 @@ ${Do}</script>`})}var Ro=`
1499
1499
  </section>
1500
1500
 
1501
1501
  <section id="tab-mesh" class="tab">
1502
- ${U({icon:oe.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
1502
+ ${U({icon:se.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
1503
1503
  <div id="mesh-hero" class="ax-mesh-hero"></div>
1504
- ${ee({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
1505
- ${Ye({label:"Connected peers"})}
1504
+ ${te({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
1505
+ ${Ze({label:"Connected peers"})}
1506
1506
  <div id="mesh-peers" class="ax-stack"></div>
1507
1507
  <div class="add-form">
1508
1508
  <h3>Add a peer</h3>
@@ -1529,8 +1529,8 @@ ${Do}</script>`})}var Ro=`
1529
1529
  </section>
1530
1530
 
1531
1531
  <section id="tab-business" class="tab">
1532
- ${U({icon:oe.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
1533
- ${ee({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
1532
+ ${U({icon:se.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
1533
+ ${te({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
1534
1534
 
1535
1535
  <div class="ax-stack" style="margin-top:14px">
1536
1536
  <h3 style="margin:0 0 6px;font-size:13px">Org chart</h3>
@@ -1617,8 +1617,8 @@ ${Do}</script>`})}var Ro=`
1617
1617
  </section>
1618
1618
 
1619
1619
  <section id="tab-boards-cfg" class="tab">
1620
- ${U({icon:oe.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
1621
- ${ee({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
1620
+ ${U({icon:se.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
1621
+ ${te({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
1622
1622
 
1623
1623
  <div class="ax-stack" style="margin-top:14px">
1624
1624
  <h3 style="margin:0 0 6px;font-size:13px">Boards</h3>
@@ -1642,8 +1642,8 @@ ${Do}</script>`})}var Ro=`
1642
1642
  </section>
1643
1643
 
1644
1644
  <section id="tab-actions" class="tab">
1645
- ${U({icon:oe.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
1646
- ${ee({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
1645
+ ${U({icon:se.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
1646
+ ${te({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
1647
1647
 
1648
1648
  <div class="ax-stack" style="margin-top:14px">
1649
1649
  <h3 style="margin:0 0 6px;font-size:13px">Registered actions</h3>
@@ -1698,8 +1698,8 @@ ${Do}</script>`})}var Ro=`
1698
1698
  </section>
1699
1699
 
1700
1700
  <section id="tab-tokens" class="tab">
1701
- ${U({icon:oe.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
1702
- ${ee({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
1701
+ ${U({icon:se.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
1702
+ ${te({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
1703
1703
  <div id="token-list" class="ax-stack"></div>
1704
1704
  <div class="add-form">
1705
1705
  <h3>Mint a new token</h3>
@@ -1718,8 +1718,8 @@ ${Do}</script>`})}var Ro=`
1718
1718
  </section>
1719
1719
 
1720
1720
  <section id="tab-advanced" class="tab">
1721
- ${U({icon:oe.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
1722
- ${ee({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
1721
+ ${U({icon:se.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
1722
+ ${te({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
1723
1723
 
1724
1724
  <div class="ax-jv-toolbar">
1725
1725
  <input class="ax-jv-search" id="jv-search" placeholder="Search keys & values\u2026" />
@@ -1745,7 +1745,7 @@ ${Do}</script>`})}var Ro=`
1745
1745
  <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>
1746
1746
  </section>
1747
1747
  </main>
1748
- `,Oo=`
1748
+ `,Jo=`
1749
1749
 
1750
1750
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
1751
1751
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -1953,7 +1953,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
1953
1953
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
1954
1954
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
1955
1955
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
1956
- `,Do=`
1956
+ `,Vo=`
1957
1957
  const $ = (id) => document.getElementById(id);
1958
1958
  let state = null;
1959
1959
 
@@ -4760,11 +4760,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
4760
4760
  })();
4761
4761
 
4762
4762
  refresh();
4763
- `;function on(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(an({peers:a,localToken:n}))}async function sn(t,e){let a=Et();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function ln(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await es(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await zo(t),r={"GET /api/admin/state":()=>Uo(),"POST /api/admin/agents":()=>Jo(n),"PATCH /api/admin/agents":()=>Vo(n),"DELETE /api/admin/agents":()=>Yo(n),"POST /api/admin/agents/access":()=>Fo(n),"POST /api/admin/channels/telegram":()=>Qo(n),"DELETE /api/admin/channels/telegram":()=>ks(n),"POST /api/admin/channels/telegram/toggle":()=>_s(n),"POST /api/admin/crons":()=>Ss(n),"DELETE /api/admin/crons":()=>Es(n),"POST /api/admin/config/raw":()=>Ts(n),"GET /api/admin/tokens":()=>Wo(),"POST /api/admin/tokens":()=>Go(n),"DELETE /api/admin/tokens":()=>Xo(n),"POST /api/admin/agents/test":()=>Ko(n),"POST /api/admin/agents/integrations":()=>ss(n),"DELETE /api/admin/agents/integrations":()=>is(n),"PATCH /api/admin/agents/integrations":()=>ls(n),"PATCH /api/admin/channels/telegram":()=>Zo(n),"POST /api/admin/channels/slack":()=>hs(n),"POST /api/admin/channels/slack/toggle":()=>gs(n),"POST /api/admin/channels/discord":()=>xs(n),"POST /api/admin/channels/discord/toggle":()=>vs(n),"POST /api/admin/channels/gitlab":()=>bs(n),"POST /api/admin/channels/gitlab/toggle":()=>ys(n),"GET /api/admin/channels/whatsapp/state":()=>Le("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Le("/webrtc/history"),"POST /api/admin/actions":()=>Hs(n),"DELETE /api/admin/actions":()=>Bs(n),"POST /api/admin/actions/run":()=>zs(n),"GET /api/admin/channels/whatsapp/chats":()=>Le("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Le("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>le("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ws(n),"POST /api/admin/webhooks":()=>ds(n),"PATCH /api/admin/webhooks":()=>cs(n),"DELETE /api/admin/webhooks":()=>fs(n),"POST /api/admin/mesh/peers":()=>ps(n),"DELETE /api/admin/mesh/peers":()=>us(n),"POST /api/admin/mesh/toggle":()=>ms(n),"GET /api/admin/files":()=>ts(t),"GET /api/admin/files/read":()=>as(t),"PUT /api/admin/files":()=>ns(n),"POST /api/admin/files/skill":()=>rs(n),"DELETE /api/admin/files/skill":()=>os(n),"POST /api/admin/business/orgchart":()=>Cs(n),"DELETE /api/admin/business/orgchart":()=>As(n),"POST /api/admin/business/project":()=>Ms(n),"DELETE /api/admin/business/project":()=>Ls(n),"POST /api/admin/business/client":()=>Is(n),"DELETE /api/admin/business/client":()=>$s(n),"POST /api/admin/business/contact":()=>Rs(n),"DELETE /api/admin/business/contact":()=>js(n),"POST /api/admin/boards":()=>Ps(n),"DELETE /api/admin/boards":()=>Os(n),"POST /api/admin/boards/columns":()=>Ds(n),"DELETE /api/admin/boards/columns":()=>Ns(n),"POST /api/admin/notifications":()=>Us(n),"POST /api/admin/screen":()=>Fs(n),"POST /api/admin/webhooks/triggers":()=>Ws(n),"POST /api/admin/mesh/health":()=>qs(n),"GET /api/admin/projects":()=>Le("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>le("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>le("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>le("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>le("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>le("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>le("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>le("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>le("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){_t(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();_t(e,200,i)}catch(n){_t(e,400,{error:n.message||"admin op failed"})}}function _t(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function zo(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 qo(t){let e=Se(process.cwd(),t);if(!tt(e))return[];let a=[];for(let n of Bo(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(nn(Se(e,n.name),"utf-8")))}catch{}return a}function Et(){let t=Se(process.cwd(),"agentx.json");return tt(t)?JSON.parse(nn(t,"utf-8")):null}function Uo(){let t=Et();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([c,m])=>({id:c,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(h=>{let x=h.credentials||{},k={};for(let[v,_]of Object.entries(x))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?k[v]=process.env[_]?"set":"unset":typeof _=="string"&&(k[v]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:x,credStatus:k,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([c,m])=>({id:c,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.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(([c,m])=>({id:c,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(c=>({id:c.id,source:c.source,agentId:c.agentId,secretEnv:c.secretEnv||"",description:c.description||"",enabled:c.enabled!==!1,triggers:c.triggers&&typeof c.triggers=="object"?c.triggers:{},defaultWorkflow:c.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(c=>({url:c.url,name:c.name,hasToken:!!c.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},b={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},w=t.notifications||{},T={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:ua(w.local),ntfy:Wa(t.channels?.ntfy)},g=[];try{g=qo(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,h)=>m.id.localeCompare(h.id))}catch{}let E=(Array.isArray(t.boards)?t.boards:[]).map(c=>({id:c.id,name:c.name,source:c.source||{type:"gitlab",projects:[]},primaryToolLabel:c.primaryToolLabel||"",timeRangeDays:c.timeRangeDays??30,closedWindowDays:c.closedWindowDays??30,columns:Array.isArray(c.columns)?c.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,crons:l,webhooks:d,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:b,boards:E,notifications:T,screen:Aa(t.screen),actions:g}}function Fo(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 Wo(){return new Z().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 Go(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 Z().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Xo(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Z().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ko(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=Q();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),d;try{d=JSON.parse(l)}catch{d={content:l}}if(!i.ok)throw new Error(d?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:d}}function Jo(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=cn(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=Se(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),d=Se(i,"CLAUDE.md");if(!tt(d))try{No(i,{recursive:!0}),rn(d,`# ${a}
4763
+ `;function un(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cn({peers:a,localToken:n}))}async function mn(t,e){let a=Mt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function fn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await ms(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await es(t),r={"GET /api/admin/state":()=>as(),"POST /api/admin/agents":()=>ls(n),"PATCH /api/admin/agents":()=>cs(n),"DELETE /api/admin/agents":()=>ds(n),"POST /api/admin/agents/access":()=>ns(n),"POST /api/admin/channels/telegram":()=>ps(n),"DELETE /api/admin/channels/telegram":()=>Ps(n),"POST /api/admin/channels/telegram/toggle":()=>Os(n),"POST /api/admin/crons":()=>Ds(n),"DELETE /api/admin/crons":()=>Ns(n),"POST /api/admin/config/raw":()=>Hs(n),"GET /api/admin/tokens":()=>rs(),"POST /api/admin/tokens":()=>os(n),"DELETE /api/admin/tokens":()=>ss(n),"POST /api/admin/agents/test":()=>is(n),"POST /api/admin/agents/integrations":()=>bs(n),"DELETE /api/admin/agents/integrations":()=>ys(n),"PATCH /api/admin/agents/integrations":()=>ws(n),"PATCH /api/admin/channels/telegram":()=>us(n),"POST /api/admin/channels/slack":()=>As(n),"POST /api/admin/channels/slack/toggle":()=>Ms(n),"POST /api/admin/channels/discord":()=>Is(n),"POST /api/admin/channels/discord/toggle":()=>$s(n),"POST /api/admin/channels/gitlab":()=>Ls(n),"POST /api/admin/channels/gitlab/toggle":()=>Rs(n),"GET /api/admin/channels/whatsapp/state":()=>Le("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Le("/webrtc/history"),"POST /api/admin/actions":()=>Qs(n),"DELETE /api/admin/actions":()=>Zs(n),"POST /api/admin/actions/run":()=>ei(n),"GET /api/admin/channels/whatsapp/chats":()=>Le("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Le("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ce("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>js(n),"POST /api/admin/webhooks":()=>ks(n),"PATCH /api/admin/webhooks":()=>_s(n),"DELETE /api/admin/webhooks":()=>Cs(n),"POST /api/admin/mesh/peers":()=>Ss(n),"DELETE /api/admin/mesh/peers":()=>Es(n),"POST /api/admin/mesh/toggle":()=>Ts(n),"GET /api/admin/files":()=>fs(t),"GET /api/admin/files/read":()=>hs(t),"PUT /api/admin/files":()=>gs(n),"POST /api/admin/files/skill":()=>xs(n),"DELETE /api/admin/files/skill":()=>vs(n),"POST /api/admin/business/orgchart":()=>Bs(n),"DELETE /api/admin/business/orgchart":()=>zs(n),"POST /api/admin/business/project":()=>qs(n),"DELETE /api/admin/business/project":()=>Ws(n),"POST /api/admin/business/client":()=>Us(n),"DELETE /api/admin/business/client":()=>Fs(n),"POST /api/admin/business/contact":()=>Gs(n),"DELETE /api/admin/business/contact":()=>Xs(n),"POST /api/admin/boards":()=>Ks(n),"DELETE /api/admin/boards":()=>Js(n),"POST /api/admin/boards/columns":()=>Vs(n),"DELETE /api/admin/boards/columns":()=>Ys(n),"POST /api/admin/notifications":()=>ai(n),"POST /api/admin/screen":()=>ni(n),"POST /api/admin/webhooks/triggers":()=>ri(n),"POST /api/admin/mesh/health":()=>ti(n),"GET /api/admin/projects":()=>Le("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ce("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ce("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ce("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ce("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ce("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ce("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ce("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ce("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Ct(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Ct(e,200,i)}catch(n){Ct(e,400,{error:n.message||"admin op failed"})}}function Ct(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function es(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 ts(t){let e=Ee(process.cwd(),t);if(!nt(e))return[];let a=[];for(let n of Zo(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(dn(Ee(e,n.name),"utf-8")))}catch{}return a}function Mt(){let t=Ee(process.cwd(),"agentx.json");return nt(t)?JSON.parse(dn(t,"utf-8")):null}function as(){let t=Mt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(h=>{let g=h.credentials||{},k={};for(let[v,_]of Object.entries(g))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?k[v]=process.env[_]?"set":"unset":typeof _=="string"&&(k[v]="literal");return{kind:h.kind,label:h.label,enabled:h.enabled!==!1,credentials:g,credStatus:k,metadata:h.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},b={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},w=t.notifications||{},T={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:xa(w.local),ntfy:Ya(t.channels?.ntfy)},E=[];try{E=ts(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,h)=>m.id.localeCompare(h.id))}catch{}let x=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:b,boards:x,notifications:T,screen:ja(t.screen),actions:E}}function ns(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 rs(){return new Z().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 os(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 Z().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function ss(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Z().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function is(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=Q();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function ls(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=gn(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=Ee(process.cwd(),"agents",e),{summary:l}=C(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),c=Ee(i,"CLAUDE.md");if(!nt(c))try{Yo(i,{recursive:!0}),pn(c,`# ${a}
4764
4764
 
4765
4765
  ${s||"You are "+a+"."}
4766
- `)}catch{}return{summary:l}}function Vo(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=cn(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 Yo(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 Qo(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 Zo(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 Le(t){let{url:e,headers:a}=Tt(),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 le(t,e){let{url:a,headers:n}=Tt(),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 es(t,e){try{let{url:a,headers:n}=Tt(),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 Tt(){let t="http://127.0.0.1:18800",e={};try{let a=Q();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Re(t){let a=Et()?.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 St(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ts(t){let e=St(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ke(Re(e));return{agentId:e,...a}}function as(t){let e=St(t,"agent").trim(),a=St(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Fe(Re(e),a)}function ns(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=We(Re(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function rs(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=Ge(Re(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function os(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=Xe(Re(e),a);return{summary:`removed skill "${a}"`,...n}}function ss(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[l];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${l} must be uppercase identifier (got "${d}")`);r[l]=d.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[l]=d);let{summary:i}=C(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function is(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=C(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(d=>d.kind===a&&d.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function ls(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let d=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!d)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(d.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(d.metadata={...d.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var dn=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function ds(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(!dn.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(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let d={id:e,source:a,agentId:n,enabled:!0};return r&&(d.secretEnv=r),o&&(d.description=o),s&&(d.node=s),l.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function cs(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"&&dn.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 ps(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 us(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 ms(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 fs(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 hs(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 gs(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 xs(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 vs(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 bs(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 ys(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 ws(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-UTKCOJ3M.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 ks(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 _s(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 Ss(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 Es(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 Ts(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=Se(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(tt(n))try{Ho(n,r)}catch{}rn(n,JSON.stringify(a,null,2)+`
4767
- `,"utf-8");try{let s=Q().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 cn(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Cs(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=C(d=>(d.business=d.business||{},d.business.orgChart=d.business.orgChart||{},d.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function As(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 Ms(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 Is(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 $s(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 Ls(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 Rs(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 js(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 Ps(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=C(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let d=l.boards.findIndex(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),d>=0){let u=l.boards[d];return l.boards[d]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Os(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 Ds(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(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let d={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");d.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");d.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(d.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...d},`column "${a}" updated`):(l.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ns(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 Hs(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 Bs(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 zs(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 qs(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 Us(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=ma(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=Ga(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 Fs(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Ma(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ws(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 Ks}from"path";function pn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4766
+ `)}catch{}return{summary:l}}function cs(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=gn(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 ds(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 ps(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 us(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 Le(t){let{url:e,headers:a}=It(),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 ce(t,e){let{url:a,headers:n}=It(),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 ms(t,e){try{let{url:a,headers:n}=It(),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 It(){let t="http://127.0.0.1:18800",e={};try{let a=Q();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Re(t){let a=Mt()?.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 At(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function fs(t){let e=At(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=_e(Re(e));return{agentId:e,...a}}function hs(t){let e=At(t,"agent").trim(),a=At(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Ge(Re(e),a)}function gs(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=Xe(Re(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function xs(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=Ke(Re(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function vs(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=Je(Re(e),a);return{summary:`removed skill "${a}"`,...n}}function bs(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 ys(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 ws(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=C(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var hn=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function ks(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(!hn.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(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function _s(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"&&hn.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 Ss(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 Es(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 Ts(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 Cs(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 As(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 Ms(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 Is(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 $s(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 Ls(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 Rs(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 js(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-VPPKD4FY.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 Ps(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 Os(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 Ds(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 Ns(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 Hs(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=Ee(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(nt(n))try{Qo(n,r)}catch{}pn(n,JSON.stringify(a,null,2)+`
4767
+ `,"utf-8");try{let s=Q().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 gn(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Bs(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 zs(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 qs(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 Us(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 Fs(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 Ws(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 Gs(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 Xs(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 Ks(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(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function Js(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 Vs(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(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ys(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 Qs(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 Zs(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 ei(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 ti(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 ai(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=va(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=Qa(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 ni(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=Pa(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function ri(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=C(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}vt();import{resolve as ii}from"path";function xn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4768
4768
 
4769
4769
  <div id="disabled-banner" class="banner warn" style="display:none">
4770
4770
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -4819,7 +4819,7 @@ ${s||"You are "+a+"."}
4819
4819
  <h2>Recent classifications</h2>
4820
4820
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
4821
4821
  <div id="recent"></div>
4822
- </section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Gs,scripts:`${e}<script>${Xs}</script>`})}var Gs=`
4822
+ </section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:oi,scripts:`${e}<script>${si}</script>`})}var oi=`
4823
4823
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
4824
4824
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
4825
4825
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -4923,7 +4923,7 @@ details {
4923
4923
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
4924
4924
  }
4925
4925
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
4926
- details[open] summary { margin-bottom: 8px; }`,Xs=`
4926
+ details[open] summary { margin-bottom: 8px; }`,si=`
4927
4927
  const $ = (id) => document.getElementById(id);
4928
4928
  const state = { schema: null, nodes: [], pending: [], recent: [] };
4929
4929
 
@@ -5143,7 +5143,7 @@ $('btn-save-schema').addEventListener('click', async () => {
5143
5143
  $('btn-reload-schema').addEventListener('click', refresh);
5144
5144
 
5145
5145
  refresh();
5146
- `;function mn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:a,localToken:n}))}async function fn(t,e,a){try{let n=t.method==="GET"?void 0:await ni(t),r=Js(),o={"GET /api/admin/graph/state":()=>Vs(r),"POST /api/admin/graph/classifications/approve":()=>Ys(r,n),"POST /api/admin/graph/classifications/reject":()=>Qs(r,n),"POST /api/admin/graph/nodes":()=>Zs(r,n),"PATCH /api/admin/graph/nodes":()=>ei(r,n),"DELETE /api/admin/graph/nodes":()=>ti(r,n),"PUT /api/admin/graph/schema":()=>ai(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Ct(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Ct(e,200,l)}catch(n){Ct(e,400,{error:n?.message||"graph op failed"})}}function Js(){let t=Q(),e=Ks(process.cwd(),t.graph.baseDir);return new ta({baseDir:e})}function Vs(t){let e=Q(),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 Ys(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=hn(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=At(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Qs(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=hn(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function hn(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 Zs(t,e){let a=un(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?un(String(e.parentId)):null,o=At({[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 ei(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=At({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function ti(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function ai(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 At(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 un(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Ct(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ni(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 gn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5146
+ `;function bn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xn({peers:a,localToken:n}))}async function yn(t,e,a){try{let n=t.method==="GET"?void 0:await gi(t),r=li(),o={"GET /api/admin/graph/state":()=>ci(r),"POST /api/admin/graph/classifications/approve":()=>di(r,n),"POST /api/admin/graph/classifications/reject":()=>pi(r,n),"POST /api/admin/graph/nodes":()=>ui(r,n),"PATCH /api/admin/graph/nodes":()=>mi(r,n),"DELETE /api/admin/graph/nodes":()=>fi(r,n),"PUT /api/admin/graph/schema":()=>hi(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){$t(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();$t(e,200,l)}catch(n){$t(e,400,{error:n?.message||"graph op failed"})}}function li(){let t=Q(),e=ii(process.cwd(),t.graph.baseDir);return new sa({baseDir:e})}function ci(t){let e=Q(),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 di(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=wn(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=Lt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function pi(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=wn(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function wn(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 ui(t,e){let a=vn(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?vn(String(e.parentId)):null,o=Lt({[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 mi(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Lt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function fi(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function hi(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 Lt(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 vn(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function $t(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function gi(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 kn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5147
5147
  <header class="apv__head">
5148
5148
  <div>
5149
5149
  <h1>Approvals</h1>
@@ -5176,7 +5176,7 @@ refresh();
5176
5176
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5177
5177
  </form>
5178
5178
  </details>
5179
- </div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ri,scripts:`${e}<script>${oi}</script>`})}var ri=`
5179
+ </div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:xi,scripts:`${e}<script>${vi}</script>`})}var xi=`
5180
5180
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
5181
5181
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
5182
5182
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -5225,7 +5225,7 @@ refresh();
5225
5225
  @media (max-width: 560px) {
5226
5226
  .apv__acts .ax-btn { flex: 1 1 0; }
5227
5227
  }
5228
- `,oi=`
5228
+ `,vi=`
5229
5229
  (function(){
5230
5230
  var state = { items: [], snoozed: 0, kind: '', showAll: false };
5231
5231
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson' };
@@ -5376,7 +5376,7 @@ $('apv-form').addEventListener('submit', async function(ev){
5376
5376
  load();
5377
5377
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
5378
5378
  })();
5379
- `;var si=["yes","no","later"];function de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function xn(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 vn(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(gn({peers:e,localToken:a}))}async function bn(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 de(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=qe(s,{includeSnoozed:n.searchParams.get("all")==="1"});return de(e,200,{...i,settings:_e(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await xn(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!si.includes(d))return de(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=_e(s.configPath),u=await Ue(s,l,d,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(de(e,200,{ok:!0,message:u.message}),!0):(de(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await xn(t),l={},d=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};if(l.defaultExpiryDays=d("defaultExpiryDays"),l.maxExpiryDays=d("maxExpiryDays"),l.laterHours=d("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let f=qa(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Ua(l,{configPath:s.configPath,reload:s.reload});return p.success?(de(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(de(e,400,{error:p.error}),!0)}}catch(i){return de(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return de(e,404,{error:"Not found"}),!0}import{resolve as di}from"path";import{existsSync as ci}from"fs";import pi from"better-sqlite3";function yn(t={}){let e=`<div class="ax-obs">
5379
+ `;var bi=["yes","no","later"];function de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function _n(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 Sn(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(kn({peers:e,localToken:a}))}async function En(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 de(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=Fe(s,{includeSnoozed:n.searchParams.get("all")==="1"});return de(e,200,{...i,settings:Se(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await _n(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!bi.includes(c))return de(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Se(s.configPath),u=await We(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(de(e,200,{ok:!0,message:u.message}),!0):(de(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await _n(t),l={},c=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let f=Ka(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Ja(l,{configPath:s.configPath,reload:s.reload});return p.success?(de(e,200,{ok:!0,settings:Se(s.configPath)}),!0):(de(e,400,{error:p.error}),!0)}}catch(i){return de(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return de(e,404,{error:"Not found"}),!0}import{resolve as ki}from"path";import{existsSync as _i}from"fs";import Si from"better-sqlite3";function Tn(t={}){let e=`<div class="ax-obs">
5380
5380
  <header class="ax-obs__head">
5381
5381
  <h1>Health</h1>
5382
5382
  <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>
@@ -5498,7 +5498,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5498
5498
  </div>
5499
5499
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
5500
5500
  </section>
5501
- </div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ii,scripts:`<script>${li}</script>`})}var ii=`
5501
+ </div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:yi,scripts:`<script>${wi}</script>`})}var yi=`
5502
5502
  .ax-obs { padding: 16px 24px; }
5503
5503
  .ax-obs__head { margin-bottom: 16px; }
5504
5504
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -5615,7 +5615,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5615
5615
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
5616
5616
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
5617
5617
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
5618
- `,li=`
5618
+ `,wi=`
5619
5619
  (function(){
5620
5620
  var panes = document.querySelectorAll('.ax-obs__pane');
5621
5621
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -5999,23 +5999,23 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5999
5999
 
6000
6000
  load(current);
6001
6001
  })();
6002
- `;var _n={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 Sn(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Mt(t){let e=_n[Sn(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 ui(){let t=di(process.cwd(),".agentx/db.sqlite");if(!ci(t))return null;try{let e=new pi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function En(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(yn({peers:a}))}function mi(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 ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Tn(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=ui();if(!r)return ce(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=mi(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6002
+ `;var Mn={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 In(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Rt(t){let e=Mn[In(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 Ei(){let t=ki(process.cwd(),".agentx/db.sqlite");if(!_i(t))return null;try{let e=new Si(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function $n(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Tn({peers:a}))}function Ti(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 pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Ln(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Ei();if(!r)return pe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Ti(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6003
6003
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
6004
6004
  FROM route_traces
6005
6005
  ${i.length?"WHERE "+i.join(" AND "):""}
6006
6006
  ORDER BY at DESC LIMIT @limit
6007
- `,p=r.db.prepare(d).all(l);return ce(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6007
+ `,p=r.db.prepare(c).all(l);return pe(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6008
6008
  SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
6009
6009
  FROM rotations
6010
6010
  ${i.length?"WHERE "+i.join(" AND "):""}
6011
6011
  ORDER BY rotated_at DESC LIMIT @limit
6012
- `,p=r.db.prepare(d).all(l);return ce(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6012
+ `,p=r.db.prepare(c).all(l);return pe(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6013
6013
  SELECT started_at, agent_id, channel, message_preview, error
6014
6014
  FROM task_history
6015
6015
  WHERE ${i.join(" AND ")}
6016
6016
  ORDER BY started_at DESC LIMIT @limit
6017
- `,u=r.db.prepare(d).all(l).map(f=>({...f,plain:Cn(f.error)}));return ce(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return ce(e,200,fi(r.db)),!0;if(n==="activity")return ce(e,200,hi(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=wn(i.searchParams.get("range"));return ce(e,200,kn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=wn(i.searchParams.get("range")),d=kn(r.db,l),p=gi(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return ce(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Cn(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(`
6018
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function fi(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,d=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=_=>p.length?p[Math.min(p.length-1,Math.floor(p.length*_))].duration_ms:0,f=u(.5),b=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Mt(M),0),g=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Mt(M),0),E=t.prepare(`
6017
+ `,u=r.db.prepare(c).all(l).map(f=>({...f,plain:Rn(f.error)}));return pe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return pe(e,200,Ci(r.db)),!0;if(n==="activity")return pe(e,200,Ai(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Cn(i.searchParams.get("range"));return pe(e,200,An(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Cn(i.searchParams.get("range")),c=An(r.db,l),p=Mi(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return pe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return pe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Rn(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(`
6018
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Ci(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=_=>p.length?p[Math.min(p.length-1,Math.floor(p.length*_))].duration_ms:0,f=u(.5),b=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Rt(M),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Rt(M),0),x=t.prepare(`
6019
6019
  SELECT agent_id,
6020
6020
  COUNT(*) AS tasks,
6021
6021
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -6025,7 +6025,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6025
6025
  WHERE started_at >= ?
6026
6026
  GROUP BY agent_id
6027
6027
  ORDER BY tasks DESC LIMIT 10
6028
- `).all(a),c=t.prepare(`
6028
+ `).all(a),d=t.prepare(`
6029
6029
  SELECT COALESCE(channel, 'unknown') AS channel,
6030
6030
  COUNT(*) AS tasks,
6031
6031
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6033,12 +6033,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6033
6033
  WHERE started_at >= ?
6034
6034
  GROUP BY channel
6035
6035
  ORDER BY tasks DESC
6036
- `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),x=m.filter(_=>!h.has(_)),v=t.prepare(`
6036
+ `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),h=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),g=m.filter(_=>!h.has(_)),v=t.prepare(`
6037
6037
  SELECT started_at, agent_id, channel, message_preview, error
6038
6038
  FROM task_history
6039
6039
  WHERE status='error' AND started_at >= ?
6040
6040
  ORDER BY started_at DESC LIMIT 5
6041
- `).all(o).map(_=>({..._,plain:Cn(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:b,spendToday:T,spendDelta:T-g,idleAgentCount:x.length},perAgent:E,perChannel:c,idleAgents:x,recentErrors:v}}function hi(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(`
6041
+ `).all(o).map(_=>({..._,plain:Rn(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:f,p95DurationMs:b,spendToday:T,spendDelta:T-E,idleAgentCount:g.length},perAgent:x,perChannel:d,idleAgents:g,recentErrors:v}}function Ai(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(`
6042
6042
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
6043
6043
  COUNT(*) AS tasks,
6044
6044
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6065,7 +6065,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6065
6065
  WHERE started_at >= @since
6066
6066
  GROUP BY agent_id
6067
6067
  ORDER BY tasks_24h DESC, tasks_7d DESC
6068
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function wn(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 kn(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6068
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Cn(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 An(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6069
6069
  SELECT day, agent_id, model,
6070
6070
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
6071
6071
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -6073,15 +6073,15 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6073
6073
  FROM usage_daily
6074
6074
  ${a}
6075
6075
  ORDER BY day
6076
- `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,d=0,p=0,u=0,f=0,b=0,w=0,T=0,g=0,E={},c={};for(let S of n){let I=Mt(S),R=Sn(S.model),j=_n[R],B=(S.tier2_input_tokens||0)/1e6*j.input*.5+(S.tier2_output_tokens||0)/1e6*j.output*.5+(S.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(S.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,ae=(S.input_tokens||0)+(S.tier2_input_tokens||0),z=(S.output_tokens||0)+(S.tier2_output_tokens||0),N=(S.cache_read_tokens||0)+(S.tier2_cache_read_tokens||0),H=(S.cache_create_tokens||0)+(S.tier2_cache_create_tokens||0);u+=I,S.day>=s&&(p+=I,w+=S.tasks||0),S.day>=i&&S.day<s&&(g+=I,T+=S.tasks||0),S.day===r&&(l+=I),S.day===o&&(d+=I),S.day===r&&(f+=B),S.day>=s&&(b+=B);let V=E[S.day]||(E[S.day]={date:S.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});V.tasks+=S.tasks||0,V.input+=ae,V.output+=z,V.cacheRead+=N,V.cacheCreate+=H,V.cost+=I,V.tier2+=B;let q=V.agents[S.agent_id]||(V.agents[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});q.tasks+=S.tasks||0,q.cost+=I,q.tier2+=B,q.input+=ae,q.output+=z,q.cacheRead+=N,q.cacheCreate+=H,S.model&&(q.model=S.model);let Y=c[S.agent_id]||(c[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});Y.tasks+=S.tasks||0,Y.cost+=I,Y.tier2+=B,Y.input+=ae,Y.output+=z,Y.cacheRead+=N,Y.cacheCreate+=H,S.model&&(Y.model=S.model)}let m=Object.values(E).sort((S,I)=>S.date<I.date?-1:1),h=0,x=0,k=0,v=0,_=0,M=0;for(let S of m)h+=S.tasks,x+=S.input,k+=S.output,v+=S.cacheRead,_+=S.cacheCreate,M+=S.cost;let A=Object.entries(c).map(([S,I])=>({agent_id:S,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((S,I)=>I.cost-S.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:b,tier2PctToday:l>0?f/l:0,spendRange:M,avgDailyRange:m.length?M/m.length:0,tasksRange:h,tokensRange:x+k+v+_,cacheHitRange:v+x>0?v/(v+x):0,costPerTaskRange:h>0?M/h:0,spendDeltaWoW:g>0?(p-g)/g:0,tasksDeltaWoW:T>0?(w-T)/T:0},days:m,perAgent:A}}function gi(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+`
6076
+ `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,u=0,f=0,b=0,w=0,T=0,E=0,x={},d={};for(let S of n){let I=Rt(S),R=In(S.model),j=Mn[R],B=(S.tier2_input_tokens||0)/1e6*j.input*.5+(S.tier2_output_tokens||0)/1e6*j.output*.5+(S.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(S.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,ne=(S.input_tokens||0)+(S.tier2_input_tokens||0),z=(S.output_tokens||0)+(S.tier2_output_tokens||0),N=(S.cache_read_tokens||0)+(S.tier2_cache_read_tokens||0),H=(S.cache_create_tokens||0)+(S.tier2_cache_create_tokens||0);u+=I,S.day>=s&&(p+=I,w+=S.tasks||0),S.day>=i&&S.day<s&&(E+=I,T+=S.tasks||0),S.day===r&&(l+=I),S.day===o&&(c+=I),S.day===r&&(f+=B),S.day>=s&&(b+=B);let V=x[S.day]||(x[S.day]={date:S.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});V.tasks+=S.tasks||0,V.input+=ne,V.output+=z,V.cacheRead+=N,V.cacheCreate+=H,V.cost+=I,V.tier2+=B;let q=V.agents[S.agent_id]||(V.agents[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});q.tasks+=S.tasks||0,q.cost+=I,q.tier2+=B,q.input+=ne,q.output+=z,q.cacheRead+=N,q.cacheCreate+=H,S.model&&(q.model=S.model);let Y=d[S.agent_id]||(d[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});Y.tasks+=S.tasks||0,Y.cost+=I,Y.tier2+=B,Y.input+=ne,Y.output+=z,Y.cacheRead+=N,Y.cacheCreate+=H,S.model&&(Y.model=S.model)}let m=Object.values(x).sort((S,I)=>S.date<I.date?-1:1),h=0,g=0,k=0,v=0,_=0,M=0;for(let S of m)h+=S.tasks,g+=S.input,k+=S.output,v+=S.cacheRead,_+=S.cacheCreate,M+=S.cost;let A=Object.entries(d).map(([S,I])=>({agent_id:S,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((S,I)=>I.cost-S.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:b,tier2PctToday:l>0?f/l:0,spendRange:M,avgDailyRange:m.length?M/m.length:0,tasksRange:h,tokensRange:g+k+v+_,cacheHitRange:v+g>0?v/(v+g):0,costPerTaskRange:h>0?M/h:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:T>0?(w-T)/T:0},days:m,perAgent:A}}function Mi(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+`
6077
6077
  `+a.join(`
6078
6078
  `)+`
6079
- `}import{resolve as xi}from"path";import{existsSync as vi}from"fs";import bi from"better-sqlite3";function yi(){let t=xi(process.cwd(),".agentx/intent/ledger.sqlite");if(!vi(t))return null;try{let e=new bi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-An>6e4&&(An=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var An=0;function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function wi(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 Mn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=yi();if(!r)return be(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=wi(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",b=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),w=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,T=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),g=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,E=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),c=r.db.prepare(`
6079
+ `}import{resolve as Ii}from"path";import{existsSync as $i}from"fs";import Li from"better-sqlite3";function Ri(){let t=Ii(process.cwd(),".agentx/intent/ledger.sqlite");if(!$i(t))return null;try{let e=new Li(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-jn>6e4&&(jn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var jn=0;function be(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ji(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 Pn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Ri();if(!r)return be(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ji(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",b=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),w=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,T=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,x=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6080
6080
  SELECT COUNT(*) AS n FROM intent_decisions d
6081
6081
  LEFT JOIN intent_resolutions r
6082
6082
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6083
6083
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
6084
- `).get().n;return be(e,200,{since:s??null,eventsBySource:b,totalDecisions:w,decisionsByOutcome:T,totalDivergences:g,divergencesBySource:E,inFlight:c}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let b=`
6084
+ `).get().n;return be(e,200,{since:s??null,eventsBySource:b,totalDecisions:w,decisionsByOutcome:T,totalDivergences:E,divergencesBySource:x,inFlight:d}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let b=`
6085
6085
  SELECT id, ts, source, source_event_id, project, subject, intent
6086
6086
  FROM intent_events
6087
6087
  ${u.length?"WHERE "+u.join(" AND "):""}
@@ -6103,7 +6103,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6103
6103
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6104
6104
  WHERE ${u.join(" AND ")}
6105
6105
  ORDER BY d.decided_at DESC LIMIT @limit
6106
- `;return be(e,200,{rows:r.db.prepare(b).all(f)}),!0}return be(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return be(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function In(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6106
+ `;return be(e,200,{rows:r.db.prepare(b).all(f)}),!0}return be(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return be(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function On(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6107
6107
  <header class="ax-led__head">
6108
6108
  <h1>Intent ledger</h1>
6109
6109
  <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>
@@ -6308,7 +6308,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6308
6308
  }
6309
6309
  load();
6310
6310
  })();
6311
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function $n(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6311
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Dn(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6312
6312
  <header class="ax-cost__head">
6313
6313
  <div>
6314
6314
  <h1>Cost</h1>
@@ -6881,7 +6881,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6881
6881
  load();
6882
6882
  setInterval(load, 30000);
6883
6883
  })();
6884
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Ln(t={}){let e=`<div class="ax-pj__root">
6884
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Nn(t={}){let e=`<div class="ax-pj__root">
6885
6885
  <aside class="ax-pj__list">
6886
6886
  <header>
6887
6887
  <h2>Projects</h2>
@@ -6908,7 +6908,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6908
6908
  </header>
6909
6909
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
6910
6910
  </section>
6911
- </div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ki,scripts:`<script>${_i}</script>`})}var ki=`
6911
+ </div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Pi,scripts:`<script>${Oi}</script>`})}var Pi=`
6912
6912
  .ax-pj__root {
6913
6913
  display: grid;
6914
6914
  grid-template-columns: 360px 1fr;
@@ -7095,7 +7095,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7095
7095
  }
7096
7096
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
7097
7097
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
7098
- `,_i=`
7098
+ `,Oi=`
7099
7099
  (function(){
7100
7100
  const $ = (sel) => document.querySelector(sel);
7101
7101
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -7745,9 +7745,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7745
7745
  load();
7746
7746
  });
7747
7747
  })();
7748
- `;import{resolve as Lt,join as Di}from"path";import{existsSync as Rt,readdirSync as Ni,readFileSync as Hi}from"fs";import Bi from"better-sqlite3";var jn=String.raw`[\w.-]+(?:/[\w.-]+)+`,Si=new RegExp(`^(?:chat:)?(${jn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Ei=new RegExp(`^\\[(?:GitLab|GitHub) (${jn}) `);function Rn(t){if(!t)return null;let e=t.match(Si);return e?e[1]:null}function It(t){if(!t)return null;let e=t.trimStart().match(Ei);return e?e[1]:null}function at(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Rn(typeof n?.chatId=="string"?n.chatId:null)??Rn(e)??It(a)}function Ti(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function nt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ci=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Ai=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Mi=t=>/^issue/i.test(t)?"issue":"mr";function Ii(t){let e=t.subject.match(Ci)??t.inputPreview.trimStart().match(Ai);return e?{kind:Mi(e[1]),n:Number(e[2])}:null}function $i(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 Pn(t){if(!Ti(t.projectId))return[];let e=Ii(t);return e?[e]:$i(t.inputPreview)}var Li=6e4,Ri=5*6e4,ji=40,On=6,Dn=new Map;function Nn(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 Pn(n)){let s=nt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=ji)return[...e.values()]}}return[...e.values()]}async function Hn(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=nt(s.project,s.ref),l=Dn.get(i);l&&n-l.at<(s.github?Ri:Li)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=On)await Promise.all(o.slice(s,s+On).map(async i=>{let l=nt(i.project,i.ref),d=null;try{d=i.github?await Oi(i,e,a):await Pi(i,e,a)}catch{}Dn.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function Bn(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 Pi(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 Bn(`${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 Oi(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 Bn(`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}function jt(){let t=Lt(process.cwd(),".agentx/intent/ledger.sqlite");if(!Rt(t))return null;try{let e=new Bi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-zn>6e4&&(zn=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var zn=0;function pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Ee={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"},opencode:{label:"OpenCode",color:"#57606a"}};function zi(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Ee)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Ee)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Ee)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 Ee)return s}return"workflow"}return t}function Fn(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 qi(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 Wn(t,e,a){return da(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 Ui(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:F(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&&!$t(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!$t(r||o||"")){let l=r||o||s,d=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:l,name:o||r||l,avatar:F(i),kind:d}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,d=i||(s.id!=null?String(s.id):null)||l;if(d&&!$t(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=qn(p);return{id:d,name:l||i||d,avatar:F(l||i||d),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,d=s.name||s.username;return{id:l,name:d,avatar:F(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:F(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:F(i),kind:qn(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:F(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:F(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:F(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:F(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:F(o),kind:"whatsapp"}}}return null}function qn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function $t(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 F(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 Gn(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}
7748
+ `;import{resolve as Ot,join as Vi}from"path";import{existsSync as Dt,readdirSync as Yi,readFileSync as Qi}from"fs";import Zi from"better-sqlite3";var Bn=String.raw`[\w.-]+(?:/[\w.-]+)+`,Di=new RegExp(`^(?:chat:)?(${Bn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Ni=new RegExp(`^\\[(?:GitLab|GitHub) (${Bn}) `);function Hn(t){if(!t)return null;let e=t.match(Di);return e?e[1]:null}function jt(t){if(!t)return null;let e=t.trimStart().match(Ni);return e?e[1]:null}function rt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Hn(typeof n?.chatId=="string"?n.chatId:null)??Hn(e)??jt(a)}function Hi(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function ot(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Bi=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,zi=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,qi=t=>/^issue/i.test(t)?"issue":"mr";function Ui(t){let e=t.subject.match(Bi)??t.inputPreview.trimStart().match(zi);return e?{kind:qi(e[1]),n:Number(e[2])}:null}function Fi(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 zn(t){if(!Hi(t.projectId))return[];let e=Ui(t);return e?[e]:Fi(t.inputPreview)}var Wi=6e4,Gi=5*6e4,Xi=40,qn=6,Un=new Map;function Fn(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 zn(n)){let s=ot(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Xi)return[...e.values()]}}return[...e.values()]}async function Wn(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=ot(s.project,s.ref),l=Un.get(i);l&&n-l.at<(s.github?Gi:Wi)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=qn)await Promise.all(o.slice(s,s+qn).map(async i=>{let l=ot(i.project,i.ref),c=null;try{c=i.github?await Ji(i,e,a):await Ki(i,e,a)}catch{}Un.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Gn(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 Ki(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 Gn(`${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 Ji(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 Gn(`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}function Nt(){let t=Ot(process.cwd(),".agentx/intent/ledger.sqlite");if(!Dt(t))return null;try{let e=new Zi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Xn>6e4&&(Xn=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Xn=0;function ue(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Te={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"},opencode:{label:"OpenCode",color:"#57606a"}};function el(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Te)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Te)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Te)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 Te)return s}return"workflow"}return t}function Vn(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 tl(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 Yn(t,e,a){return fa(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 al(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:F(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&&!Pt(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!Pt(r||o||"")){let l=r||o||s,c=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:l,name:o||r||l,avatar:F(i),kind:c}}}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&&!Pt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Kn(p);return{id:c,name:l||i||c,avatar:F(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:F(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:F(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:F(i),kind:Kn(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:F(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:F(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:F(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:F(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:F(o),kind:"whatsapp"}}}return null}function Kn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Pt(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 F(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 Qn(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}
7749
7749
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
7750
- ${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 Fi(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 Xn(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7750
+ ${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 nl(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 Zn(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7751
7751
  SELECT id, ts, source, project, subject, intent, raw_json
7752
7752
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
7753
7753
  `).all(r),s=new Map,i=new Map;if(o.length>0){let v=o.map(I=>I.id),_=v.map((I,R)=>`@id${R}`).join(","),M=Object.fromEntries(v.map((I,R)=>[`id${R}`,I])),A=t.prepare(`
@@ -7756,11 +7756,11 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
7756
7756
  `).all(M);for(let I of A)s.has(I.event_id)||s.set(I.event_id,[]),s.get(I.event_id).push(I);let S=t.prepare(`
7757
7757
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
7758
7758
  FROM intent_resolutions WHERE decision_event_id IN (${_})
7759
- `).all(M);for(let I of S)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,d=new Map,p=new Map,u=new Map,f=[],b=e?.business?.projects??[],w=e?.business?.contactMap??[],T=xt(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Wn(v.source,_,w),A=Gn(v.source,_),S=v.project??at(_,v.subject,A),I=null,R=null;M?(I=M.client,R=M.project||`${M.client}/_chat`):S&&(I=ze(S,b),R=S);let j=zi(v.source,v.intent||"",_),B=Ee[j]||{label:j,color:"#6b7280"};p.has(j)||p.set(j,{id:j,label:B.label,color:B.color});let ae="__system",z,N=Ui(v.source,v.intent||"",_);if(N){ae=N.id,z=N.kind;let H=M?.displayName||N.name;(!u.has(N.id)||M?.displayName)&&u.set(N.id,{id:N.id,name:H,avatar:F(H),kind:N.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(v.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let V=`${v.id}|${H.decided_by}`,q=i.get(V),Y=H.decided_at,Qt=q?.resolved_at??null,ut=Qt===null,vo=q?.duration_ms??(ut?n-Y:0),bo=ut?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",X,$e;if(I)X=I,$e=R;else{let mt=T.get(H.agent_id);mt?(X=mt,$e=`${mt}/_${v.source}`):(X="unmapped",$e=`unmapped/_${v.source}`)}l.has(X)||l.set(X,{id:X,name:X,color:Fn(X),projects:[]}),d.has(X)||d.set(X,new Set),d.get(X).add($e),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:X,projectId:$e,channelId:j,initiatorId:ae,initiatorKind:z,subject:Fi(v.subject),intent:v.intent||"",startedAt:Y,resolvedAt:Qt,duration:vo,active:ut,outcome:bo,tokens:0,inputPreview:A,system:qi(H.agent_id,e)})}}let g=[...l.values()].map(v=>({...v,projects:[...d.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),E=[],c=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,S=A?v.roles?.[A]?.title:void 0;return typeof S=="string"&&S.trim()?S.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let S={id:M,name:A.name||M,tier:A.tier==="claude-code"?"lead":"worker",model:A.model||"",role:A.systemPrompt?A.systemPrompt.split(/[.\n]/)[0].slice(0,60):A.tier||"",title:_(M)};E.push(S),c.add(M)}}for(let v of f)c.has(v.agentId)||(E.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),c.add(v.agentId));E.sort((v,_)=>v.id.localeCompare(_.id));let m=[],h=new Set;for(let[v,_]of Object.entries(Ee))m.push({id:v,label:_.label,color:_.color}),h.add(v);for(let v of p.values())h.has(v.id)||m.push(v);let x=[...u.values()];x.find(v=>v.id==="__system")||x.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:E,channels:m,initiators:x,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function Pt(t){let e=jt();if(!e)return null;try{return Xn(e.db,fe,t)}finally{e.close()}}function Kn(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:d,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let b=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:b})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=Wi(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Fn(f.clientId),projects:[]}),f.projectId!==u.projectId){let b=e.get(f.clientId);b.projects.includes(f.projectId)||e.set(f.clientId,{...b,projects:[...b.projects,f.projectId].sort()})}o.push({...f,nodeId:d,id:`${d}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((d,p)=>d.id.localeCompare(p.id)),agents:[...a.values()].sort((d,p)=>d.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((d,p)=>p.startedAt-d.startedAt)}}function Wi(t){if(t.clientId!=="unmapped")return t;let e=It(t.inputPreview);if(!e)return t;let a=fe?.business?.projects??[];return{...t,projectId:e,clientId:ze(e,a)}}async function rt(t){let e=fe?.channels?.gitlab,a=await Hn(Nn(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 fe=null;function Jn(t){fe=t}async function Vn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=jt();if(!n)return pe(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Yn(parseInt(r.searchParams.get("hours")||"6",10));pe(e,200,await rt(Xn(n.db,fe,o)))}catch(r){pe(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Gi=5e3;async function Ot(t,e,a,n=Pt){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
7759
+ `).all(M);for(let I of S)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],b=e?.business?.projects??[],w=e?.business?.contactMap??[],T=wt(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Yn(v.source,_,w),A=Qn(v.source,_),S=v.project??rt(_,v.subject,A),I=null,R=null;M?(I=M.client,R=M.project||`${M.client}/_chat`):S&&(I=Ue(S,b),R=S);let j=el(v.source,v.intent||"",_),B=Te[j]||{label:j,color:"#6b7280"};p.has(j)||p.set(j,{id:j,label:B.label,color:B.color});let ne="__system",z,N=al(v.source,v.intent||"",_);if(N){ne=N.id,z=N.kind;let H=M?.displayName||N.name;(!u.has(N.id)||M?.displayName)&&u.set(N.id,{id:N.id,name:H,avatar:F(H),kind:N.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(v.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let V=`${v.id}|${H.decided_by}`,q=i.get(V),Y=H.decided_at,na=q?.resolved_at??null,gt=na===null,$o=q?.duration_ms??(gt?n-Y:0),Lo=gt?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",X,$e;if(I)X=I,$e=R;else{let xt=T.get(H.agent_id);xt?(X=xt,$e=`${xt}/_${v.source}`):(X="unmapped",$e=`unmapped/_${v.source}`)}l.has(X)||l.set(X,{id:X,name:X,color:Vn(X),projects:[]}),c.has(X)||c.set(X,new Set),c.get(X).add($e),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:X,projectId:$e,channelId:j,initiatorId:ne,initiatorKind:z,subject:nl(v.subject),intent:v.intent||"",startedAt:Y,resolvedAt:na,duration:$o,active:gt,outcome:Lo,tokens:0,inputPreview:A,system:tl(H.agent_id,e)})}}let E=[...l.values()].map(v=>({...v,projects:[...c.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),x=[],d=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,S=A?v.roles?.[A]?.title:void 0;return typeof S=="string"&&S.trim()?S.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let S={id:M,name:A.name||M,tier:A.tier==="claude-code"?"lead":"worker",model:A.model||"",role:A.systemPrompt?A.systemPrompt.split(/[.\n]/)[0].slice(0,60):A.tier||"",title:_(M)};x.push(S),d.add(M)}}for(let v of f)d.has(v.agentId)||(x.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),d.add(v.agentId));x.sort((v,_)=>v.id.localeCompare(_.id));let m=[],h=new Set;for(let[v,_]of Object.entries(Te))m.push({id:v,label:_.label,color:_.color}),h.add(v);for(let v of p.values())h.has(v.id)||m.push(v);let g=[...u.values()];g.find(v=>v.id==="__system")||g.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:x,channels:m,initiators:g,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function Ht(t){let e=Nt();if(!e)return null;try{return Zn(e.db,he,t)}finally{e.close()}}function er(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let b=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:b})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=rl(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Vn(f.clientId),projects:[]}),f.projectId!==u.projectId){let b=e.get(f.clientId);b.projects.includes(f.projectId)||e.set(f.clientId,{...b,projects:[...b.projects,f.projectId].sort()})}o.push({...f,nodeId:c,id:`${c}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function rl(t){if(t.clientId!=="unmapped")return t;let e=jt(t.inputPreview);if(!e)return t;let a=he?.business?.projects??[];return{...t,projectId:e,clientId:Ue(e,a)}}async function st(t){let e=he?.channels?.gitlab,a=await Wn(Fn(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 he=null;function tr(t){he=t}async function ar(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Nt();if(!n)return ue(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=nr(parseInt(r.searchParams.get("hours")||"6",10));ue(e,200,await st(Zn(n.db,he,o)))}catch(r){ue(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var ol=5e3;async function Bt(t,e,a,n=Ht){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
7760
7760
 
7761
- `);let r=new URL(t.url||"/","http://_"),o=Yn(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
7761
+ `);let r=new URL(t.url||"/","http://_"),o=nr(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
7762
7762
 
7763
- `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await rt(p);if(s)break;u?(e.write(`event: snapshot
7763
+ `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await st(p);if(s)break;u?(e.write(`event: snapshot
7764
7764
  `),e.write(`data: ${JSON.stringify(u)}
7765
7765
 
7766
7766
  `)):e.write(`event: error
@@ -7769,7 +7769,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
7769
7769
  `)}catch(p){e.write(`event: error
7770
7770
  data: ${JSON.stringify({error:p?.message??String(p)})}
7771
7771
 
7772
- `)}let d=Date.now();for(;!s&&Date.now()-d<Gi;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Yn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Xi(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Lt(process.cwd(),".agentx/task-history",t,n);if(!Rt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Lt(process.cwd(),".agentx/task-history",t,o);return Rt(s)?Un(s,e,a):null}return Un(r,e,a)}function Un(t,e,a){let n=null,r=1/0;for(let o of Ni(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Hi(Di(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let d=Math.abs(l-e);d<r&&d<=a&&(n=s,r=d)}return n}async function Qn(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 pe(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=jt();if(!l)return pe(e,503,{error:"ledger not available"}),!0;try{let d=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return pe(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return pe(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(d.raw_json)}catch{}let b=Gn(d.source,f),w=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||b,T=null,g=null;if(p.agent_id){let k=Xi(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(T=k.responseText);let v=k.transcript;Array.isArray(v)&&(g=v.length)}}let E=fe?.business?.projects??[],c=fe?.business?.contactMap??[],m=xt(fe?.business??{}),h={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=Wn(d.source,f,c);if(x)h={client:x.client,project:x.project||`${x.client}/_chat`,via:`contactMap (channel=${x.channel??"*"}${x.username?` username=${x.username}`:""}${x.chatId?` chatId=${x.chatId}`:""})`};else if(d.project||at(f,d.subject,b)){let k=d.project||at(f,d.subject,b);h={client:ze(k,E),project:k,via:d.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=m.get(p.agent_id);k&&(h={client:k,project:`${k}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}pe(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:w,response:T,transcriptLen:g,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:h})}catch(d){pe(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Yi,readFileSync as Qi}from"fs";import{resolve as er}from"path";ft();function Zn(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=Ki.replace(/__AGENT_ID__/g,P(e));return $({title:`AgentX \xB7 ${P(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${P(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Ji,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>${Vi}</script>`})}var Ki=`
7772
+ `)}let c=Date.now();for(;!s&&Date.now()-c<ol;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function nr(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function sl(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Ot(process.cwd(),".agentx/task-history",t,n);if(!Dt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Ot(process.cwd(),".agentx/task-history",t,o);return Dt(s)?Jn(s,e,a):null}return Jn(r,e,a)}function Jn(t,e,a){let n=null,r=1/0;for(let o of Yi(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Qi(Vi(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function rr(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 ue(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Nt();if(!l)return ue(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 ue(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return ue(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(c.raw_json)}catch{}let b=Qn(c.source,f),w=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||b,T=null,E=null;if(p.agent_id){let k=sl(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(T=k.responseText);let v=k.transcript;Array.isArray(v)&&(E=v.length)}}let x=he?.business?.projects??[],d=he?.business?.contactMap??[],m=wt(he?.business??{}),h={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},g=Yn(c.source,f,d);if(g)h={client:g.client,project:g.project||`${g.client}/_chat`,via:`contactMap (channel=${g.channel??"*"}${g.username?` username=${g.username}`:""}${g.chatId?` chatId=${g.chatId}`:""})`};else if(c.project||rt(f,c.subject,b)){let k=c.project||rt(f,c.subject,b);h={client:Ue(k,x),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=m.get(p.agent_id);k&&(h={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}ue(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:w,response:T,transcriptLen:E,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:h})}catch(c){ue(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as dl,readFileSync as pl}from"fs";import{resolve as sr}from"path";vt();function or(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=il.replace(/__AGENT_ID__/g,P(e));return $({title:`AgentX \xB7 ${P(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${P(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:ll,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>${cl}</script>`})}var il=`
7773
7773
  <!-- Breadcrumb -->
7774
7774
  <div class="ax-crumb">
7775
7775
  <a href="/admin">Settings</a>
@@ -8358,7 +8358,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
8358
8358
  </div>
8359
8359
  </div>
8360
8360
  </div>
8361
- `,Ji=`
8361
+ `,ll=`
8362
8362
  /* Agent-specific layout + legacy styles for bits the migration left in
8363
8363
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
8364
8364
  * primitives live in components.css.ts. */
@@ -8477,7 +8477,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
8477
8477
 
8478
8478
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
8479
8479
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
8480
- `,Vi=`
8480
+ `,cl=`
8481
8481
  const $ = (id) => document.getElementById(id);
8482
8482
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
8483
8483
 
@@ -9333,15 +9333,15 @@ document.addEventListener('keydown', (e) => {
9333
9333
  /* ===== Boot ===== */
9334
9334
  initOptsToggles();
9335
9335
  loadAgent();
9336
- `;function tr(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zn({agentId:a,peers:n,localToken:r}))}async function ar(t,e,a){try{let n=t.method==="GET"?void 0:await yl(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){ot(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>je(i),"PATCH ":()=>Zi(i,n),"PATCH capability":()=>al(i,n),"POST mcp":()=>el(i,n),"DELETE mcp":()=>tl(i,n),"GET identity":()=>nl(i),"GET identity/file":()=>rl(i,String(o.path||"")),"PUT identity/file":()=>ol(i,n),"GET skills":()=>sl(i),"POST skills":()=>il(i,n),"DELETE skills":()=>ll(i,n),"GET skills/tree":()=>dl(i,String(o.slug||"")),"GET skills/file":()=>cl(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>pl(i,n),"GET skills/deps":()=>ul(i,String(o.slug||"")),"POST skills/install":()=>ml(i,n,t),"POST skills/deps":()=>fl(i,n,t),"GET channels":()=>hl(i),"GET activity":()=>gl(i,t),"GET handovers":()=>xl(i),"POST handovers":()=>vl(i,n),"DELETE handovers":()=>bl(n)}[d];if(!u){ot(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();ot(e,200,f)}catch(n){ot(e,400,{error:n?.message||"agent op failed"})}}function nr(){let t=er(process.cwd(),"agentx.json");return Yi(t)?JSON.parse(Qi(t,"utf-8")):null}function W(t){let e=nr();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 je(t){let{def:e,cfg:a}=W(t),n=e.workspace?ke(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 Zi(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:je(t)}}function el(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:je(t)}}function tl(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:je(t)}}function al(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:je(t)}}function nl(t){let{def:e}=W(t);return ke(e.workspace)}function rl(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return Fe(a.workspace,e)}function ol(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return We(n.workspace,a,String(e?.content??""))}function sl(t){let{def:e}=W(t),a=ke(e.workspace);return{skills:a.skills,workspace:a.workspace}}function il(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ge(n.workspace,a,{title:e?.title,content:e?.content})}function ll(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Xe(n.workspace,a)}function dl(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=Ea(a.workspace,e),r=Ke(a.workspace,e);return{slug:e,tree:n,deps:r}}function cl(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return Ta(n.workspace,e,a)}function pl(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=W(t);return Ca(r.workspace,a,n,String(e?.content??""))}function ul(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return Ke(a.workspace,e)}async function ml(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=rr(e?.worker),{def:o}=W(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(`
9337
- `);return or(a,r,s,`install-${n}:${Date.now()}`)}async function fl(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=rr(e?.worker),{def:o}=W(t),s=Ke(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=er(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(`
9338
- `);return or(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function rr(t){if(t&&typeof t=="string")return t;let e=Q();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function or(t,e,a,n){let r=Q(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),d=await l.text(),p;try{p=JSON.parse(d)}catch{p={content:d}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function hl(t){let e=nr(),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 gl(t,e){try{let n=(Q().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 Dt(){return new aa}function xl(t){let e=Dt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function vl(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,d=Dt().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function bl(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:Dt().remove(e,a,n)?"Released":"No active handover for that chat"}}function ot(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function yl(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 ye={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 sr=[{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 Nt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(ye)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9336
+ `;function ir(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(or({agentId:a,peers:n,localToken:r}))}async function lr(t,e,a){try{let n=t.method==="GET"?void 0:await Rl(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){it(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>je(i),"PATCH ":()=>ul(i,n),"PATCH capability":()=>hl(i,n),"POST mcp":()=>ml(i,n),"DELETE mcp":()=>fl(i,n),"GET identity":()=>gl(i),"GET identity/file":()=>xl(i,String(o.path||"")),"PUT identity/file":()=>vl(i,n),"GET skills":()=>bl(i),"POST skills":()=>yl(i,n),"DELETE skills":()=>wl(i,n),"GET skills/tree":()=>kl(i,String(o.slug||"")),"GET skills/file":()=>_l(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Sl(i,n),"GET skills/deps":()=>El(i,String(o.slug||"")),"POST skills/install":()=>Tl(i,n,t),"POST skills/deps":()=>Cl(i,n,t),"GET channels":()=>Al(i),"GET activity":()=>Ml(i,t),"GET handovers":()=>Il(i),"POST handovers":()=>$l(i,n),"DELETE handovers":()=>Ll(n)}[c];if(!u){it(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();it(e,200,f)}catch(n){it(e,400,{error:n?.message||"agent op failed"})}}function cr(){let t=sr(process.cwd(),"agentx.json");return dl(t)?JSON.parse(pl(t,"utf-8")):null}function W(t){let e=cr();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 je(t){let{def:e,cfg:a}=W(t),n=e.workspace?_e(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 ul(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:je(t)}}function ml(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:je(t)}}function fl(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:je(t)}}function hl(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:je(t)}}function gl(t){let{def:e}=W(t);return _e(e.workspace)}function xl(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return Ge(a.workspace,e)}function vl(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return Xe(n.workspace,a,String(e?.content??""))}function bl(t){let{def:e}=W(t),a=_e(e.workspace);return{skills:a.skills,workspace:a.workspace}}function yl(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ke(n.workspace,a,{title:e?.title,content:e?.content})}function wl(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Je(n.workspace,a)}function kl(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=$a(a.workspace,e),r=Ve(a.workspace,e);return{slug:e,tree:n,deps:r}}function _l(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return La(n.workspace,e,a)}function Sl(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=W(t);return Ra(r.workspace,a,n,String(e?.content??""))}function El(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return Ve(a.workspace,e)}async function Tl(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=dr(e?.worker),{def:o}=W(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(`
9337
+ `);return pr(a,r,s,`install-${n}:${Date.now()}`)}async function Cl(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=dr(e?.worker),{def:o}=W(t),s=Ve(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=sr(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(`
9338
+ `);return pr(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function dr(t){if(t&&typeof t=="string")return t;let e=Q();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function pr(t,e,a,n){let r=Q(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Al(t){let e=cr(),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 Ml(t,e){try{let n=(Q().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 zt(){return new ia}function Il(t){let e=zt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function $l(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=zt().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 Ll(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:zt().remove(e,a,n)?"Released":"No active handover for that chat"}}function it(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Rl(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 ye={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 ur=[{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 qt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(ye)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9339
9339
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
9340
9340
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
9341
9341
  <section id="statstrip" class="ax-statstrip"></section>
9342
9342
  <main id="grid" class="ax-live__body"></main>
9343
9343
  </div>
9344
- `;return $({title:`${ye.brand} \xB7 ${ye.subtitle}`,activeTab:"live",subtitle:ye.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:wl,scripts:e+`<script>${kl}</script>`,headExtras:`<script>
9344
+ `;return $({title:`${ye.brand} \xB7 ${ye.subtitle}`,activeTab:"live",subtitle:ye.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:jl,scripts:e+`<script>${Pl}</script>`,headExtras:`<script>
9345
9345
  // rightExtras for the topbar are injected at runtime \u2014 they reference
9346
9346
  // IDs (#ts, #conn-dot) that the script below addresses directly.
9347
9347
  document.addEventListener('DOMContentLoaded', () => {
@@ -9352,7 +9352,7 @@ loadAgent();
9352
9352
  extras.innerHTML = ${JSON.stringify(a)};
9353
9353
  right.insertBefore(extras, right.firstChild);
9354
9354
  });
9355
- </script>`})}var wl=`
9355
+ </script>`})}var jl=`
9356
9356
  /* --- Page frame --- */
9357
9357
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
9358
9358
 
@@ -9559,7 +9559,7 @@ loadAgent();
9559
9559
  border-top-color: var(--ax-accent); border-radius: 50%;
9560
9560
  animation: ax-spin 800ms linear infinite; display: inline-block;
9561
9561
  }
9562
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,kl=`
9562
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,Pl=`
9563
9563
  'use strict';
9564
9564
 
9565
9565
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -10130,7 +10130,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10130
10130
  });
10131
10131
  }
10132
10132
 
10133
- `;var ir=`
10133
+ `;var mr=`
10134
10134
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
10135
10135
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
10136
10136
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -10304,7 +10304,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10304
10304
  .mx-summary{max-width:56vw}
10305
10305
  }
10306
10306
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
10307
- `;var lr=`<script>
10307
+ `;var fr=`<script>
10308
10308
  window.MX=(function(){
10309
10309
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
10310
10310
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -10413,7 +10413,7 @@ window.MX=(function(){
10413
10413
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
10414
10414
  setHealth:setHealth,get:get};
10415
10415
  })();
10416
- </script>`;var dr=`<script>
10416
+ </script>`;var hr=`<script>
10417
10417
  window.MXD=(function(){
10418
10418
  function el(id){return document.getElementById(id)}
10419
10419
  function tz(){return -new Date().getTimezoneOffset()}
@@ -10627,7 +10627,7 @@ window.MXD=(function(){
10627
10627
 
10628
10628
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
10629
10629
  })();
10630
- </script>`;var cr=`<script>
10630
+ </script>`;var gr=`<script>
10631
10631
  (function(){
10632
10632
  var LANES=[
10633
10633
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -10943,7 +10943,7 @@ window.MXD=(function(){
10943
10943
  window.addEventListener('scroll',hideTip,{passive:true});
10944
10944
  load();
10945
10945
  })();
10946
- </script>`;var pr=`<script>
10946
+ </script>`;var xr=`<script>
10947
10947
  (function(){
10948
10948
  var showAll=document.getElementById('mx-show-all'),expanded=false;
10949
10949
  var esc=MX.esc;
@@ -11121,7 +11121,7 @@ window.MXD=(function(){
11121
11121
  }
11122
11122
  load();setInterval(load,5000);
11123
11123
  })();
11124
- </script>`;var ur=`
11124
+ </script>`;var vr=`
11125
11125
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
11126
11126
  .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}
11127
11127
  .mx-rt-wrap > .mx-empty{border:0}
@@ -11162,7 +11162,7 @@ window.MXD=(function(){
11162
11162
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
11163
11163
  .mx-rt-name{max-width:100%}
11164
11164
  }
11165
- `,mr=`<script>
11165
+ `,br=`<script>
11166
11166
  (function(){
11167
11167
  var root=document.getElementById('mx-routines');
11168
11168
  var bar=document.getElementById('mx-rt-filter');
@@ -11289,7 +11289,7 @@ window.MXD=(function(){
11289
11289
  syncBar();
11290
11290
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
11291
11291
  })();
11292
- </script>`;var fr=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],hr=`<script>
11292
+ </script>`;var yr=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],wr=`<script>
11293
11293
  (function(){
11294
11294
  var root=document.getElementById('mx-feed');
11295
11295
  if(!root)return;
@@ -11364,12 +11364,12 @@ window.MXD=(function(){
11364
11364
  }
11365
11365
  load();setInterval(load,5000);
11366
11366
  })();
11367
- </script>`;var K={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 J(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var _l=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Sl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],El=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function gr(t){let e=Je({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Ve([{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">
11367
+ </script>`;var K={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 J(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Ol=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Dl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Nl=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function kr(t){let e=Ye({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Qe([{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">
11368
11368
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
11369
- ${Sl.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("")}
11369
+ ${Dl.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("")}
11370
11370
  </div>
11371
11371
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
11372
- ${El.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11372
+ ${Nl.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11373
11373
  </div>
11374
11374
  </div>
11375
11375
  <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">
@@ -11422,7 +11422,7 @@ window.MXD=(function(){
11422
11422
  <section class="mx-section" aria-labelledby="mx-routines-title">
11423
11423
  ${J(K.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>')}
11424
11424
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
11425
- ${_l.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11425
+ ${Ol.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11426
11426
  </div>
11427
11427
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
11428
11428
  </section>
@@ -11430,7 +11430,7 @@ window.MXD=(function(){
11430
11430
  <section class="mx-section" aria-labelledby="mx-feed-title">
11431
11431
  ${J(K.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>')}
11432
11432
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
11433
- ${fr.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11433
+ ${yr.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11434
11434
  </div>
11435
11435
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
11436
11436
  </section>
@@ -11463,7 +11463,7 @@ window.MXD=(function(){
11463
11463
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
11464
11464
  </header>
11465
11465
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
11466
- </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:ir+ur,scripts:lr+Tl+dr+cr+mr+pr+hr})}var Tl=`<script>
11466
+ </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:mr+vr,scripts:fr+Hl+hr+gr+br+xr+wr})}var Hl=`<script>
11467
11467
  (function(){
11468
11468
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
11469
11469
  var range=document.getElementById('mx-range');
@@ -11491,7 +11491,7 @@ window.MXD=(function(){
11491
11491
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
11492
11492
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
11493
11493
  })();
11494
- </script>`;async function xr(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Cl(s,e.days)}function Cl(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],d=0,p=0,u=0,f=0,b=0,w=0;for(let{node:g,data:E}of t)if(E){a.runs+=E.totals.runs,a.errors+=E.totals.errors,a.hours+=E.totals.hours,a.agents+=E.totals.agents,a.threads+=E.totals.threads;for(let c of E.days){let m=n.get(c.day)||{day:c.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])m[h][0]+=c[h]?.[0]||0,m[h][1]+=c[h]?.[1]||0;n.set(c.day,m)}for(let c of E.origins){let m=r.get(c.channel)||{channel:c.channel,runs:0,errors:0,hours:0};m.runs+=c.runs,m.errors+=c.errors,m.hours+=c.hours,r.set(c.channel,m)}for(let c of E.causes){let m=o.get(c.cause)||{cause:c.cause,count:0,agents:[],example:""};m.count+=c.count;for(let h of c.agents)m.agents.includes(h)||m.agents.push(h);m.example||(m.example=c.example),o.set(c.cause,m)}for(let c of E.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=E.rotations.total,p+=E.rotations.tokenSum||0,u+=E.rotations.tokenSamples||0,f=Math.max(f,E.rotations.maxTokens),b+=E.retention.traces,w+=E.retention.tracesWithSteps;for(let c of E.jobs)i.push({...c,node:g.name,nodeUrl:g.url});for(let c of E.threads)l.push({...c,node:g.name,nodeUrl:g.url})}let T=t.filter(g=>g.data).map(g=>g.data.since).filter(g=>Number.isFinite(g));return{generatedAt:Date.now(),windowDays:e,since:T.length?Math.min(...T):Date.now()-e*864e5,nodes:t.map(g=>({name:g.node.name,url:g.node.url,ok:!!g.data,error:g.error,runs:g.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((g,E)=>g.day.localeCompare(E.day)),origins:[...r.values()].map(g=>({...g,hours:Math.round(g.hours*100)/100})).sort((g,E)=>E.runs-g.runs),causes:[...o.values()].sort((g,E)=>E.count-g.count),jobs:i.sort((g,E)=>E.hours-g.hours),threads:l.sort((g,E)=>E.lastAt-E.firstAt-(g.lastAt-g.firstAt)||E.runs-g.runs),rotations:{total:d,byReason:[...s.entries()].map(([g,E])=>({reason:g,count:E})).sort((g,E)=>E.count-g.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:b,tracesWithSteps:w}}}async function vr(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 br(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let d=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return d.ok?{node:i,data:await d.json()}:{node:i,error:`HTTP ${d.status}`}}catch(d){return{node:i,error:d?.name==="AbortError"?"timeout":d?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Al(s,e.day)}function Al(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let d=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};d.runs+=l.runs,d.errors+=l.errors,d.ms+=l.ms,n.set(l.channel,d)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function yr(t={}){let e=`
11494
+ </script>`;async function _r(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 Bl(s,e.days)}function Bl(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,u=0,f=0,b=0,w=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 d of x.days){let m=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let h of["cron","workflow","direct"])m[h][0]+=d[h]?.[0]||0,m[h][1]+=d[h]?.[1]||0;n.set(d.day,m)}for(let d of x.origins){let m=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};m.runs+=d.runs,m.errors+=d.errors,m.hours+=d.hours,r.set(d.channel,m)}for(let d of x.causes){let m=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};m.count+=d.count;for(let h of d.agents)m.agents.includes(h)||m.agents.push(h);m.example||(m.example=d.example),o.set(d.cause,m)}for(let d of x.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=x.rotations.total,p+=x.rotations.tokenSum||0,u+=x.rotations.tokenSamples||0,f=Math.max(f,x.rotations.maxTokens),b+=x.retention.traces,w+=x.retention.tracesWithSteps;for(let d of x.jobs)i.push({...d,node:E.name,nodeUrl:E.url});for(let d of x.threads)l.push({...d,node:E.name,nodeUrl:E.url})}let T=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:T.length?Math.min(...T):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:p,tokenSamples:u,maxTokens:f},retention:{traces:b,tracesWithSteps:w}}}async function Sr(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 Er(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 zl(s,e.day)}function zl(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 Tr(t={}){let e=`
11495
11495
  <select id="boardPicker" title="Switch board"></select>
11496
11496
  <div class="search">
11497
11497
  <span class="icon">\u2315</span>
@@ -11592,7 +11592,7 @@ window.MXD=(function(){
11592
11592
  </footer>
11593
11593
  </div>
11594
11594
  </div>
11595
- <script src="/sortable.min.js"></script>`;return $({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Ml,scripts:`<script>${Il}</script>`,headExtras:`<script>
11595
+ <script src="/sortable.min.js"></script>`;return $({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:ql,scripts:`<script>${Ul}</script>`,headExtras:`<script>
11596
11596
  // The boards page has its own connection dot + wants body height:100%
11597
11597
  // for the full-viewport kanban layout. Inject the dot into the topbar
11598
11598
  // and override body height at runtime so the shared shell doesn't
@@ -11608,7 +11608,7 @@ window.MXD=(function(){
11608
11608
  right.insertBefore(dot, right.firstChild);
11609
11609
  }
11610
11610
  });
11611
- </script>`})}var Ml=`
11611
+ </script>`})}var ql=`
11612
11612
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
11613
11613
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
11614
11614
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -11861,7 +11861,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
11861
11861
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
11862
11862
  .draft-box .draft-row .hint.err { color: var(--red); }
11863
11863
  .draft-box .draft-row .hint.ok { color: var(--green); }
11864
- `,Il=`
11864
+ `,Ul=`
11865
11865
  'use strict';
11866
11866
  const state = {
11867
11867
  boards: [], current: null, items: {},
@@ -12914,9 +12914,9 @@ function appendEvents(events) {
12914
12914
  }
12915
12915
 
12916
12916
  loadBoards().catch(e => toast('Init failed: ' + e.message));
12917
- `;function wr(t={}){let a=`<h1>Plain-English glossary</h1>
12917
+ `;function Cr(t={}){let a=`<h1>Plain-English glossary</h1>
12918
12918
  <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>
12919
- ${sr.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${P(n.alias)}</span>`:"";return`<article class="term"><h3>${P(n.term)}${r}</h3><p>${P(n.definition)}</p></article>`}).join("")}`;return $({title:`${ye.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:$l})}var $l=`
12919
+ ${ur.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${P(n.alias)}</span>`:"";return`<article class="term"><h3>${P(n.term)}${r}</h3><p>${P(n.definition)}</p></article>`}).join("")}`;return $({title:`${ye.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Fl})}var Fl=`
12920
12920
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
12921
12921
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
12922
12922
  .lead {
@@ -12946,7 +12946,7 @@ article.term .alias {
12946
12946
  }
12947
12947
  article.term p {
12948
12948
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
12949
- }`;function kr(t={}){let e=`<div class="ax-wf__root">
12949
+ }`;function Ar(t={}){let e=`<div class="ax-wf__root">
12950
12950
  <aside class="ax-wf__list">
12951
12951
  <header>
12952
12952
  <h2>Workflows</h2>
@@ -13023,7 +13023,7 @@ article.term p {
13023
13023
  </aside>
13024
13024
  </div>
13025
13025
 
13026
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return $({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ll,scripts:`<script>${me({workflowHealth:la})}${Rl}</script>`})}var Ll=`
13026
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return $({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Wl,scripts:`<script>${ee({workflowHealth:ma})}${Gl}</script>`})}var Wl=`
13027
13027
  .ax-wf__root {
13028
13028
  display: grid;
13029
13029
  grid-template-columns: 340px 1fr;
@@ -13407,7 +13407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13407
13407
  font-size: 12px; z-index: 50;
13408
13408
  }
13409
13409
  .hint { color: var(--ax-muted); font-size: 11px; }
13410
- `,Rl=`
13410
+ `,Gl=`
13411
13411
  (() => {
13412
13412
  const $ = (sel) => document.querySelector(sel)
13413
13413
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -14196,7 +14196,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14196
14196
  setInterval(refresh, 15000)
14197
14197
  })
14198
14198
  })();
14199
- `;function _r(t={}){let e=`<div class="ax-proc__root">
14199
+ `;function Mr(t={}){let e=`<div class="ax-proc__root">
14200
14200
  <header class="ax-proc__header">
14201
14201
  <h1>Procedures</h1>
14202
14202
  <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>
@@ -14240,7 +14240,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14240
14240
  <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>
14241
14241
  <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>
14242
14242
  </section>
14243
- </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:jl,scripts:`<script>${Pl}</script>`})}var jl=`
14243
+ </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Xl,scripts:`<script>${Kl}</script>`})}var Xl=`
14244
14244
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
14245
14245
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
14246
14246
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -14266,7 +14266,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14266
14266
  .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); }
14267
14267
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
14268
14268
  .ax-proc__link:hover { text-decoration: underline; }
14269
- `,Pl=`
14269
+ `,Kl=`
14270
14270
  (function(){
14271
14271
  function $(sel){ return document.querySelector(sel) }
14272
14272
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -14366,7 +14366,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14366
14366
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
14367
14367
  else bootAll()
14368
14368
  })();
14369
- `;function Sr(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14369
+ `;function Ir(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14370
14370
  data-task-id="${P(t.taskId)}"
14371
14371
  data-agent-id="${P(t.agentId)}"
14372
14372
  data-node-url="${P(t.nodeUrl)}"
@@ -14409,7 +14409,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14409
14409
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
14410
14410
  </div>
14411
14411
  </footer>
14412
- </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ol,scripts:`<script>${Dl}</script>`})}var Ol=`
14412
+ </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Jl,scripts:`<script>${Vl}</script>`})}var Jl=`
14413
14413
  /* The shell gives <main> no padding, so page content butted straight against
14414
14414
  the sticky topbar. Breathe. */
14415
14415
  .ax-task-page {
@@ -14551,7 +14551,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14551
14551
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
14552
14552
  }
14553
14553
 
14554
- `,Dl=`
14554
+ `,Vl=`
14555
14555
  (function () {
14556
14556
  var root = document.querySelector('.ax-task-page');
14557
14557
  if (!root) return;
@@ -14936,7 +14936,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14936
14936
  });
14937
14937
 
14938
14938
  })();
14939
- `;function Er(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14939
+ `;function $r(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14940
14940
  data-agent-id="${P(t.agentId)}"
14941
14941
  data-agent-name="${P(e)}"
14942
14942
  data-node-url="${P(t.nodeUrl)}">
@@ -14965,7 +14965,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14965
14965
  <div class="ax-history__list" id="hist-list">
14966
14966
  <div class="ax-history__empty">loading\u2026</div>
14967
14967
  </div>
14968
- </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Nl,scripts:`<script>${Hl}</script>`})}var Nl=`
14968
+ </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Yl,scripts:`<script>${Ql}</script>`})}var Yl=`
14969
14969
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
14970
14970
  flush against the sticky topbar. */
14971
14971
  .ax-history {
@@ -15017,7 +15017,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15017
15017
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
15018
15018
  }
15019
15019
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
15020
- `,Hl=`
15020
+ `,Ql=`
15021
15021
  (function () {
15022
15022
  var root = document.querySelector('.ax-history');
15023
15023
  if (!root) return;
@@ -15117,24 +15117,24 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15117
15117
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15118
15118
  });
15119
15119
  })();
15120
- `;function Cr(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?L(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return Te(t,e,l=>Tr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:zl(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return L(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Te(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return L(e,200,{ok:!0,emission:d})}):L(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?L(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Te(t,e,l=>{try{let d=a.layouts.save(s,l);return L(e,200,{layout:d})}catch(d){return L(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Te(t,e,l=>{let d=ht.safeParse(l);if(!d.success)return L(e,200,{ok:!1,issues:d.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=gt(d.data).map(u=>({path:"",message:u}));return L(e,200,{ok:p.length===0,issues:p,workflow:d.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?L(e,200,{workflow:l}):L(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,d=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Te(t,e,p=>Tr(e,a,p,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),L(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return L(e,404,{error:"unknown workflows endpoint",path:n})}var Bl=["mesh"];function Tr(t,e,a,n){let r=ht.safeParse(a);if(!r.success)return L(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=gt(o);if(s.length>0)return L(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return L(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return L(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,d=e.store.get(n.id);if(d)for(let p of Bl)!(p in l)&&p in d&&(o[p]=d[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let d=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(d);return L(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":d,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),L(t,200,{workflow:i})}function zl(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:d,limit:l});if(!p)return L(e,200,{runs:u});let f=u.map(b=>({id:b.id,workflowId:b.workflowId,workflowVersion:b.workflowVersion,homeNode:b.homeNode,status:b.status,pending:b.pending,entityRef:b.entityRef,history:(b.history||[]).slice(-5),parentRunId:b.parentRunId,parentNodeId:b.parentNodeId,rootRunId:b.rootRunId,depth:b.depth,createdAt:b.createdAt,updatedAt:b.updatedAt}));return L(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Te(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?L(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?L(e,200,{ok:!0,runId:l,status:p}):L(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return ql(t,e,a,l);let d=a.runs.get(l);return d?L(e,200,{run:d}):L(e,404,{error:"run not found"})}return L(e,404,{error:"unknown runs endpoint"})}function ql(t,e,a,n){let r=a.runs.get(n);if(!r)return L(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
15120
+ `;function Rr(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?L(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return Ce(t,e,l=>Lr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:ec(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return L(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Ce(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return L(e,200,{ok:!0,emission:c})}):L(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?L(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Ce(t,e,l=>{try{let c=a.layouts.save(s,l);return L(e,200,{layout:c})}catch(c){return L(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Ce(t,e,l=>{let c=bt.safeParse(l);if(!c.success)return L(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=yt(c.data).map(u=>({path:"",message:u}));return L(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?L(e,200,{workflow:l}):L(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return Ce(t,e,p=>Lr(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),L(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return L(e,404,{error:"unknown workflows endpoint",path:n})}var Zl=["mesh"];function Lr(t,e,a,n){let r=bt.safeParse(a);if(!r.success)return L(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=yt(o);if(s.length>0)return L(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return L(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return L(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,c=e.store.get(n.id);if(c)for(let p of Zl)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(c);return L(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),L(t,200,{workflow:i})}function ec(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return L(e,200,{runs:u});let f=u.map(b=>({id:b.id,workflowId:b.workflowId,workflowVersion:b.workflowVersion,homeNode:b.homeNode,status:b.status,pending:b.pending,entityRef:b.entityRef,history:(b.history||[]).slice(-5),parentRunId:b.parentRunId,parentNodeId:b.parentNodeId,rootRunId:b.rootRunId,depth:b.depth,createdAt:b.createdAt,updatedAt:b.updatedAt}));return L(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return L(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Ce(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?L(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?L(e,200,{ok:!0,runId:l,status:p}):L(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return tc(t,e,a,l);let c=a.runs.get(l);return c?L(e,200,{run:c}):L(e,404,{error:"run not found"})}return L(e,404,{error:"unknown runs endpoint"})}function tc(t,e,a,n){let r=a.runs.get(n);if(!r)return L(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
15121
15121
 
15122
15122
  `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
15123
15123
 
15124
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),d=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==d&&(d=u.updatedAt,i(u))},2e3);return!0}function Te(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){L(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{L(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{L(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>L(e,400,{error:"body read failed",message:r.message})),!0}function L(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{deflateSync as Ul}from"zlib";var Fl=[41,121,255],Wl=[255,255,255],Ar=new Map;function Bt(t){let e=Ar.get(t);return e||(e=Xl(t,Gl(t)),Ar.set(t,e)),e}function Gl(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,d=i*i+l*l<=r*r?Wl:Fl;a.set(d,o*e+1+s*3)}return a}function Xl(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Ht("IHDR",a),Ht("IDAT",Ul(e)),Ht("IEND",Buffer.alloc(0))])}function Ht(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(Jl(n)),Buffer.concat([a,n,r])}var Kl=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 Jl(t){let e=4294967295;for(let a of t)e=Kl[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function st(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Vl(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:st(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:st(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:st(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Yl(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:st(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Ql=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Mr(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let b=Zl(s.searchParams.get("timezone")),w=await o.snapshot({date:ed(b),timezone:b});return a==="/api/app/activity"?se(e,200,{ts:w.ts,tasks:Yl(w.nodes)}):se(e,200,{ts:w.ts,nodes:w.nodes.map(Vl)})}if(n==="GET"&&a==="/api/app/approvals")return se(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Ql);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let d;try{d=await we(t)}catch(b){return se(e,400,{error:b.message})}let p=Pe(d.node);if(!p)return se(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let b=Pe(d.taskId);if(!b)return se(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(b)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Pe(d.message);if(!T)return se(e,400,{error:"message is required"});f=await o.nodePost(p,w,{message:T,sender:u})}}else if(a==="/api/app/nodes/restart")f=await o.nodePost(p,d.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")f=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let b=Pe(d.cronId);if(!b||typeof d.enabled!="boolean")return se(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(b)}/enabled`,{enabled:d.enabled})}else{let b=Pe(d.key),w=d.action;if(!b||w!=="yes"&&w!=="no"&&w!=="later")return se(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,b,w,u)}return se(e,f.status,f.body)}function Pe(t){return typeof t=="string"?t.trim():""}function Zl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function ed(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function we(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function se(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var td=2048,Ir=/^[A-Za-z0-9_-]{8,256}$/;async function $r(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return ie(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(b=>b.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return ie(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return ie(e,404,{error:"not found"});if(!s||l)return ie(e,503,{error:l});let d;try{d=await we(t)}catch(b){return ie(e,400,{error:b.message})}let p=ad(d.endpoint,o.allowedHosts);if(!p){let b="";try{b=new URL(String(d.endpoint)).hostname}catch{}return ie(e,400,{error:`not a known push service${b?`: ${b}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return ie(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=d.keys?.p256dh,f=d.keys?.auth;return typeof u!="string"||!Ir.test(u)||typeof f!="string"||!Ir.test(f)?ie(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?ie(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),ie(e,200,{ok:!0}))}function ad(t,e){if(typeof t!="string"||t.length>td)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function ie(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var nd=50;function rd(t){let e={channel:"app",chatId:t.chatId};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 Lr(t,e,a,n){let{path:r,body:o}=rd(e),s="",i=[],l=new Map,d=(p,u,f)=>{let{cleanText:b,ui:w}=p==="done"?ca(u):{cleanText:u,ui:void 0},T=sd(w);return{status:p,text:b,tools:i,...T?{ui:T}:{},...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}`}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let u=await p.json().then(f=>f?.error).catch(()=>"");return d("error",s,u||`AgentX answered HTTP ${p.status}.`)}for await(let u of id(p.body)){n(u.event,u.data);let f=u.data??{};if(u.event==="text"&&typeof f.text=="string")s+=f.text;else if(u.event==="tool"&&f.status==="start"&&i.length<nd){let b={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(b),f.id&&l.set(String(f.id),b)}else if(u.event==="tool"&&f.status==="result"&&f.error===!0&&l.has(String(f.id)))l.get(String(f.id)).error=!0;else{if(u.event==="done")return d("done",typeof f.content=="string"&&f.content?f.content:s);if(u.event==="error")return d("error",s,od(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 od(t){let e=String(t||"The agent could not answer.");return e.startsWith("__queued__")?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function sd(t){if(!t)return;let e=r=>/^https?:\/\//i.test(r)&&r.length<=2048,a={},n=(t.buttons??[]).filter(r=>e(r.url)).slice(0,8).map(r=>({label:r.label.slice(0,80),url:r.url}));return n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(r=>r.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)}:{}}),Object.keys(a).length?a:void 0}async function*id(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,`
15124
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function Ce(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){L(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{L(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{L(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>L(e,400,{error:"body read failed",message:r.message})),!0}function L(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Pc}from"fs";import{createRequire as Oc}from"module";import{deflateSync as ac}from"zlib";var nc=[41,121,255],rc=[255,255,255],jr=new Map;function Ft(t){let e=jr.get(t);return e||(e=sc(t,oc(t)),jr.set(t,e)),e}function oc(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,c=i*i+l*l<=r*r?rc:nc;a.set(c,o*e+1+s*3)}return a}function sc(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),Ut("IHDR",a),Ut("IDAT",ac(e)),Ut("IEND",Buffer.alloc(0))])}function Ut(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(lc(n)),Buffer.concat([a,n,r])}var ic=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 lc(t){let e=4294967295;for(let a of t)e=ic[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function lt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function cc(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:lt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:lt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:lt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function dc(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:lt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var pc=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Pr(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let b=uc(s.searchParams.get("timezone")),w=await o.snapshot({date:mc(b),timezone:b});return a==="/api/app/activity"?ie(e,200,{ts:w.ts,tasks:dc(w.nodes)}):ie(e,200,{ts:w.ts,nodes:w.nodes.map(cc)})}if(n==="GET"&&a==="/api/app/approvals")return ie(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(pc);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await we(t)}catch(b){return ie(e,400,{error:b.message})}let p=Pe(c.node);if(!p)return ie(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let b=Pe(c.taskId);if(!b)return ie(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(b)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Pe(c.message);if(!T)return ie(e,400,{error:"message is required"});f=await o.nodePost(p,w,{message:T,sender:u})}}else if(a==="/api/app/nodes/restart")f=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")f=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let b=Pe(c.cronId);if(!b||typeof c.enabled!="boolean")return ie(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(b)}/enabled`,{enabled:c.enabled})}else{let b=Pe(c.key),w=c.action;if(!b||w!=="yes"&&w!=="no"&&w!=="later")return ie(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,b,w,u)}return ie(e,f.status,f.body)}function Pe(t){return typeof t=="string"?t.trim():""}function uc(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function mc(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function we(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function ie(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var fc=2048,Or=/^[A-Za-z0-9_-]{8,256}$/;async function Dr(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return le(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(b=>b.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return le(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return le(e,404,{error:"not found"});if(!s||l)return le(e,503,{error:l});let c;try{c=await we(t)}catch(b){return le(e,400,{error:b.message})}let p=hc(c.endpoint,o.allowedHosts);if(!p){let b="";try{b=new URL(String(c.endpoint)).hostname}catch{}return le(e,400,{error:`not a known push service${b?`: ${b}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return le(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Or.test(u)||typeof f!="string"||!Or.test(f)?le(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?le(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),le(e,200,{ok:!0}))}function hc(t,e){if(typeof t!="string"||t.length>fc)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function le(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var gc=50;function xc(t){let e={channel:"app",chatId:t.chatId};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 Nr(t,e,a,n){let{path:r,body:o}=xc(e),s="",i=[],l=new Map,c=(p,u,f)=>{let{cleanText:b,ui:w}=p==="done"?ha(u):{cleanText:u,ui:void 0},T=bc(w);return{status:p,text:b,tools:i,...T?{ui:T}:{},...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}`}:{}},body:JSON.stringify(o),signal:a});if(!p.ok||!p.body){let u=await p.json().then(f=>f?.error).catch(()=>"");return c("error",s,u||`AgentX answered HTTP ${p.status}.`)}for await(let u of yc(p.body)){n(u.event,u.data);let f=u.data??{};if(u.event==="text"&&typeof f.text=="string")s+=f.text;else if(u.event==="tool"&&f.status==="start"&&i.length<gc){let b={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(b),f.id&&l.set(String(f.id),b)}else if(u.event==="tool"&&f.status==="result"&&f.error===!0&&l.has(String(f.id)))l.get(String(f.id)).error=!0;else{if(u.event==="done")return c("done",typeof f.content=="string"&&f.content?f.content:s);if(u.event==="error")return c("error",s,vc(f.error))}}return a.aborted?c("stopped",s):c("error",s,"The connection to the agent closed before it answered.")}catch(p){return a.aborted?c("stopped",s):c("error",s,`Could not reach AgentX: ${p?.message||p}`)}}function vc(t){let e=String(t||"The agent could not answer.");return e.startsWith("__queued__")?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function bc(t){if(!t)return;let e=r=>/^https?:\/\//i.test(r)&&r.length<=2048,a={},n=(t.buttons??[]).filter(r=>e(r.url)).slice(0,8).map(r=>({label:r.label.slice(0,80),url:r.url}));return n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(r=>r.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)}:{}}),Object.keys(a).length?a:void 0}async function*yc(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,`
15125
15125
  `);let s;for(;(s=n.indexOf(`
15126
15126
 
15127
- `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
15128
- `))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&d.push(p.slice(5).replace(/^ /,""));if(d.length)try{yield{event:l,data:JSON.parse(d.join(`
15129
- `))}}catch{}}}}finally{e.releaseLock()}}var it=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];orphaned=!1;listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
15127
+ `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
15128
+ `))p.startsWith("event:")?l=p.slice(6).trim():p.startsWith("data:")&&c.push(p.slice(5).replace(/^ /,""));if(c.length)try{yield{event:l,data:JSON.parse(c.join(`
15129
+ `))}}catch{}}}}finally{e.releaseLock()}}var ct=class{constructor(e){this.orphanLimitMs=e}ac=new AbortController;text="";tools=[];orphaned=!1;listeners=new Map;orphanTimer=null;done=!1;broadcast(e,a){e==="text"&&typeof a?.text=="string"&&(this.text+=a.text),e==="tool"&&a?.status==="start"&&this.tools.length<50&&this.tools.push({name:String(a.name||"tool"),...a.arg?{arg:String(a.arg)}:{}});for(let n of this.listeners.keys())n(e,a)}attach(e){let a=()=>!e.writableEnded&&!e.destroyed,n=(o,s)=>{a()&&e.write(`event: ${o}
15130
15130
  data: ${JSON.stringify(s)}
15131
15131
 
15132
15132
  `)},r=setInterval(()=>{a()&&e.write(`: ping
15133
15133
 
15134
- `)},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()}};var jr=8e3,ld=/^[A-Za-z0-9_.:-]{1,64}$/,Ce=new Map;async function Pr(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/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await Or(o)});let s=o.store();if(!s)return D(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return D(e,200,{conversations:s.list(r.id)});let i=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(i){let d=s.get(r.id,decodeURIComponent(i[1]));if(!d)return D(e,404,{error:"no such conversation"});let p=Ce.get(d.id);return D(e,200,{...d,running:!!p,...p?{partial:{text:p.text,tools:p.tools}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=s.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=d&&Ce.get(d.id);if(!d||!p)return D(e,404,{error:"nothing is running in this conversation"});Dr(e);let{id:u,title:f,node:b,nodeName:w,agent:T,agentName:g}=d;return e.write(zt("conversation",{id:u,title:f,node:b,nodeName:w,agent:T,agentName:g})),e.write(zt("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return D(e,404,{error:"not found"});let l;try{l=await we(t,64*1024)}catch(d){return D(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=s.get(r.id,String(l.conversationId??""));if(!d)return D(e,404,{error:"no such conversation"});let p=Ce.get(d.id);return p?(p.ac.abort(),qt(d,o,r.name),D(e,200,{stopped:!0})):await qt(d,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await cd(e,l,r,s,o),!0}function dd(t,e,a){let n=Ae(e.url),r=new Set,o=[];for(let s of t){let i=Ae(s.url),l=a.find(u=>Ae(u.peerUrl)===i);l&&r.add(l.peer);let d=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:d?"local":l?l.peer:null,name:s.reachable?s.name:(d?e.name:l?.peer)||s.name,online:d?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Or(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return dd(e.nodes,t.daemon,a)}async function cd(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>jr){D(t,400,{error:`message must be 1\u2013${jr} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!ld.test(T)){D(t,400,{error:"pick an agent"});return}let g=(await Or(r)).find(c=>c.target===w);if(!g){D(t,400,{error:`unknown node "${w}"`});return}if(!g.online){D(t,409,{error:`${g.name} is offline`});return}let E=g.agents.find(c=>c.id===T);if(!E){D(t,400,{error:`no agent "${T}" on ${g.name}`});return}s=n.create(a.id,{node:w,nodeName:g.name,agent:T,agentName:E.name},o)}if(Ce.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new it(r.orphanLimitMs??18e5);Ce.set(s.id,i),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()});let{id:l,title:d,node:p,nodeName:u,agent:f,agentName:b}=s;Dr(t),t.write(zt("conversation",{id:l,title:d,node:p,nodeName:u,agent:f,agentName:b})),i.attach(t);try{let w=await Lr(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`},i.ac.signal,(T,g)=>i.broadcast(T,g));i.orphaned&&(w.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,qt(s,r,a.name)),n.append(a.id,l,{role:"assistant",content:w.text,status:w.status,at:Date.now(),...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{},...w.tools.length?{tools:w.tools}:{}}),i.broadcast("final",{status:w.status,content:w.text,...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{}})}finally{Ce.delete(l),i.finish()}}function Dr(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function zt(t,e){return`event: ${t}
15134
+ `)},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()}};var Br=8e3,wc=/^[A-Za-z0-9_.:-]{1,64}$/,Ae=new Map;async function zr(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/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await qr(o)});let s=o.store();if(!s)return D(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return D(e,200,{conversations:s.list(r.id)});let i=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(i){let c=s.get(r.id,decodeURIComponent(i[1]));if(!c)return D(e,404,{error:"no such conversation"});let p=Ae.get(c.id);return D(e,200,{...c,running:!!p,...p?{partial:{text:p.text,tools:p.tools}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let c=s.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),p=c&&Ae.get(c.id);if(!c||!p)return D(e,404,{error:"nothing is running in this conversation"});Ur(e);let{id:u,title:f,node:b,nodeName:w,agent:T,agentName:E}=c;return e.write(Wt("conversation",{id:u,title:f,node:b,nodeName:w,agent:T,agentName:E})),e.write(Wt("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return D(e,404,{error:"not found"});let l;try{l=await we(t,64*1024)}catch(c){return D(e,400,{error:c.message})}if(a==="/api/app/chat/stop"){let c=s.get(r.id,String(l.conversationId??""));if(!c)return D(e,404,{error:"no such conversation"});let p=Ae.get(c.id);return p?(p.ac.abort(),Gt(c,o,r.name),D(e,200,{stopped:!0})):await Gt(c,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await _c(e,l,r,s,o),!0}function kc(t,e,a){let n=Me(e.url),r=new Set,o=[];for(let s of t){let i=Me(s.url),l=a.find(u=>Me(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function qr(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return kc(e.nodes,t.daemon,a)}async function _c(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Br){D(t,400,{error:`message must be 1\u2013${Br} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!wc.test(T)){D(t,400,{error:"pick an agent"});return}let E=(await qr(r)).find(d=>d.target===w);if(!E){D(t,400,{error:`unknown node "${w}"`});return}if(!E.online){D(t,409,{error:`${E.name} is offline`});return}let x=E.agents.find(d=>d.id===T);if(!x){D(t,400,{error:`no agent "${T}" on ${E.name}`});return}s=n.create(a.id,{node:w,nodeName:E.name,agent:T,agentName:x.name},o)}if(Ae.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new ct(r.orphanLimitMs??18e5);Ae.set(s.id,i),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()});let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:b}=s;Ur(t),t.write(Wt("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:b})),i.attach(t);try{let w=await Nr(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`},i.ac.signal,(T,E)=>i.broadcast(T,E));i.orphaned&&(w.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Gt(s,r,a.name)),n.append(a.id,l,{role:"assistant",content:w.text,status:w.status,at:Date.now(),...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{},...w.tools.length?{tools:w.tools}:{}}),i.broadcast("final",{status:w.status,content:w.text,...w.error?{error:w.error}:{},...w.ui?{ui:w.ui}:{}})}finally{Ae.delete(l),i.finish()}}function Ur(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Wt(t,e){return`event: ${t}
15135
15135
  data: ${JSON.stringify(e)}
15136
15136
 
15137
- `}async function qt(t,e,a){try{let n=Ae(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Ae(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ae(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 Ae(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Hr=8e3;async function Br(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return G(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let f=String(t.headers["content-type"]||"");if(!ka(f))return G(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let b=wa(t.headers["x-audio-duration-ms"]);if(b)return t.resume(),G(e,b.status,{error:b.error});let w=await bt(t,ya.bytes);if(!w)return G(e,413,{error:_a()});if(!w.length)return G(e,400,{error:"The recording is empty."});let T={"Content-Type":f,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Nr(e,o.daemon,"/voice/transcribe",w,T,18e4)}let s,i=await bt(t,64*1024);if(!i)return G(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return G(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return G(e,503,{error:"The database on this computer is unavailable."});let d=l.get(r.id,String(s?.conversationId??""));if(!d)return G(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Hr):"";if(!p.trim())return G(e,400,{error:"text is required"});if(!ud(d.messages,p))return G(e,404,{error:"no such answer in this conversation"});let u={agent:d.agent,text:p,...d.node!=="local"?{peer:d.node}:{}};return Nr(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(u)),{"Content-Type":"application/json"},9e4)}async function Nr(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(pd(l)?.endpoints)?G(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 G(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function G(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function pd(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function ud(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Hr&&a.content.startsWith(e)))}var md={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},lt=class{constructor(e=md,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},fd="That code didn't work. Check it, or run agentx app pair for a new one.",hd=400;async function zr(t,e){let a=Date.now(),n=e.log??(d=>console.log(d)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await we(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await gd(a,e.minMs??hd),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:fd}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function gd(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}var qr=`
15137
+ `}async function Gt(t,e,a){try{let n=Me(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Me(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Me(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 Me(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Wr=8e3;async function Gr(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return G(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let f=String(t.headers["content-type"]||"");if(!Aa(f))return G(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let b=Ca(t.headers["x-audio-duration-ms"]);if(b)return t.resume(),G(e,b.status,{error:b.error});let w=await _t(t,Ta.bytes);if(!w)return G(e,413,{error:Ma()});if(!w.length)return G(e,400,{error:"The recording is empty."});let T={"Content-Type":f,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Fr(e,o.daemon,"/voice/transcribe",w,T,18e4)}let s,i=await _t(t,64*1024);if(!i)return G(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return G(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return G(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return G(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Wr):"";if(!p.trim())return G(e,400,{error:"text is required"});if(!Ec(c.messages,p))return G(e,404,{error:"no such answer in this conversation"});let u={agent:c.agent,text:p,...c.node!=="local"?{peer:c.node}:{}};return Fr(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(u)),{"Content-Type":"application/json"},9e4)}async function Fr(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(Sc(l)?.endpoints)?G(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 G(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function G(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function Sc(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function Ec(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Wr&&a.content.startsWith(e)))}var Tc={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},dt=class{constructor(e=Tc,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},Cc="That code didn't work. Check it, or run agentx app pair for a new one.",Ac=400;async function Xr(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await we(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await Mc(a,e.minMs??Ac),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:Cc}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function Mc(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function Xt(t,e){if(!t)return"absent";let a=ba(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var pt=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 Jr(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Kr(t.headers["sec-fetch-mode"]),n.site=Kr(t.headers["sec-fetch-site"]),n}function Kr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var Vr=`
15138
15138
  (function () {
15139
15139
  var fleetPanel = document.getElementById('panel-fleet');
15140
15140
  var activityPanel = document.getElementById('panel-activity');
@@ -15378,7 +15378,7 @@ data: ${JSON.stringify(e)}
15378
15378
  setInterval(refresh, 15000);
15379
15379
  refresh();
15380
15380
  })();
15381
- `;var Ur=`
15381
+ `;var Yr=`
15382
15382
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
15383
15383
  .fx-head h2 { margin: 4px 0 0; }
15384
15384
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -15435,7 +15435,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15435
15435
  }
15436
15436
  .fx-error:empty { display: none; }
15437
15437
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
15438
- `;var Fr=`
15438
+ `;var Qr=`
15439
15439
  (function () {
15440
15440
  var panel = document.getElementById('panel-alerts');
15441
15441
  if (!panel) return;
@@ -15597,7 +15597,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15597
15597
  refresh();
15598
15598
  loadRecent();
15599
15599
  })();
15600
- `;var Wr=`
15600
+ `;var Zr=`
15601
15601
  (function () {
15602
15602
  var panel = document.getElementById('panel-chat');
15603
15603
  var V = window.AXChatView;
@@ -15893,7 +15893,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15893
15893
  var last = recall('ax-chat-conv');
15894
15894
  if (last) openConversation(last);
15895
15895
  })();
15896
- `;var Gr=`
15896
+ `;var eo=`
15897
15897
  window.AXChatView = (function () {
15898
15898
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
15899
15899
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -16054,7 +16054,7 @@ window.AXChatView = (function () {
16054
16054
  return { NL: NL, esc: esc, httpUrl: httpUrl, md: md, preview: preview, setTools: setTools, renderUi: renderUi, readStream: readStream,
16055
16055
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
16056
16056
  })();
16057
- `;var Xr=`
16057
+ `;var to=`
16058
16058
  body { height: 100dvh; }
16059
16059
  main { min-height: 0; }
16060
16060
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -16137,7 +16137,7 @@ main { min-height: 0; }
16137
16137
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
16138
16138
  }
16139
16139
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
16140
- `;var Kr=`
16140
+ `;var ao=`
16141
16141
  window.AXOrb = (function () {
16142
16142
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
16143
16143
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -16267,7 +16267,7 @@ window.AXOrb = (function () {
16267
16267
  }
16268
16268
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
16269
16269
  })();
16270
- `;var Jr=`
16270
+ `;var no=`
16271
16271
  window.AXVoiceIO = (function () {
16272
16272
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
16273
16273
  var ac = null, playing = null;
@@ -16385,7 +16385,7 @@ window.AXVoiceIO = (function () {
16385
16385
 
16386
16386
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
16387
16387
  })();
16388
- `;var Vr=`
16388
+ `;var ro=`
16389
16389
  (function () {
16390
16390
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
16391
16391
  if (!panel || !C || !IO || !O) return;
@@ -16563,7 +16563,7 @@ window.AXVoiceIO = (function () {
16563
16563
  idle();
16564
16564
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; } };
16565
16565
  })();
16566
- `;var Yr=`
16566
+ `;var oo=`
16567
16567
  .vx {
16568
16568
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
16569
16569
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -16599,21 +16599,21 @@ window.AXVoiceIO = (function () {
16599
16599
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
16600
16600
  .cx-typing-on .vx-row { gap: 16px; }
16601
16601
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
16602
- `;var Qr=`
16602
+ `;var so=`
16603
16603
  <main class="card">
16604
16604
  <h1>This phone isn't paired</h1>
16605
- <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>. Type the code it shows here.</p>
16605
+ <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>
16606
16606
  <form id="pair-form" class="pair-form" novalidate>
16607
+ <button type="button" id="scan-btn" class="scan-btn">Scan QR code</button>
16607
16608
  <label for="pair-code">Pairing code</label>
16608
- <input id="pair-code" name="code" type="text" placeholder="XXXX-XXXX" maxlength="16"
16609
+ <input id="pair-code" name="code" type="text" placeholder="XXXX-XXXX" maxlength="9"
16609
16610
  autocomplete="one-time-code" inputmode="text" autocapitalize="characters" autocorrect="off" spellcheck="false" enterkeyhint="go" required>
16610
16611
  <button type="submit" id="pair-btn">Pair</button>
16611
16612
  <p id="pair-offline" class="pair-offline" role="status" hidden>You're offline. Pairing needs a connection: turn on Wi-Fi or mobile data and Tailscale, then try again.</p>
16612
16613
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
16613
16614
  </form>
16614
- <p class="muted">Or scan the QR code it shows with this phone's camera. That pairs the browser; an app added to the home screen needs the code.</p>
16615
16615
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
16616
- </main>`,Zr=`
16616
+ </main>`,io=`
16617
16617
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
16618
16618
  .pair-form label { font-weight: 600; }
16619
16619
  .pair-form input {
@@ -16635,7 +16635,7 @@ window.AXVoiceIO = (function () {
16635
16635
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
16636
16636
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
16637
16637
  }
16638
- `,eo=`
16638
+ `,lo=`
16639
16639
  (function () {
16640
16640
  var form = document.getElementById('pair-form');
16641
16641
  var input = document.getElementById('pair-code');
@@ -16648,7 +16648,30 @@ window.AXVoiceIO = (function () {
16648
16648
  setOnline(navigator.onLine !== false);
16649
16649
  window.addEventListener('online', function () { setOnline(true); });
16650
16650
  window.addEventListener('offline', function () { setOnline(false); });
16651
- input.addEventListener('input', function () { if (msg.className.indexOf('bad') >= 0) say('', false); });
16651
+ // Capitals, code symbols only, and the dash after four (formatPairInput
16652
+ // in app-pair-logic.ts), keeping the cursor after the same symbol.
16653
+ input.addEventListener('input', function () {
16654
+ var f = formatPairInput(input.value, input.selectionStart == null ? input.value.length : input.selectionStart);
16655
+ if (f.value !== input.value) {
16656
+ input.value = f.value;
16657
+ try { if (document.activeElement === input) input.setSelectionRange(f.caret, f.caret); } catch (x) {}
16658
+ }
16659
+ if (msg.className.indexOf('bad') >= 0) say('', false);
16660
+ });
16661
+ // maxlength would cut a pasted "abcd - efgh" before the input event
16662
+ // sees it, so format pastes here instead.
16663
+ input.addEventListener('paste', function (ev) {
16664
+ var text = ev.clipboardData && ev.clipboardData.getData('text');
16665
+ if (!text) return;
16666
+ ev.preventDefault();
16667
+ var start = input.selectionStart == null ? input.value.length : input.selectionStart;
16668
+ var end = input.selectionEnd == null ? start : input.selectionEnd;
16669
+ var raw = input.value.slice(0, start) + text + input.value.slice(end);
16670
+ var f = formatPairInput(raw, start + text.length);
16671
+ input.value = f.value;
16672
+ try { input.setSelectionRange(f.caret, f.caret); } catch (x) {}
16673
+ if (msg.className.indexOf('bad') >= 0) say('', false);
16674
+ });
16652
16675
  function done() { busy = false; setOnline(navigator.onLine !== false); }
16653
16676
  form.addEventListener('submit', function (ev) {
16654
16677
  ev.preventDefault();
@@ -16678,11 +16701,238 @@ window.AXVoiceIO = (function () {
16678
16701
  say('Could not reach AgentX. Pairing needs a connection: check this phone is on your tailnet, then try again.', true);
16679
16702
  });
16680
16703
  });
16704
+ // Self-heal (#234). This page can appear although the phone is paired:
16705
+ // iOS has opened the app without its cookie, and the service worker keeps
16706
+ // a copy of this page for offline starts. Ask /api/app/me first; if the
16707
+ // phone is known, go straight back to the app. mayBounce() allows that
16708
+ // once per 30 seconds, so a server that refuses /app but accepts the
16709
+ // probe can't trap the phone in a reload loop.
16710
+ function heal() {
16711
+ if (busy || navigator.onLine === false) return;
16712
+ var last = null;
16713
+ try { last = Number(sessionStorage.getItem('ax-heal')) || null; } catch (x) {}
16714
+ if (!mayBounce(last, Date.now())) return;
16715
+ fetch('/api/app/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) {
16716
+ if (r.status !== 200 || busy) return;
16717
+ try { sessionStorage.setItem('ax-heal', String(Date.now())); } catch (x) {}
16718
+ say('This phone is paired. Opening the app\u2026', false);
16719
+ location.replace('/app');
16720
+ }).catch(function () {});
16721
+ }
16722
+ heal();
16723
+ window.addEventListener('online', heal);
16724
+ document.addEventListener('visibilitychange', function () { if (!document.hidden) heal(); });
16725
+
16681
16726
  if ('serviceWorker' in navigator) {
16682
16727
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
16683
16728
  }
16684
16729
  })();
16685
- `;var Ut=`
16730
+ `;function co(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function po(t,e){return!t||e-t>=3e4||t>e}function uo(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 mo(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}var fo=`
16731
+ <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
16732
+ <video id="scan-video" playsinline muted autoplay></video>
16733
+ <div class="scan-frame" aria-hidden="true"></div>
16734
+ <div class="scan-top">
16735
+ <h2 id="scan-title">Scan the pairing QR code</h2>
16736
+ <button type="button" id="scan-close" class="scan-close">Close</button>
16737
+ </div>
16738
+ <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>
16739
+ </div>`,ho=`
16740
+ .pair-form .scan-btn {
16741
+ color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
16742
+ }
16743
+ [data-theme="dark"] .pair-form .scan-btn { color: var(--ax-text); }
16744
+ .scan { position: fixed; inset: 0; z-index: 50; background: #000; color: #fff; overflow: hidden; }
16745
+ .scan[hidden] { display: none; }
16746
+ .scan video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
16747
+ .scan-frame {
16748
+ position: absolute; left: 50%; top: 50%; width: min(70vw, 70vh, 320px); aspect-ratio: 1;
16749
+ transform: translate(-50%, -50%); border: 3px solid rgba(255,255,255,0.9); border-radius: 20px;
16750
+ box-shadow: 0 0 0 100vmax rgba(0,0,0,0.45);
16751
+ }
16752
+ .scan-top {
16753
+ position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px;
16754
+ padding: calc(12px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) 12px calc(16px + env(safe-area-inset-left));
16755
+ }
16756
+ .scan-top h2 { margin: 0; font-size: 17px; font-weight: 700; }
16757
+ .scan-close {
16758
+ min-height: 44px; padding: 0 18px; border: 0; border-radius: var(--ax-radius-pill);
16759
+ font: inherit; font-weight: 700; color: #000; background: #fff; cursor: pointer;
16760
+ }
16761
+ .scan-msg {
16762
+ position: absolute; left: 0; right: 0; bottom: 0; margin: 0; text-align: center; line-height: 1.45;
16763
+ padding: 16px calc(20px + env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-left));
16764
+ background: rgba(0,0,0,0.6);
16765
+ }
16766
+ .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
16767
+ body.scanning { overflow: hidden; }
16768
+ `,go=`
16769
+ (function () {
16770
+ var openBtn = document.getElementById('scan-btn');
16771
+ var box = document.getElementById('scan');
16772
+ var video = document.getElementById('scan-video');
16773
+ var smsg = document.getElementById('scan-msg');
16774
+ var closeBtn = document.getElementById('scan-close');
16775
+ var input = document.getElementById('pair-code');
16776
+ var form = document.getElementById('pair-form');
16777
+ var pairMsg = document.getElementById('pair-msg');
16778
+ var HINT = 'Point the camera at the QR code shown by agentx app pair.';
16779
+ var stream = null, timer = null, detector = null, canvas = null, ctx = null, working = false, done = false, jsqr = null, misses = 0;
16780
+
16781
+ // No camera API: plain http, or a browser without it. Typing the code
16782
+ // still works, so just don't offer Scan.
16783
+ if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { openBtn.hidden = true; return; }
16784
+
16785
+ function say(text, bad) { smsg.textContent = text; smsg.className = bad ? 'scan-msg bad' : 'scan-msg'; }
16786
+ function stop() {
16787
+ if (timer) { clearInterval(timer); timer = null; }
16788
+ if (stream) { stream.getTracks().forEach(function (t) { t.stop(); }); stream = null; }
16789
+ video.srcObject = null;
16790
+ working = false;
16791
+ }
16792
+ function close() {
16793
+ stop();
16794
+ if (box.hidden) return;
16795
+ box.hidden = true;
16796
+ document.body.classList.remove('scanning');
16797
+ openBtn.focus();
16798
+ }
16799
+
16800
+ function loadJsQR() {
16801
+ if (window.jsQR) return Promise.resolve(window.jsQR);
16802
+ if (!jsqr) {
16803
+ jsqr = new Promise(function (ok, fail) {
16804
+ var s = document.createElement('script');
16805
+ s.src = '/app/qr.js';
16806
+ s.async = true;
16807
+ s.onload = function () { if (window.jsQR) ok(window.jsQR); else fail(new Error('no jsQR')); };
16808
+ s.onerror = function () { jsqr = null; fail(new Error('load failed')); };
16809
+ document.head.appendChild(s);
16810
+ });
16811
+ }
16812
+ return jsqr;
16813
+ }
16814
+ function pickDecoder() {
16815
+ if (!('BarcodeDetector' in window)) return loadJsQR().then(function () { return null; });
16816
+ var BD = window.BarcodeDetector;
16817
+ var formats = BD.getSupportedFormats ? BD.getSupportedFormats() : Promise.resolve(['qr_code']);
16818
+ return formats.then(function (f) {
16819
+ if (f.indexOf('qr_code') < 0) throw new Error('no qr');
16820
+ return new BD({ formats: ['qr_code'] });
16821
+ }).catch(function () { return loadJsQR().then(function () { return null; }); });
16822
+ }
16823
+
16824
+ // One frame. Returns the QR text, or null when there is none yet.
16825
+ // Some BarcodeDetector builds claim QR support and never find one, or
16826
+ // fail outright; after 3 seconds without a result (or on an error) jsQR
16827
+ // reads every other frame too.
16828
+ function readFrame() {
16829
+ var useDetector = detector && (misses < 24 || misses % 2 === 0 || !window.jsQR);
16830
+ if (detector && misses === 24) loadJsQR().catch(function () {});
16831
+ if (useDetector) {
16832
+ return detector.detect(video).then(function (codes) {
16833
+ if (codes.length) return codes[0].rawValue;
16834
+ misses++;
16835
+ return null;
16836
+ }, function () {
16837
+ detector = null;
16838
+ return loadJsQR().then(function () { return null; });
16839
+ });
16840
+ }
16841
+ misses++;
16842
+ if (!window.jsQR) return Promise.resolve(null);
16843
+ var w = video.videoWidth, h = video.videoHeight;
16844
+ if (!w || !h) return Promise.resolve(null);
16845
+ var scale = Math.min(1, 720 / Math.max(w, h));
16846
+ var cw = Math.round(w * scale), ch = Math.round(h * scale);
16847
+ if (!canvas) { canvas = document.createElement('canvas'); ctx = canvas.getContext('2d', { willReadFrequently: true }); }
16848
+ canvas.width = cw; canvas.height = ch;
16849
+ ctx.drawImage(video, 0, 0, cw, ch);
16850
+ var found = window.jsQR(ctx.getImageData(0, 0, cw, ch).data, cw, ch, { inversionAttempts: 'attemptBoth' });
16851
+ return Promise.resolve(found ? found.data : null);
16852
+ }
16853
+
16854
+ function tick() {
16855
+ if (working || done || !stream) return;
16856
+ working = true;
16857
+ readFrame().then(function (text) {
16858
+ working = false;
16859
+ if (text) handle(text);
16860
+ }, function () { working = false; });
16861
+ }
16862
+
16863
+ function handle(text) {
16864
+ var r = parsePairScan(text);
16865
+ if (r.kind === 'none') { say("That QR isn't an AgentX pairing code. Scan the one shown by agentx app pair.", true); return; }
16866
+ done = true;
16867
+ stop();
16868
+ if (r.kind === 'code') {
16869
+ close();
16870
+ input.value = r.code;
16871
+ if (form.requestSubmit) form.requestSubmit();
16872
+ else form.dispatchEvent(new Event('submit', { cancelable: true }));
16873
+ return;
16874
+ }
16875
+ say('Pairing\u2026', false);
16876
+ fetch('/api/app/session', {
16877
+ method: 'POST',
16878
+ credentials: 'same-origin',
16879
+ headers: { 'Authorization': 'Bearer ' + r.token },
16880
+ }).then(function (res) {
16881
+ if (res.ok) { say('Paired. Opening the app\u2026', false); location.replace('/app'); return; }
16882
+ close();
16883
+ pairMsg.className = 'pair-msg bad';
16884
+ pairMsg.textContent = res.status === 401
16885
+ ? 'That QR code is not valid any more. Run agentx app pair again and scan the new one.'
16886
+ : 'Pairing failed (HTTP ' + res.status + '). Try again.';
16887
+ }).catch(function () {
16888
+ close();
16889
+ pairMsg.className = 'pair-msg bad';
16890
+ pairMsg.textContent = 'Could not reach AgentX. Pairing needs a connection: check this phone is on your tailnet, then try again.';
16891
+ });
16892
+ }
16893
+
16894
+ function cameraError(err) {
16895
+ stop();
16896
+ var name = err && err.name;
16897
+ if (name === 'NotAllowedError' || name === 'SecurityError') {
16898
+ say('AgentX may not use the camera. Allow camera access for this app (on iPhone: Settings, then Safari, then Camera), or type the code instead.', true);
16899
+ } else if (name === 'NotFoundError' || name === 'OverconstrainedError') {
16900
+ say('No camera found on this device. Type the code instead.', true);
16901
+ } else if (name === 'decoder') {
16902
+ say('Could not load the QR reader. Check the connection, or type the code instead.', true);
16903
+ } else {
16904
+ say('The camera could not start. Close other apps using it, or type the code instead.', true);
16905
+ }
16906
+ }
16907
+
16908
+ function open() {
16909
+ done = false;
16910
+ misses = 0;
16911
+ box.hidden = false;
16912
+ document.body.classList.add('scanning');
16913
+ say(HINT, false);
16914
+ closeBtn.focus();
16915
+ navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false }).then(function (s) {
16916
+ if (box.hidden) { s.getTracks().forEach(function (t) { t.stop(); }); return; }
16917
+ stream = s;
16918
+ video.srcObject = s;
16919
+ var p = video.play();
16920
+ if (p && p.catch) p.catch(function () {});
16921
+ return pickDecoder().then(function (d) {
16922
+ detector = d;
16923
+ if (stream) timer = setInterval(tick, 125);
16924
+ }, function () { cameraError({ name: 'decoder' }); });
16925
+ }).catch(cameraError);
16926
+ }
16927
+
16928
+ openBtn.addEventListener('click', open);
16929
+ closeBtn.addEventListener('click', close);
16930
+ box.addEventListener('keydown', function (ev) { if (ev.key === 'Escape') close(); });
16931
+ document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
16932
+ window.addEventListener('pagehide', close);
16933
+ })();
16934
+ `;var Kt=`
16935
+ ${ee({afterUnauthorized:co})}
16686
16936
  var CACHE = 'agentx-app-v3';
16687
16937
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
16688
16938
  self.addEventListener('install', function (e) {
@@ -16699,23 +16949,42 @@ self.addEventListener('fetch', function (e) {
16699
16949
  if (req.method !== 'GET' || url.origin !== self.location.origin) return;
16700
16950
  if (url.pathname.indexOf('/api/') === 0) return;
16701
16951
  if (req.mode === 'navigate' && url.pathname === '/app') {
16702
- e.respondWith(fetch(req).then(function (res) {
16703
- var copy = res.clone();
16704
- caches.open(CACHE).then(function (c) {
16705
- if (res.ok) return Promise.all([c.put('/app', copy), c.delete('/app/locked')]);
16706
- if (res.status === 401) return Promise.all([c.put('/app/locked', copy), c.delete('/app')]);
16707
- return null;
16708
- });
16709
- return res;
16710
- }).catch(function () {
16711
- return caches.match('/app').then(function (hit) { return hit || caches.match('/app/locked'); }).then(function (hit) { return hit || Response.error(); });
16712
- }));
16952
+ e.respondWith(navigateApp(req, e));
16713
16953
  return;
16714
16954
  }
16715
16955
  if (STATIC.indexOf(url.pathname) >= 0) {
16716
16956
  e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
16717
16957
  }
16718
16958
  });
16959
+ function keep(e, p) { try { e.waitUntil(p); } catch (x) { /* already settled */ } return p; }
16960
+ function saveShell(e, res) {
16961
+ return keep(e, caches.open(CACHE).then(function (c) { return Promise.all([c.put('/app', res), c.delete('/app/locked')]); }));
16962
+ }
16963
+ function saveLocked(e, res) {
16964
+ return keep(e, caches.open(CACHE).then(function (c) { return Promise.all([c.put('/app/locked', res), c.delete('/app')]); }));
16965
+ }
16966
+ function offlineApp() {
16967
+ return caches.match('/app').then(function (hit) { return hit || caches.match('/app/locked'); }).then(function (hit) { return hit || Response.error(); });
16968
+ }
16969
+ function navigateApp(req, e) {
16970
+ return fetch(req).then(function (res) {
16971
+ if (res.ok) { saveShell(e, res.clone()); return res; }
16972
+ if (res.status !== 401) return res;
16973
+ // A 401 on the navigation alone doesn't mean the phone was unpaired:
16974
+ // iOS has opened the app without its cookie (#234). Ask /api/app/me
16975
+ // from here, where the cookie is sent, before dropping anything.
16976
+ return fetch('/api/app/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (p) { return p.status; }, function () { return 0; }).then(function (probe) {
16977
+ var step = afterUnauthorized(probe);
16978
+ if (step === 'lock') { saveLocked(e, res.clone()); return res; }
16979
+ if (step === 'keep') return res;
16980
+ var saved = function () { return caches.match('/app').then(function (hit) { return hit || res; }); };
16981
+ return fetch('/app', { credentials: 'same-origin', cache: 'no-store' }).then(function (again) {
16982
+ if (again.ok) { saveShell(e, again.clone()); return again; }
16983
+ return saved();
16984
+ }, saved);
16985
+ });
16986
+ }).catch(offlineApp);
16987
+ }
16719
16988
  function safeUrl(u) {
16720
16989
  try {
16721
16990
  var abs = new URL(u || '/app#alerts', self.location.origin);
@@ -16754,7 +17023,7 @@ self.addEventListener('notificationclick', function (e) {
16754
17023
  return self.clients.openWindow(target);
16755
17024
  }));
16756
17025
  });
16757
- `;var xd="<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 Ft(t){return`<meta charset="utf-8">
17026
+ `;var Ic="<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 Jt(t){return`<meta charset="utf-8">
16758
17027
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
16759
17028
  <meta name="theme-color" content="#2979FF">
16760
17029
  <meta name="referrer" content="no-referrer">
@@ -16765,13 +17034,13 @@ self.addEventListener('notificationclick', function (e) {
16765
17034
  <link rel="icon" type="image/png" href="/app/icon-192.png">
16766
17035
  <link rel="apple-touch-icon" href="/app/icon-192.png">
16767
17036
  <title>${t}</title>
16768
- ${xd}
16769
- <style>${$a}${yd}</style>`}var to=[{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 ao(){let t=to.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}">${a.label}</button>`).join(""),e=to.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
17037
+ ${Ic}
17038
+ <style>${Da}${Rc}</style>`}var xo=[{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 vo(){let t=xo.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}">${a.label}</button>`).join(""),e=xo.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
16770
17039
  <h2>${a.label}</h2>
16771
17040
  <p class="soon">${a.soon}</p>
16772
17041
  </section>`).join("");return`<!doctype html>
16773
17042
  <html lang="en">
16774
- <head>${Ft("AgentX")}<style>${wd}${Ur}${Xr}${Yr}</style></head>
17043
+ <head>${Jt("AgentX")}<style>${jc}${Yr}${to}${oo}</style></head>
16775
17044
  <body>
16776
17045
  <header class="bar">
16777
17046
  <div>
@@ -16783,29 +17052,31 @@ ${xd}
16783
17052
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
16784
17053
  <main>${e}</main>
16785
17054
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
16786
- <script>${vd}</script>
16787
- <script>${qr}</script>
16788
- <script>${Fr}</script>
16789
- <script>${me({markdownToHtml:La})}${Gr}${Wr}</script>
16790
- <script>${Kr}${Jr}${Vr}</script>
17055
+ <script>${$c}</script>
17056
+ <script>${Vr}</script>
17057
+ <script>${Qr}</script>
17058
+ <script>${ee({markdownToHtml:Na})}${eo}${Zr}</script>
17059
+ <script>${ao}${no}${ro}</script>
16791
17060
  </body>
16792
- </html>`}function no(){return`<!doctype html>
17061
+ </html>`}function bo(){return`<!doctype html>
16793
17062
  <html lang="en">
16794
- <head>${Ft("Pair \xB7 AgentX")}</head>
17063
+ <head>${Jt("Pair \xB7 AgentX")}</head>
16795
17064
  <body>
16796
17065
  <main class="card">
16797
17066
  <h1>Pairing this phone\u2026</h1>
16798
17067
  <p id="msg" role="status">One moment.</p>
16799
17068
  </main>
16800
- <script>${bd}</script>
17069
+ <script>${Lc}</script>
16801
17070
  </body>
16802
- </html>`}function ro(){return`<!doctype html>
17071
+ </html>`}function yo(){return`<!doctype html>
16803
17072
  <html lang="en">
16804
- <head>${Ft("Not paired \xB7 AgentX")}<style>${Zr}</style></head>
16805
- <body>${Qr}
16806
- <script>${eo}</script>
17073
+ <head>${Jt("Not paired \xB7 AgentX")}<style>${io}${ho}</style></head>
17074
+ <body>${so}${fo}
17075
+ <script>${ee({mayBounce:po,formatPairInput:uo,parsePairScan:mo})}</script>
17076
+ <script>${lo}</script>
17077
+ <script>${go}</script>
16807
17078
  </body>
16808
- </html>`}function oo(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var vd=`
17079
+ </html>`}function wo(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var $c=`
16809
17080
  (function () {
16810
17081
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
16811
17082
  function select(tab, focus) {
@@ -16871,7 +17142,7 @@ ${xd}
16871
17142
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
16872
17143
  }
16873
17144
  })();
16874
- `,bd=`
17145
+ `,Lc=`
16875
17146
  (function () {
16876
17147
  var msg = document.getElementById('msg');
16877
17148
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -16888,7 +17159,7 @@ ${xd}
16888
17159
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
16889
17160
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
16890
17161
  })();
16891
- `,yd=`
17162
+ `,Rc=`
16892
17163
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
16893
17164
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
16894
17165
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -16900,7 +17171,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
16900
17171
  .card h1 { font-size: 22px; margin: 0 0 12px; }
16901
17172
  .muted { color: var(--ax-text-2); }
16902
17173
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
16903
- `,wd=`
17174
+ `,jc=`
16904
17175
  body { display: flex; flex-direction: column; }
16905
17176
  .bar {
16906
17177
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -16937,7 +17208,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
16937
17208
  }
16938
17209
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
16939
17210
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
16940
- `;var io="agentx_app",kd=400*86400,_d=new lt;async function lo(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Z;if(n==="GET"){if(a==="/app/manifest.webmanifest")return he(e,200,"application/manifest+json",oo());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),he(e,200,"text/javascript; charset=utf-8",Ut);if(a==="/app/icon-192.png")return he(e,200,"image/png",Bt(192),"public, max-age=86400");if(a==="/app/icon-512.png")return he(e,200,"image/png",Bt(512),"public, max-age=86400");if(a==="/app/pair")return he(e,200,"text/html; charset=utf-8",no())}if(n==="POST"&&a==="/api/app/session"){let i=Wt(Gt(t),o);return i?(e.setHeader("Set-Cookie",so(Gt(t))),Me(e,200,{device:i.name})):Me(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await zr(t,{codes:r.pairCodes??new za,limiter:r.pairLimiter??_d,verify:l=>Wt(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",so(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Me(e,i.status,i.body)}let s=Wt(Sd(t),o);return s?n==="GET"&&a==="/app"?he(e,200,"text/html; charset=utf-8",ao()):n==="GET"&&a==="/api/app/me"?Me(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Mr(t,e,a,n,s.name,r.fleet)||r.push&&await $r(t,e,a,n,s,r.push)||r.chat&&await Pr(t,e,a,n,s,r.chat)||r.voice&&await Br(t,e,a,n,s,r.voice)?!0:Me(e,404,{error:"not found"}):a==="/app"?he(e,401,"text/html; charset=utf-8",ro()):Me(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function Wt(t,e){if(!t)return null;let a=e.verify(t);return a&&xe(a,"app")?a:null}function so(t){return`${io}=${t}; Path=/; Max-Age=${kd}; HttpOnly; Secure; SameSite=Strict`}function Sd(t){return Gt(t)??Ed(t,io)}function Gt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ed(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function he(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Me(t,e,a){return he(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Td}from"crypto";var Ie={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},Cd=/^c[a-z0-9]{8,32}$/;function Ad(t){return Cd.test(t)}var Oe=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
17211
+ `;var ut="agentx_app",Dc=400*86400,Nc=new dt,Hc=new pt;async function ko(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Z;if(n==="GET"){if(a==="/app/manifest.webmanifest")return me(e,200,"application/manifest+json",wo());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),me(e,200,"text/javascript; charset=utf-8",Kt);if(a==="/app/icon-192.png")return me(e,200,"image/png",Ft(192),"public, max-age=86400");if(a==="/app/icon-512.png")return me(e,200,"image/png",Ft(512),"public, max-age=86400");if(a==="/app/pair")return me(e,200,"text/html; charset=utf-8",bo());if(a==="/app/qr.js"){let i=Bc();return i?me(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):ke(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Vt(De(t),o);return i?(e.setHeader("Set-Cookie",Yt(De(t))),ke(e,200,{device:i.name})):ke(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Xr(t,{codes:r.pairCodes??new Xa,limiter:r.pairLimiter??Nc,verify:l=>Vt(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Yt(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),ke(e,i.status,i.body)}let s=Vt(zc(t),o);if(!s){let i=De(t);return(r.rejectLog??Hc).record(a.slice(0,120),Jr(t,Xt(Qt(t,ut),o),i?Xt(i,o):null)),a==="/app"?me(e,401,"text/html; charset=utf-8",yo()):ke(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Qt(t,ut);return i&&!De(t)&&e.setHeader("Set-Cookie",Yt(i)),me(e,200,"text/html; charset=utf-8",vo())}return n==="GET"&&a==="/api/app/me"?ke(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Pr(t,e,a,n,s.name,r.fleet)||r.push&&await Dr(t,e,a,n,s,r.push)||r.chat&&await zr(t,e,a,n,s,r.chat)||r.voice&&await Gr(t,e,a,n,s,r.voice)?!0:ke(e,404,{error:"not found"})}var Oe;function Bc(){if(Oe!==void 0)return Oe;try{let t=Oc(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
17212
+ `;Oe=Buffer.concat([Buffer.from(a),Pc(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Oe=null}return Oe}function Vt(t,e){if(!t)return null;let a=e.verify(t);return a&&xe(a,"app")?a:null}function Yt(t){return`${ut}=${t}; Path=/; Max-Age=${Dc}; HttpOnly; Secure; SameSite=Lax`}function zc(t){return De(t)??Qt(t,ut)}function De(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Qt(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function me(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function ke(t,e,a){return me(t,e,"application/json",JSON.stringify(a))}import{randomBytes as qc}from"crypto";var Ie={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},Uc=/^c[a-z0-9]{8,32}$/;function Fc(t){return Uc.test(t)}var Ne=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
16941
17213
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
16942
17214
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
16943
17215
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -16945,30 +17217,30 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
16945
17217
  CREATE TABLE IF NOT EXISTS app_chat_messages (
16946
17218
  id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id TEXT NOT NULL, role TEXT NOT NULL,
16947
17219
  content TEXT NOT NULL, status TEXT, error TEXT, ui TEXT, tools TEXT, at INTEGER NOT NULL);
16948
- CREATE INDEX IF NOT EXISTS app_chat_messages_conversation ON app_chat_messages(conversation_id, id);`)}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${Td(4).toString("hex")}`,s={id:o,title:Id(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
16949
- (id, device_id, title, node, node_name, agent, agent_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,s.title,s.node,s.nodeName,s.agent,s.agentName??null,r,r),this.pruneDevice(e),s}get(e,a){if(!Ad(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(Md);return{...co(n),messages:r}}list(e,a=Ie.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
17220
+ CREATE INDEX IF NOT EXISTS app_chat_messages_conversation ON app_chat_messages(conversation_id, id);`)}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${qc(4).toString("hex")}`,s={id:o,title:Gc(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
17221
+ (id, device_id, title, node, node_name, agent, agent_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,s.title,s.node,s.nodeName,s.agent,s.agentName??null,r,r),this.pruneDevice(e),s}get(e,a){if(!Fc(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(Wc);return{..._o(n),messages:r}}list(e,a=Ie.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
16950
17222
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
16951
17223
  (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
16952
- 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{...co(r),messages:r.n,...o?{last:o}:{}}})}append(e,a,n){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return!1;let o=n.content.length>Ie.content?n.content.slice(0,Ie.content)+`
17224
+ 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{..._o(r),messages:r.n,...o?{last:o}:{}}})}append(e,a,n){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return!1;let o=n.content.length>Ie.content?n.content.slice(0,Ie.content)+`
16953
17225
 
16954
17226
  [Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,Ie.toolsPerMessage);return this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, at)
16955
17227
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,o,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,s?.length?JSON.stringify(s):null,n.at),this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
16956
17228
  (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ie.messagesPerConversation),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),!0}pruneDevice(e){let a=this.db.prepare(`SELECT id FROM app_chat_conversations WHERE device_id = ?
16957
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ie.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function co(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}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function Md(t){let e=r=>{if(r)try{return JSON.parse(r)}catch{return}},a=e(t.ui),n=e(t.tools);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}:{}}}function Id(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function Rf(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let b of a)try{s.set(b.id,qd(b,t))}catch(w){console.error(` Board "${b.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?De(process.cwd(),t.workflows.dir):void 0,d=new na(l?{baseDir:l}:void 0),p=new ra(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new oa(l?{baseDir:l}:void 0);Jn(t),va({business:t.business?.enabled===!0}),$d(async(b,w)=>{try{await Nd(b,w,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(T){y(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let b=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
17229
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ie.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function _o(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}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function Wc(t){let e=r=>{if(r)try{return JSON.parse(r)}catch{return}},a=e(t.ui),n=e(t.tools);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}:{}}}function Gc(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function sh(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let b of a)try{s.set(b.id,rd(b,t))}catch(w){console.error(` Board "${b.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?He(process.cwd(),t.workflows.dir):void 0,c=new la(l?{baseDir:l}:void 0),p=new ca(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new da(l?{baseDir:l}:void 0);tr(t),Sa({business:t.business?.enabled===!0}),Xc(async(b,w)=>{try{await ed(b,w,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(T){y(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let b=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
16958
17230
  Live dashboard: http://${b}:${n}
16959
17231
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
16960
17232
  Kanban dashboard: http://${b}:${n}
16961
- `),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Dd=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Nd(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ga(t.headers)==="foreign"&&xa(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await lo(t,e,r,o,{nodeName:a.config.node?.name,fleet:ho(a.config),push:rc(a.config),chat:oc(a.config),voice:sc(a.config)}))return;if(o==="GET"&&Dd.has(r)&&Fa("page",r),o==="GET"&&r==="/"){let c=Da();if(!c.configExists||c.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nt({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(yr({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nt({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await ge(a.config);if(!c){y(e,503,{error:"no node available"});return}let m=await new Promise(x=>{let k="";t.on("data",v=>k+=v),t.on("end",()=>x(k)),t.on("error",()=>x(""))}),h=await fetch(c.url+r,{method:"POST",headers:{"Content-Type":"application/json",...c.token?{Authorization:`Bearer ${c.token}`}:{}},body:m||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(c){y(e,502,{error:"could not reach the node",message:String(c?.message||c)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let c=await ge(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await ue(t):void 0,x=h?.node??m,k=x?c.find(M=>M.url===x):c[0];if(!k){y(e,400,{error:"unknown node"});return}let v=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",_=await fetch(k.url+r+v,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});y(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(c){y(e,502,{error:"could not reach the node",message:c?.message||String(c)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let c=await ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,k)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await ge(a.config);if(!c){y(e,200,{configured:!1,workflows:[]});return}let m=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});y(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(en({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Za({peers:O(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(Ja({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,m=setTimeout(()=>c.abort(),8e3);try{let h=ia(await ge(a.config,c.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(h.map(async A=>{try{let S=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!S.ok)throw new Error(`HTTP ${S.status}`);return{name:A.name,url:A.url,ok:!0,data:await S.json()}}catch(S){return{name:A.name,url:A.url,ok:!1,error:S.message}}}));y(e,200,{nodes:M});return}let x=h.find(M=>M.url===n.searchParams.get("node"));if(!x){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await sa(t)):void 0,_=await fetch(x.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:v,signal:c.signal,headers:{"Content-Type":"application/json",...x.token?{Authorization:`Bearer ${x.token}`}:{}}});y(e,_.status,await _.json())}catch(h){y(e,502,{error:h.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gr({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wr({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_r({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oa({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let c=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!c){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(Sr({taskId:decodeURIComponent(i[1]),agentId:c,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:m,peers:O(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Er({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Na(t,e);return}if(o==="POST"&&r==="/api/setup"){await Ha(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ba(t,e);return}if(o==="GET"&&r==="/admin"){on(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){vn(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){mn(t,e,O(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}En(t,e,O(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let c=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(c==="fleet"){if(r==="/api/admin/activity-graph"){await uc(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Ot(t,e,r,h=>xo(h,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let h=decodeURIComponent(m[1]),x=h.indexOf("::");if(x>0){let k=h.slice(0,x),v=h.slice(x+2),_=a.config.node?.id||a.config.node?.name||"local";if(k===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===k);if(M){let A=He(M.url.replace(/\/+$/,""),a.config);if(A){await uo(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=He(c,a.config);if(!m){y(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await uo(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Tn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await mc(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-47ZKWQZT.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:h});y(e,200,x)}catch(c){y(e,500,{error:c?.message||String(c)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(In({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Mn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($n({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ln({peers:O(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 Fd(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 Vn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Ot(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Qn(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){tr(t,e,d[1],O(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let c=t.headers.authorization||"",m=c.startsWith("Bearer ")?c.slice(7):"";if(m!==a.token){let h=new Z,x=m?h.verify(m):null;if(!x||!xe(x,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await sn(t,e);return}if(r.startsWith("/api/admin/approvals")){await bn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await fn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await ar(t,e,r);return}if(r.startsWith("/api/admin/")){await ln(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(tn);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){y(e,400,{error:"invalid asset name"});return}let m=cc("web/"+c);try{let h=await pc(m),x=c.endsWith(".map")?"application/json; charset=utf-8":c.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":x,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await Ne(a.config);y(e,200,c)}catch(c){y(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let c=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",h=await Ne(a.config,{date:c,timezone:m});y(e,200,h)}catch(c){y(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(m,h,x,k)=>{let v=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(v)?Math.max(x,Math.min(k,v)):h};try{let m=await ge(a.config);y(e,200,await xr(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){y(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let c=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(c)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(h,x,k,v)=>{let _=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(_)?Math.max(k,Math.min(v,_)):x};try{let h=await ge(a.config);y(e,200,await br(h,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(h){y(e,502,{error:h.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let c=n.searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}let m=n.searchParams,h;if(r==="/api/mesh/thread"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){y(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[x,k]=[m.get("kind"),m.get("key")];if(!x||!k){y(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(x)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[x,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!k||!v){y(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let x=m.get("task");if(!x){y(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(x)}`}try{await vr(e,await ge(a.config),c,h)}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Qd(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("agent"),x=c.searchParams.get("task");if(!m||!h||!x){y(e,400,{error:"node, agent, task query params required"});return}await Zd(t,e,a,m,h,x);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("agent"),x=c.searchParams.get("task"),k=c.searchParams.get("limit")||"50";if(!m||!h){y(e,400,{error:"node and agent query params required"});return}await ac(e,a,m,h,x,k);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),h=c.searchParams.get("task"),x=c.searchParams.get("kind");if(!m||!h||x!=="cancel"&&x!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await nc(t,e,a,m,h,x);return}if(o==="POST"&&r==="/api/voice/stop"){let c=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}await Yt(t,e,a,c,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:c});if(!m.ok)throw new Error(`HTTP ${m.status}`);let h=await m.json();y(e,200,h)}catch(c){y(e,502,{error:c.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:c});if(!m.ok){y(e,m.status,{error:`HTTP ${m.status}`});return}y(e,200,await m.json())}catch(c){y(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await ue(t);try{let m=await lc(a.config,c);y(e,200,m)}catch(m){y(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let c=p[1];if(!ec(t,e,[`agent:${c}`]))return;await tc(t,e,a.config,c);return}if(r.startsWith("/api/")&&a.token){let c=t.headers.authorization||"",m=c.startsWith("Bearer ")?c.slice(7):"";if(m!==a.token){let h=new Z,x=m?h.verify(m):null;if(!x||!xe(x,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Gd(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let c=n.searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}await Yt(t,e,a,c,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(_=>({name:_.name,url:_.url,token:_.token}))],x={flag:!1},k=[];t.on("close",()=>{x.flag=!0;for(let _ of k)try{_.abort()}catch{}});let v=setInterval(()=>{if(!x.flag)try{e.write(`: ping
17233
+ `),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Zc=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function ed(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ka(t.headers)==="foreign"&&_a(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ko(t,e,r,o,{nodeName:a.config.node?.name,fleet:Ao(a.config),push:yd(a.config),chat:wd(a.config),voice:kd(a.config)}))return;if(o==="GET"&&Zc.has(r)&&Va("page",r),o==="GET"&&r==="/"){let d=Ua();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qt({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Tr({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qt({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ge(a.config);if(!d){y(e,503,{error:"no node available"});return}let m=await new Promise(g=>{let k="";t.on("data",v=>k+=v),t.on("end",()=>g(k)),t.on("error",()=>g(""))}),h=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(h.status,{"Content-Type":"application/json"}),e.end(await h.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await ge(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await fe(t):void 0,g=h?.node??m,k=g?d.find(M=>M.url===g):d[0];if(!k){y(e,400,{error:"unknown node"});return}let v=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",_=await fetch(k.url+r+v,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...h,node:void 0})}:{}});y(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await fe(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${h}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),k=await g.json().catch(()=>({error:`HTTP ${g.status}`}));y(e,g.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ge(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sn({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(on({peers:O(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(tn({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let h=ua(await ge(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(h.map(async A=>{try{let S=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:d.signal});if(!S.ok)throw new Error(`HTTP ${S.status}`);return{name:A.name,url:A.url,ok:!0,data:await S.json()}}catch(S){return{name:A.name,url:A.url,ok:!1,error:S.message}}}));y(e,200,{nodes:M});return}let g=h.find(M=>M.url===n.searchParams.get("node"));if(!g){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await pa(t)):void 0,_=await fetch(g.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:v,signal:d.signal,headers:{"Content-Type":"application/json",...g.token?{Authorization:`Bearer ${g.token}`}:{}}});y(e,_.status,await _.json())}catch(h){y(e,502,{error:h.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Cr({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ar({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Mr({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qa({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ir({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers:O(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Fa(t,e);return}if(o==="POST"&&r==="/api/setup"){await Wa(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ga(t,e);return}if(o==="GET"&&r==="/admin"){un(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Sn(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){bn(t,e,O(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}$n(t,e,O(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Ad(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Bt(t,e,r,h=>Io(h,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let h=decodeURIComponent(m[1]),g=h.indexOf("::");if(g>0){let k=h.slice(0,g),v=h.slice(g+2),_=a.config.node?.id||a.config.node?.name||"local";if(k===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`;else{let M=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===k);if(M){let A=ze(M.url.replace(/\/+$/,""),a.config);if(A){await Eo(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=ze(d,a.config);if(!m){y(e,404,{error:`unknown peer: ${d}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Eo(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Ln(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Md(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-IITNYJU5.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",g=await d({running:h});y(e,200,g)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(On({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Pn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Dn({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nn({peers:O(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 id(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 ar(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Bt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await rr(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){ir(t,e,c[1],O(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let h=new Z,g=m?h.verify(m):null;if(!g||!xe(g,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await mn(t,e);return}if(r.startsWith("/api/admin/approvals")){await En(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await yn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await lr(t,e,r);return}if(r.startsWith("/api/admin/")){await fn(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(ln);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let m=Td("web/"+d);try{let h=await Cd(m),g=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":g,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(h)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Be(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",h=await Be(a.config,{date:d,timezone:m});y(e,200,h)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,h,g,k)=>{let v=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(v)?Math.max(g,Math.min(k,v)):h};try{let m=await ge(a.config);y(e,200,await _r(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){y(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(h,g,k,v)=>{let _=parseInt(n.searchParams.get(h)||"",10);return Number.isFinite(_)?Math.max(k,Math.min(v,_)):g};try{let h=await ge(a.config);y(e,200,await Er(h,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(h){y(e,502,{error:h.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let m=n.searchParams,h;if(r==="/api/mesh/thread"){let[g,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!g||!k||!v){y(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/thread?agent=${encodeURIComponent(g)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[g,k]=[m.get("kind"),m.get("key")];if(!g||!k){y(e,400,{error:"kind and key required"});return}h=`/analytics/job?kind=${encodeURIComponent(g)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[g,k,v]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!g||!k||!v){y(e,400,{error:"agent, channel, chat required"});return}h=`/analytics/conversation?agent=${encodeURIComponent(g)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(v)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let g=m.get("task");if(!g){y(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(g)}`}try{await Sr(e,await ge(a.config),d,h)}catch(g){y(e,502,{error:g.message})}return}if(o==="GET"&&r==="/api/live/stream"){fd(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),h=d.searchParams.get("agent"),g=d.searchParams.get("task");if(!m||!h||!g){y(e,400,{error:"node, agent, task query params required"});return}await hd(t,e,a,m,h,g);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),h=d.searchParams.get("agent"),g=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!m||!h){y(e,400,{error:"node and agent query params required"});return}await vd(e,a,m,h,g,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),h=d.searchParams.get("task"),g=d.searchParams.get("kind");if(!m||!h||g!=="cancel"&&g!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await bd(t,e,a,m,h,g);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await aa(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let h=await m.json();y(e,200,h)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){y(e,m.status,{error:`HTTP ${m.status}`});return}y(e,200,await m.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await fe(t);try{let m=await Sd(a.config,d);y(e,200,m)}catch(m){y(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!gd(t,e,[`agent:${d}`]))return;await xd(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let h=new Z,g=m?h.verify(m):null;if(!g||!xe(g,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await ld(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await aa(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let h=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(_=>({name:_.name,url:_.url,token:_.token}))],g={flag:!1},k=[];t.on("close",()=>{g.flag=!0;for(let _ of k)try{_.abort()}catch{}});let v=setInterval(()=>{if(!g.flag)try{e.write(`: ping
16962
17234
 
16963
- `)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let _ of h)(async()=>{let M={Accept:"text/event-stream"};_.token&&(M.Authorization=`Bearer ${_.token}`);let A=new AbortController;k.push(A);try{let S=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:A.signal});if(!S.ok||!S.body)return;let I=S.body.getReader(),R=new TextDecoder,j="";for(;!x.flag;){let{done:B,value:ae}=await I.read();if(B)break;j+=R.decode(ae,{stream:!0});let z;for(;(z=j.indexOf(`
17235
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(v));for(let _ of h)(async()=>{let M={Accept:"text/event-stream"};_.token&&(M.Authorization=`Bearer ${_.token}`);let A=new AbortController;k.push(A);try{let S=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:A.signal});if(!S.ok||!S.body)return;let I=S.body.getReader(),R=new TextDecoder,j="";for(;!g.flag;){let{done:B,value:ne}=await I.read();if(B)break;j+=R.decode(ne,{stream:!0});let z;for(;(z=j.indexOf(`
16964
17236
 
16965
- `))>=0;){let N=j.slice(0,z);if(j=j.slice(z+2),x.flag)break;try{e.write(N+`
17237
+ `))>=0;){let N=j.slice(0,z);if(j=j.slice(z+2),g.flag)break;try{e.write(N+`
16966
17238
 
16967
- `)}catch{x.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let c=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(c.searchParams.get("limit")||50))),h=c.searchParams.get("workflowId")||void 0,x=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:m,workflowId:h}),v=`?limit=${m}${h?`&workflowId=${encodeURIComponent(h)}`:""}${x?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(R=>({url:R.url,token:R.token}))],M=await Promise.all(_.map(async R=>{let j={};R.token&&(j.Authorization=`Bearer ${R.token}`);try{let B=new AbortController,ae=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${R.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:j,signal:B.signal});if(!z.ok)return[];let N=await z.json();return Array.isArray(N.runs)?N.runs:[]}finally{clearTimeout(ae)}}catch{return[]}})),A=new Map;for(let R of k)A.set(R.id,R);for(let R of M)for(let j of R)A.set(j.id,j);let S=Array.from(A.values()).sort((R,j)=>R.updatedAt<j.updatedAt?1:-1).slice(0,m),I=x?S.map(R=>zd(R)):S;y(e,200,{runs:I})}catch(c){y(e,502,{error:"runs fetch failed",message:c.message||String(c)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let c=decodeURIComponent(f[1]),m=a.workflowRuns.get(c);if(m){y(e,200,{run:m});return}let h=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(x=>({url:x.url,token:x.token}))];for(let x of h)try{let k={};x.token&&(k.Authorization=`Bearer ${x.token}`);let v=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(c)}`,{headers:k});if(v.ok){y(e,200,await v.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${m}/api/actions/builtin`,{headers:c}),x=await h.json().catch(()=>({error:`HTTP ${h.status}`}));y(e,h.status,x)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let b=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(b){try{let c=await ue(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${h}/workflows/${encodeURIComponent(b[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,k)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&Cr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,h,x)=>{if(a.token)return!0;let k=vt(m);if(!k)return!0;let v=new Z().verify(k);if(!v)return y(h,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!xe(v,_))return y(h,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(c=>({id:c.id,name:c.name,source:c.source,primaryToolLabel:c.primaryToolLabel,labels:c.labels,columns:c.columns,timeRangeDays:c.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let c=a.sources.get(w[1]);if(!c){y(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(T&&o==="GET"){let c=a.sources.get(T[1]);if(!c){y(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(g&&o==="PATCH"){let[,c,m]=g,h=decodeURIComponent(m),x=a.boards.find(A=>A.id===c);if(!x){y(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){y(e,503,{error:`board "${c}" source unavailable`});return}let v=await ue(t),_=x.columns.find(A=>A.id===v.to),M=x.columns.find(A=>A.id===v.from);if(!_){y(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await Bd(k,h,M,_),Xt({actor:Kt(t),action:"move",boardId:c,itemId:h,payload:{from:v.from,to:v.to}}),y(e,200,{ok:!0})}catch(A){y(e,502,{error:A.message||"transition failed"})}return}if(E){let[,c,m]=E,h=m?decodeURIComponent(m):void 0,x=a.boards.find(v=>v.id===c);if(!x){y(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){y(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!h){let{columns:v,totals:_}=await Hd(x,k,n.searchParams);y(e,200,{columns:v,totals:_});return}if(o==="GET"&&h){try{let v=typeof k.getItem=="function"?await k.getItem(h):null;if(!v){y(e,404,{error:"not found"});return}y(e,200,v)}catch(v){y(e,502,{error:v.message})}return}if(o==="PATCH"&&h){let v=await ue(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(h,v):null;if(!_){y(e,501,{error:"update unsupported"});return}Xt({actor:Kt(t),action:"update",boardId:c,itemId:h,payload:v}),y(e,200,_)}catch(_){y(e,502,{error:_.message})}return}if(o==="POST"&&!h){let v=await ue(t);if(!v.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let _=await k.create({title:v.title,description:v.description,labels:v.labels,assigneeUsernames:v.assigneeUsernames,milestoneTitle:v.milestoneTitle,projectHint:v.projectHint});Xt({actor:Kt(t),action:"create",boardId:c,itemId:_.id,payload:{title:v.title}}),y(e,201,_)}catch(_){y(e,502,{error:_.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let c=r.replace(/^\/+|\/+$/g,""),h={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[c];if(h){e.writeHead(302,{Location:h}),e.end();return}}y(e,404,{error:"not found",path:r})}async function Hd(t,e,a){if(!e.capabilities.listAll||!e.listAll){let c={};for(let m of t.columns)c[m.id]=[];return{columns:c,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(c=>c.kind!=="closed"),u=t.columns.some(c=>c.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],b=u?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let c of t.columns)w[c.id]=[];let T=t.columns.find(c=>c.kind==="closed");for(let c of b)T&&w[T.id].push({...c,stage:T.id});let g=t.columns.filter(c=>c.kind!=="closed");for(let c of f){let m=Zt(c,g);if(!m)continue;let h=w[m];h&&h.push({...c,stage:m})}if(i)for(let c of Object.keys(w))w[c]=w[c].filter(m=>m.assignee===i);for(let c of Object.keys(w))w[c].sort((m,h)=>{let x=(m.priority??99)-(h.priority??99);return x!==0?x:(h.updatedAt||"").localeCompare(m.updatedAt||"")});let E=Object.fromEntries(Object.entries(w).map(([c,m])=>[c,m.length]));return{columns:w,totals:E}}async function Bd(t,e,a,n){let r=ea(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 zd(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 qd(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 Sa(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Xt(t){try{let e=De(process.cwd(),".agentx");mo(e)||Rd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
16968
- `;Ld(De(e,"board-audit.jsonl"),a)}catch{}}function Kt(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function Ud(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,l,d,p,u,f,b,w]=await Promise.all([fetch(t+"/health",{headers:r,signal:a}).catch(()=>null),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),fetch(t+"/mesh",{headers:r,signal:a}).catch(()=>null),fetch(t+"/crons",{headers:r,signal:a}).catch(()=>null),fetch(t+"/crons/runs"+s,{headers:r,signal:a}).catch(()=>null),fetch(t+"/talk",{headers:r,signal:a}).catch(()=>null),fetch(t+"/routines",{headers:r,signal:a}).catch(()=>null),fetch(t+"/attach/sessions",{headers:r,signal:a}).catch(()=>null)]);if(!l||!l.ok)return o.error=l?`HTTP ${l.status}`:"unreachable",o;let T=await l.json();if(o.agents=T.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),i&&i.ok){let g=await i.json();o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(p&&p.ok){let g=await p.json();o.crons=g.map(E=>({id:E.id,enabled:E.enabled===!0,schedule:String(E.schedule||""),timezone:E.timezone,agent:String(E.agent||""),kind:typeof E.command=="string"&&E.command.trim()?"command":"agent",model:E.model,nextRun:E.nextRun,retryPending:E.retryPending===!0,consecutiveErrors:Number(E.consecutiveErrors)||0}))}if(u&&u.ok){let g=await u.json();o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(b&&b.ok){let g=await b.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,pa.routines))}if(f&&f.ok){let g=await f.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Yd(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await Wd(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var dt=null;function Fd(t){if(dt)return dt;let e=De(process.cwd(),".agentx/wiki");return dt=Xa({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),dt}var Jt=new WeakMap;async function Wd(t){if(Jt.has(t))return Jt.get(t);try{let e=t.ok?await t.json():null;return Jt.set(t,e),e}catch{return null}}async function pt(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function Gd(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||ne(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function ge(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=ne(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:ne(a,l)})}let s=await pt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:ne(a,i.url)});return[...o.values()]}var Xd=3e3,Kd=6e3,Jd=5*6e4,Vt=new Map,ct=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=ct.get(a);if(n)return n;let r=(async()=>{let o=await ge(t,AbortSignal.timeout(Xd)),s=await Promise.all(o.map(async i=>{let l=await Ud(i.url,i.token,AbortSignal.timeout(Kd),e);return e?l:Vd(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ct.delete(a));return ct.set(a,r),r}function Vd(t,e,a=Date.now()){if(e.reachable&&!e.error)return Vt.set(t,{node:e,at:a}),e;let n=Vt.get(t);return!n||a-n.at>Jd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function jf(){Vt.clear(),ct.clear()}function Yd(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 Qd(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,d)=>{n||e.write(`event: ${l}
16969
- data: ${JSON.stringify(d)}
17239
+ `)}catch{g.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),h=d.searchParams.get("workflowId")||void 0,g=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:m,workflowId:h}),v=`?limit=${m}${h?`&workflowId=${encodeURIComponent(h)}`:""}${g?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(R=>({url:R.url,token:R.token}))],M=await Promise.all(_.map(async R=>{let j={};R.token&&(j.Authorization=`Bearer ${R.token}`);try{let B=new AbortController,ne=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${R.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:j,signal:B.signal});if(!z.ok)return[];let N=await z.json();return Array.isArray(N.runs)?N.runs:[]}finally{clearTimeout(ne)}}catch{return[]}})),A=new Map;for(let R of k)A.set(R.id,R);for(let R of M)for(let j of R)A.set(j.id,j);let S=Array.from(A.values()).sort((R,j)=>R.updatedAt<j.updatedAt?1:-1).slice(0,m),I=g?S.map(R=>nd(R)):S;y(e,200,{runs:I})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let d=decodeURIComponent(f[1]),m=a.workflowRuns.get(d);if(m){y(e,200,{run:m});return}let h=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(g=>({url:g.url,token:g.token}))];for(let g of h)try{let k={};g.token&&(k.Authorization=`Bearer ${g.token}`);let v=await fetch(`${g.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(v.ok){y(e,200,await v.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),h=await fetch(`${m}/api/actions/builtin`,{headers:d}),g=await h.json().catch(()=>({error:`HTTP ${h.status}`}));y(e,h.status,g)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let b=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(b){try{let d=await fe(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let h=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${h}/workflows/${encodeURIComponent(b[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),k=await g.json().catch(()=>({error:`HTTP ${g.status}`}));y(e,g.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Rr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,h,g)=>{if(a.token)return!0;let k=kt(m);if(!k)return!0;let v=new Z().verify(k);if(!v)return y(h,401,{error:"invalid or revoked token"}),!1;for(let _ of g)if(!xe(v,_))return y(h,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let d=a.sources.get(w[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(T&&o==="GET"){let d=a.sources.get(T[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),x=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,d,m]=E,h=decodeURIComponent(m),g=a.boards.find(A=>A.id===d);if(!g){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let v=await fe(t),_=g.columns.find(A=>A.id===v.to),M=g.columns.find(A=>A.id===v.from);if(!_){y(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await ad(k,h,M,_),Zt({actor:ea(t),action:"move",boardId:d,itemId:h,payload:{from:v.from,to:v.to}}),y(e,200,{ok:!0})}catch(A){y(e,502,{error:A.message||"transition failed"})}return}if(x){let[,d,m]=x,h=m?decodeURIComponent(m):void 0,g=a.boards.find(v=>v.id===d);if(!g){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!h){let{columns:v,totals:_}=await td(g,k,n.searchParams);y(e,200,{columns:v,totals:_});return}if(o==="GET"&&h){try{let v=typeof k.getItem=="function"?await k.getItem(h):null;if(!v){y(e,404,{error:"not found"});return}y(e,200,v)}catch(v){y(e,502,{error:v.message})}return}if(o==="PATCH"&&h){let v=await fe(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(h,v):null;if(!_){y(e,501,{error:"update unsupported"});return}Zt({actor:ea(t),action:"update",boardId:d,itemId:h,payload:v}),y(e,200,_)}catch(_){y(e,502,{error:_.message})}return}if(o==="POST"&&!h){let v=await fe(t);if(!v.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let _=await k.create({title:v.title,description:v.description,labels:v.labels,assigneeUsernames:v.assigneeUsernames,milestoneTitle:v.milestoneTitle,projectHint:v.projectHint});Zt({actor:ea(t),action:"create",boardId:d,itemId:_.id,payload:{title:v.title}}),y(e,201,_)}catch(_){y(e,502,{error:_.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),h={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(h){e.writeHead(302,{Location:h}),e.end();return}}y(e,404,{error:"not found",path:r})}async function td(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let m of t.columns)d[m.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],b=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let d of t.columns)w[d.id]=[];let T=t.columns.find(d=>d.kind==="closed");for(let d of b)T&&w[T.id].push({...d,stage:T.id});let E=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=ra(d,E);if(!m)continue;let h=w[m];h&&h.push({...d,stage:m})}if(i)for(let d of Object.keys(w))w[d]=w[d].filter(m=>m.assignee===i);for(let d of Object.keys(w))w[d].sort((m,h)=>{let g=(m.priority??99)-(h.priority??99);return g!==0?g:(h.updatedAt||"").localeCompare(m.updatedAt||"")});let x=Object.fromEntries(Object.entries(w).map(([d,m])=>[d,m.length]));return{columns:w,totals:x}}async function ad(t,e,a,n){let r=oa(a,n),o=t;r.closeIssue&&typeof o.setState=="function"?await o.setState(e,"close"):r.reopen&&typeof o.setState=="function"&&await o.setState(e,"reopen"),(r.addLabels?.length||r.removeLabels?.length)&&typeof o.transitionMany=="function"?await o.transitionMany(e,r.addLabels||[],r.removeLabels||[]):r.addLabels?.length&&t.transition&&await t.transition(e,r.addLabels[0],r.removeLabels?.[0])}function nd(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 rd(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 Ia(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Zt(t){try{let e=He(process.cwd(),".agentx");To(e)||Jc(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
17240
+ `;Kc(He(e,"board-audit.jsonl"),a)}catch{}}function ea(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var od=2e3;async function sd(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 d=new AbortController,m=setTimeout(()=>d.abort(),od),h=()=>d.abort();return a?.addEventListener("abort",h,{once:!0}),fetch(t+x,{headers:r,signal:d.signal}).then(async g=>{let k=g.ok?await g.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",h)})},[l,c,p,u,f,b,w,T]=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(u&&u.ok){let x=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=x.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(f&&f.ok){let x=await f.json().catch(()=>({}));o.cronRuns=Array.isArray(x.runs)?x.runs:[]}if(w&&w.ok){let x=await w.json().catch(()=>null);x&&Array.isArray(x.routines)&&(o.routines=x.routines.slice(0,ga.routines))}if(b&&b.ok){let x=await b.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(T&&T.ok){let x=await T.json().catch(()=>null);x&&Array.isArray(x.sessions)&&md(o,x.sessions,x.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var mt=null;function id(t){if(mt)return mt;let e=He(process.cwd(),".agentx/wiki");return mt=Za({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),mt}async function ht(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 ld(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||re(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function ge(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=re(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:re(a,l)})}let s=await ht(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:re(a,i.url)});return[...o.values()]}var cd=3e3,dd=6e3,pd=5*6e4,ta=new Map,ft=new Map;function Be(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=ft.get(a);if(n)return n;let r=(async()=>{let o=await ge(t,AbortSignal.timeout(cd)),s=await Promise.all(o.map(async i=>{let l=await sd(i.url,i.token,AbortSignal.timeout(dd),e);return e?l:ud(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ft.delete(a));return ft.set(a,r),r}function ud(t,e,a=Date.now()){if(e.reachable&&!e.error)return ta.set(t,{node:e,at:a}),e;let n=ta.get(t);return!n||a-n.at>pd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function ih(){ta.clear(),ft.clear()}function md(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 fd(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}
17241
+ data: ${JSON.stringify(c)}
16970
17242
 
16971
- `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ne(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}finally{o=!1}}};s();let i=setInterval(s,2e3);t.on("close",()=>{n=!0,clearInterval(i),e.end()})}async function Zd(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await pt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=ne(a.config.dashboard,s),d={Accept:"text/event-stream"};l&&(d.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:p.signal})}catch(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:T}=await f.read();if(T)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function ec(t,e,a){let n=vt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Z().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!xe(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function tc(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ue(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(d){y(e,502,{error:d.message||"upstream call failed"})}}async function ac(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await pt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=ne(e.config.dashboard,s),d={Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:d}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function nc(t,e,a,n,r,o){await Yt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Yt(t,e,a,n,r){let o={};try{o=await ue(t)??{}}catch{}let s=await fo(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function fo(t,e,a,n){let r=(d,p)=>({status:d,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let d of t.dashboard.daemons)s.add(d.url.replace(/\/+$/,""));try{let d=await pt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of d)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=ne(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let d=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:d.status,text:await d.text(),contentType:d.headers.get("content-type")||"application/json; charset=utf-8"}}catch(d){return r(502,{error:d.message||"upstream fetch failed"})}}function rc(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=fa(e.keysFile);return{store:()=>{let r=Be();return r?new Ia(r):null},publicKey:()=>ha(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function ho(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ne(t,n),async nodePost(n,r,o){let s=await fo(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=qe({root:process.cwd()}).items.map(po)}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=He(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let d=await l.json();s.items=(d.items??[]).map(po)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let d=_e(),p=await Ue({root:process.cwd()},r,o,{laterHours:d.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=He(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let d=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:d.status,body:a(await d.text())}}catch(d){return{status:502,body:{error:d.message||"peer dashboard unreachable"}}}}}}function oc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=ne(t.dashboard,e),n=ho(t);return{store:()=>{let r=Be();return r?new Oe(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ne(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s)}}function sc(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Be();return a?new Oe(a):null},daemon:{url:e,token:ne(t.dashboard,e)}}}function po(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var ic=`
17243
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Be(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 hd(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await ht(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=re(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:T}=await f.read();if(T)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function gd(t,e,a){let n=kt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Z().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!xe(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function xd(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await fe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function vd(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await ht(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=re(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:c}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function bd(t,e,a,n,r,o){await aa(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function aa(t,e,a,n,r){let o={};try{o=await fe(t)??{}}catch{}let s=await Co(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Co(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await ht(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=re(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 yd(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=ya(e.keysFile);return{store:()=>{let r=qe();return r?new Oa(r):null},publicKey:()=>wa(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Ao(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Be(t,n),async nodePost(n,r,o){let s=await Co(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=Fe({root:process.cwd()}).items.map(So)}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=ze(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(So)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=Se(),p=await We({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=ze(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}function wd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=re(t.dashboard,e),n=Ao(t);return{store:()=>{let r=qe();return r?new Ne(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Be(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)}}function kd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=qe();return a?new Ne(a):null},daemon:{url:e,token:re(t.dashboard,e)}}}function So(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var _d=`
16972
17244
  You are helping draft a new GitLab issue. Follow these conventions strictly.
16973
17245
 
16974
17246
  Title pattern:
@@ -17000,16 +17272,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
17000
17272
  Shape:
17001
17273
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
17002
17274
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
17003
- `;async function lc(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):
17275
+ `;async function Sd(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):
17004
17276
  - ${r.knownLabels.slice(0,60).join(`
17005
17277
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
17006
- `),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:ic}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let d=await l.json();if(d.error)throw new Error(String(d.error));let p=(d.content||"").toString(),u=dc(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.labels.filter(b=>typeof b=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function dc(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 cc(t){let e=Od(Pd(import.meta.url));return De(e,t)}async function pc(t){return jd(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ue(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 go(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function O(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:go(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 uc(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await rt(await xo(r,a.config)))}async function xo(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Pt(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=He(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:d.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return Kn(n)}async function mc(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),b=f.find(w=>mo(w));if(!b){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:f}));return}r="tail",o=["-F","-n","200",b]}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}
17278
+ `),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:_d}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),u=Ed(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.labels.filter(b=>typeof b=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function Ed(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 Td(t){let e=Qc(Yc(import.meta.url));return He(e,t)}async function Cd(t){return Vc(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function fe(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 Mo(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function O(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:Mo(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 Ad(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await st(await Io(r,a.config)))}async function Io(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ht(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=ze(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return er(n)}async function Md(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),b=f.find(w=>To(w));if(!b){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:f}));return}r="tail",o=["-F","-n","200",b]}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}
17007
17279
 
17008
17280
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
17009
17281
  `))>=0;){let b=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
17010
17282
  data: ${b.replace(/\n/g," ")}
17011
17283
 
17012
- `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
17284
+ `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
17013
17285
 
17014
- `)}catch{}},15e3),p=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function uo(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let b=[];t.on("data",w=>b.push(w)),t.on("end",()=>u(Buffer.concat(b))),t.on("error",f)}):void 0,l={},d=t.headers["content-type"];d&&(l["Content-Type"]=Array.isArray(d)?d[0]:d);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function He(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:go(n),token:n.dashboardToken||n.token}:null}export{Yd as applyAttachSessions,Nd as handleBoardRequest,jf as resetLiveCaches,ge as resolveNodeTargets,Rf as startBoardDashboard,Vd as withLastGood};
17015
- //# sourceMappingURL=board-dashboard-27XK4IL5.js.map
17286
+ `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function Eo(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let b=[];t.on("data",w=>b.push(w)),t.on("end",()=>u(Buffer.concat(b))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function ze(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Mo(n),token:n.dashboardToken||n.token}:null}export{md as applyAttachSessions,sd as fetchDaemonAgents,ed as handleBoardRequest,ih as resetLiveCaches,ge as resolveNodeTargets,sh as startBoardDashboard,ud as withLastGood};
17287
+ //# sourceMappingURL=board-dashboard-SMCZBJKO.js.map