agentix-cli 0.58.0 → 0.60.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 (130) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/AgentClient.swift +4 -0
  2. package/apps/mac-voice/Sources/AgentXVoice/AnswerView.swift +228 -0
  3. package/apps/mac-voice/Sources/AgentXVoice/HistoryClient.swift +55 -0
  4. package/apps/mac-voice/Sources/AgentXVoice/HistoryModel.swift +153 -0
  5. package/apps/mac-voice/Sources/AgentXVoice/HistoryWindow.swift +301 -0
  6. package/apps/mac-voice/Sources/AgentXVoice/LocalSTT.swift +79 -0
  7. package/apps/mac-voice/Sources/AgentXVoice/ModelStore.swift +184 -0
  8. package/apps/mac-voice/Sources/AgentXVoice/Orb.swift +36 -9
  9. package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +126 -55
  10. package/apps/mac-voice/Sources/AgentXVoice/PanelAnswer.swift +113 -0
  11. package/apps/mac-voice/Sources/AgentXVoice/Parakeet.swift +264 -0
  12. package/apps/mac-voice/Sources/AgentXVoice/PillPlacement.swift +28 -17
  13. package/apps/mac-voice/Sources/AgentXVoice/Recorder.swift +81 -3
  14. package/apps/mac-voice/Sources/AgentXVoice/SettingsLook.swift +90 -0
  15. package/apps/mac-voice/Sources/AgentXVoice/SettingsWindow.swift +20 -5
  16. package/apps/mac-voice/Sources/AgentXVoice/SileroVAD.swift +92 -0
  17. package/apps/mac-voice/Sources/AgentXVoice/Speech.swift +7 -5
  18. package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +14 -1
  19. package/apps/mac-voice/Sources/AgentXVoice/Surface.swift +105 -0
  20. package/apps/mac-voice/Sources/AgentXVoice/TurnEnd.swift +110 -0
  21. package/apps/mac-voice/Sources/AgentXVoice/VoiceSettings.swift +54 -0
  22. package/apps/mac-voice/Sources/AgentXVoice/main.swift +35 -36
  23. package/apps/mac-voice/build.sh +10 -1
  24. package/dist/{App-Z5VOAUXB.js → App-LQXWKBVY.js} +2 -2
  25. package/dist/{ChatApp-BE7ONQKS.js → ChatApp-75TL4LKW.js} +2 -2
  26. package/dist/{agent-Q74EISKP.js → agent-DH4FMMMY.js} +2 -2
  27. package/dist/{board-dashboard-A7PQOI6C.js → board-dashboard-BVRRDYAG.js} +223 -138
  28. package/dist/board-dashboard-BVRRDYAG.js.map +1 -0
  29. package/dist/{chunk-NKMFHEGV.js → chunk-27P5NLTC.js} +2 -2
  30. package/dist/{chunk-5LLGIX5M.js → chunk-2VQIPJH5.js} +2 -2
  31. package/dist/{chunk-V7ZK6ZIO.js → chunk-3XVTFNYM.js} +2 -2
  32. package/dist/{chunk-KW7TIOS3.js → chunk-B3DCYBP4.js} +2 -2
  33. package/dist/{chunk-547G3HYQ.js → chunk-CRSXKQLZ.js} +2 -2
  34. package/dist/{chunk-5W7NJHCS.js → chunk-DTEQNXK3.js} +2 -2
  35. package/dist/{chunk-XTD3SZIP.js → chunk-E2BJVHBR.js} +2 -2
  36. package/dist/{chunk-RXEAACVH.js → chunk-E2PWCU2N.js} +2 -2
  37. package/dist/{chunk-I2LYULR4.js → chunk-JO3PSLWL.js} +5 -5
  38. package/dist/{chunk-U5YBQJ5Q.js → chunk-JORXRF4E.js} +2 -2
  39. package/dist/{chunk-2MIOMYT2.js → chunk-LXUG2X26.js} +2 -2
  40. package/dist/{chunk-Q6SMLSRO.js → chunk-N5KD3TVN.js} +2 -2
  41. package/dist/{chunk-VI7GBDKV.js → chunk-NBGNPKAF.js} +2 -2
  42. package/dist/{chunk-6QNPCVRN.js → chunk-PAOV37KQ.js} +3 -3
  43. package/dist/chunk-PAOV37KQ.js.map +1 -0
  44. package/dist/{chunk-OZZPJ2YG.js → chunk-RYFUFX6F.js} +194 -181
  45. package/dist/chunk-RYFUFX6F.js.map +1 -0
  46. package/dist/chunk-S7TCVIET.js +15 -0
  47. package/dist/chunk-S7TCVIET.js.map +1 -0
  48. package/dist/{chunk-POL7RAJQ.js → chunk-TM762AXU.js} +159 -153
  49. package/dist/chunk-TM762AXU.js.map +1 -0
  50. package/dist/{chunk-6OABTCRA.js → chunk-WBGC7MWX.js} +2 -2
  51. package/dist/{chunk-CQUVUVXR.js → chunk-WIBMNQKJ.js} +2 -2
  52. package/dist/{chunk-KKGFZEXS.js → chunk-WOPFHKBF.js} +37 -36
  53. package/dist/chunk-WOPFHKBF.js.map +1 -0
  54. package/dist/{chunk-VVBGPT6W.js → chunk-YQCOX4R3.js} +2 -2
  55. package/dist/cli.js +1 -1
  56. package/dist/client-QVZIZFV4.js +2 -0
  57. package/dist/config-3XC7EYB7.js +2 -0
  58. package/dist/config-mutator-HKU63FJM.js +2 -0
  59. package/dist/doctor-YFA4ZSRH.js +2 -0
  60. package/dist/index.d.ts +66 -7
  61. package/dist/index.js +1 -1
  62. package/dist/program-BOCLU6ES.js +2 -0
  63. package/dist/{promote-KVPLDSKT.js → promote-UR2GSHKC.js} +2 -2
  64. package/dist/query-XUP3BMVS.js +2 -0
  65. package/dist/{registry-AUOI4TW2.js → registry-PGALUW5L.js} +2 -2
  66. package/dist/{request-planner-LMZ5ZAXC.js → request-planner-NHE3IRJN.js} +2 -2
  67. package/dist/{review-candidates-WCBXLLDS.js → review-candidates-6GKRSRBQ.js} +2 -2
  68. package/dist/{routing-FBASYKUL.js → routing-AQKHAU3Z.js} +2 -2
  69. package/dist/schedule-tool-6NMCLTIH.js +2 -0
  70. package/dist/scheduler-RAYGNDWT.js +2 -0
  71. package/dist/{seat-DBFW3Z5P.js → seat-6FMW2QI4.js} +2 -2
  72. package/dist/{select-6CNVVFA5.js → select-5VONJMLH.js} +2 -2
  73. package/dist/{set-enabled-AYZH3KSB.js → set-enabled-YHD3IJJZ.js} +2 -2
  74. package/dist/{tool-PKS4NBZ6.js → tool-MXJGLJZ5.js} +2 -2
  75. package/dist/wiki-ZQLEYY24.js +2 -0
  76. package/package.json +1 -1
  77. package/apps/mac-voice/Sources/AgentXVoice/ResultCard.swift +0 -198
  78. package/dist/board-dashboard-A7PQOI6C.js.map +0 -1
  79. package/dist/chunk-6QNPCVRN.js.map +0 -1
  80. package/dist/chunk-ERL6AS3O.js +0 -15
  81. package/dist/chunk-ERL6AS3O.js.map +0 -1
  82. package/dist/chunk-KKGFZEXS.js.map +0 -1
  83. package/dist/chunk-OZZPJ2YG.js.map +0 -1
  84. package/dist/chunk-POL7RAJQ.js.map +0 -1
  85. package/dist/client-EFP2PKA3.js +0 -2
  86. package/dist/config-P6YXC6XZ.js +0 -2
  87. package/dist/config-mutator-3GKXLTHH.js +0 -2
  88. package/dist/doctor-JEWMHXYH.js +0 -2
  89. package/dist/program-7DUQJDSQ.js +0 -2
  90. package/dist/query-AGOMCYTT.js +0 -2
  91. package/dist/schedule-tool-RJRJ63SS.js +0 -2
  92. package/dist/scheduler-ATA7Z44S.js +0 -2
  93. package/dist/wiki-QW6BDNEQ.js +0 -2
  94. /package/dist/{App-Z5VOAUXB.js.map → App-LQXWKBVY.js.map} +0 -0
  95. /package/dist/{ChatApp-BE7ONQKS.js.map → ChatApp-75TL4LKW.js.map} +0 -0
  96. /package/dist/{agent-Q74EISKP.js.map → agent-DH4FMMMY.js.map} +0 -0
  97. /package/dist/{chunk-NKMFHEGV.js.map → chunk-27P5NLTC.js.map} +0 -0
  98. /package/dist/{chunk-5LLGIX5M.js.map → chunk-2VQIPJH5.js.map} +0 -0
  99. /package/dist/{chunk-V7ZK6ZIO.js.map → chunk-3XVTFNYM.js.map} +0 -0
  100. /package/dist/{chunk-KW7TIOS3.js.map → chunk-B3DCYBP4.js.map} +0 -0
  101. /package/dist/{chunk-547G3HYQ.js.map → chunk-CRSXKQLZ.js.map} +0 -0
  102. /package/dist/{chunk-5W7NJHCS.js.map → chunk-DTEQNXK3.js.map} +0 -0
  103. /package/dist/{chunk-XTD3SZIP.js.map → chunk-E2BJVHBR.js.map} +0 -0
  104. /package/dist/{chunk-RXEAACVH.js.map → chunk-E2PWCU2N.js.map} +0 -0
  105. /package/dist/{chunk-I2LYULR4.js.map → chunk-JO3PSLWL.js.map} +0 -0
  106. /package/dist/{chunk-U5YBQJ5Q.js.map → chunk-JORXRF4E.js.map} +0 -0
  107. /package/dist/{chunk-2MIOMYT2.js.map → chunk-LXUG2X26.js.map} +0 -0
  108. /package/dist/{chunk-Q6SMLSRO.js.map → chunk-N5KD3TVN.js.map} +0 -0
  109. /package/dist/{chunk-VI7GBDKV.js.map → chunk-NBGNPKAF.js.map} +0 -0
  110. /package/dist/{chunk-6OABTCRA.js.map → chunk-WBGC7MWX.js.map} +0 -0
  111. /package/dist/{chunk-CQUVUVXR.js.map → chunk-WIBMNQKJ.js.map} +0 -0
  112. /package/dist/{chunk-VVBGPT6W.js.map → chunk-YQCOX4R3.js.map} +0 -0
  113. /package/dist/{client-EFP2PKA3.js.map → client-QVZIZFV4.js.map} +0 -0
  114. /package/dist/{config-P6YXC6XZ.js.map → config-3XC7EYB7.js.map} +0 -0
  115. /package/dist/{config-mutator-3GKXLTHH.js.map → config-mutator-HKU63FJM.js.map} +0 -0
  116. /package/dist/{doctor-JEWMHXYH.js.map → doctor-YFA4ZSRH.js.map} +0 -0
  117. /package/dist/{program-7DUQJDSQ.js.map → program-BOCLU6ES.js.map} +0 -0
  118. /package/dist/{promote-KVPLDSKT.js.map → promote-UR2GSHKC.js.map} +0 -0
  119. /package/dist/{query-AGOMCYTT.js.map → query-XUP3BMVS.js.map} +0 -0
  120. /package/dist/{registry-AUOI4TW2.js.map → registry-PGALUW5L.js.map} +0 -0
  121. /package/dist/{request-planner-LMZ5ZAXC.js.map → request-planner-NHE3IRJN.js.map} +0 -0
  122. /package/dist/{review-candidates-WCBXLLDS.js.map → review-candidates-6GKRSRBQ.js.map} +0 -0
  123. /package/dist/{routing-FBASYKUL.js.map → routing-AQKHAU3Z.js.map} +0 -0
  124. /package/dist/{schedule-tool-RJRJ63SS.js.map → schedule-tool-6NMCLTIH.js.map} +0 -0
  125. /package/dist/{scheduler-ATA7Z44S.js.map → scheduler-RAYGNDWT.js.map} +0 -0
  126. /package/dist/{seat-DBFW3Z5P.js.map → seat-6FMW2QI4.js.map} +0 -0
  127. /package/dist/{select-6CNVVFA5.js.map → select-5VONJMLH.js.map} +0 -0
  128. /package/dist/{set-enabled-AYZH3KSB.js.map → set-enabled-YHD3IJJZ.js.map} +0 -0
  129. /package/dist/{tool-PKS4NBZ6.js.map → tool-MXJGLJZ5.js.map} +0 -0
  130. /package/dist/{wiki-QW6BDNEQ.js.map → wiki-ZQLEYY24.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as ka}from"./chunk-WWMFNLKD.js";import{a as Aa}from"./chunk-GUJB53QU.js";import{a as C,b as Ma,c as Ia,d as $a,e as La,f as we,g as ja,h as Ra,i as Na,j as Oa,k as Da}from"./chunk-KKGFZEXS.js";import{a as Pa}from"./chunk-Z3IP66SL.js";import{a as _a,b as ue,c as Ea,d as $,e as P,j as Ge,k as Xe,l as Z,m as U,n as Ke,o as Sa,p as Ta,q as Ca}from"./chunk-KAFO5QZR.js";import{A as Be,G as se,H as ua,I as ma,N as ga,P as ye,Q as ze,R as qe,S as Ue,T as Fe,U as xa,V as va,W as ba,X as We,Z as ya,a as ra,aa as wa,c as De,d as ht,e as oa,i as sa,k as ia,m as Q,n as ge,o as gt,z as He}from"./chunk-6QNPCVRN.js";import{g as aa,h as na}from"./chunk-RXEAACVH.js";import{o as la,r as da}from"./chunk-S7CVSKOX.js";import{a as fa,b as ha}from"./chunk-LQRBGQIR.js";import"./chunk-NKMFHEGV.js";import"./chunk-2MIOMYT2.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ca,c as pa}from"./chunk-2D3RYIDU.js";import{a as Qt,c as mt,d as ft,h as Zt,i as ea,j as ta}from"./chunk-CQUVUVXR.js";import"./chunk-WP6KLXTP.js";import{a as ut}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-U5YBQJ5Q.js";import"./chunk-547G3HYQ.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-5LLGIX5M.js";import{b as Yt}from"./chunk-XTD3SZIP.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-VI7GBDKV.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 Jt,b as Vt,c as Zr,r as Y,u as pt}from"./chunk-ERL6AS3O.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function xt(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 Ha(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:xt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ee={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"/>'},xe=(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>",Je=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+xe(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ba(t={}){return $({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as Ea}from"./chunk-WWMFNLKD.js";import{a as Ia}from"./chunk-GUJB53QU.js";import{a as C,b as $a,c as La,d as ja,e as Ra,h as Pa,i as ke,j as Oa,k as Na,l as Ha,m as Ba,n as za}from"./chunk-WOPFHKBF.js";import{a as Da}from"./chunk-Z3IP66SL.js";import{a as Sa,b as ue,c as Ta,d as $,e as P,j as Ge,k as Xe,l as Z,m as U,n as Ke,o as Ca,p as Aa,q as Ma}from"./chunk-KAFO5QZR.js";import{A as Be,G as se,H as fa,I as ha,N as va,P as we,Q as ze,R as qe,S as Ue,T as Fe,U as ba,V as ya,W as wa,X as We,Z as ka,a as sa,aa as _a,c as De,d as gt,e as ia,i as la,k as da,m as Q,n as ge,o as xt,z as He}from"./chunk-PAOV37KQ.js";import{g as ra,h as oa}from"./chunk-E2PWCU2N.js";import{o as ca,r as pa}from"./chunk-S7CVSKOX.js";import{a as ga,b as xa}from"./chunk-LQRBGQIR.js";import"./chunk-27P5NLTC.js";import"./chunk-LXUG2X26.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as ua,c as ma}from"./chunk-2D3RYIDU.js";import{a as ea,c as ft,d as ht,h as ta,i as aa,j as na}from"./chunk-WIBMNQKJ.js";import"./chunk-WP6KLXTP.js";import{a as mt}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-JORXRF4E.js";import"./chunk-CRSXKQLZ.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-2VQIPJH5.js";import{b as Zt}from"./chunk-E2BJVHBR.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-NBGNPKAF.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 Yt,b as Qt,c as so,w as Y,z as ut}from"./chunk-S7TCVIET.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function vt(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 qa(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:vt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var ee={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"/>'},xe=(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>",Je=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+xe(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ua(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>
@@ -85,7 +85,7 @@ ${Je(ee.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:eo,scripts:`<script>${ue({decayOf:xt,rankByDecay:Ha})}const ICON = ${JSON.stringify(ee)};${to}</script>`})}var eo=`
88
+ </div>`,css:io,scripts:`<script>${ue({decayOf:vt,rankByDecay:qa})}const ICON = ${JSON.stringify(ee)};${lo}</script>`})}var io=`
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
- }`,to=String.raw`
364
+ }`,lo=String.raw`
365
365
  (function(){
366
366
  const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
367
367
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -776,13 +776,13 @@ if(document.querySelector('form :focus'))return;
776
776
  if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
777
777
  refresh();
778
778
  },15000);
779
- })();`;function vt(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 bt(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 za(t,e=[],a){let{bands:n,gaps:r}=vt(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,y=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:y,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)=>bt(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 ao}from"crypto";import{readFileSync as no,statSync as ro}from"fs";import{resolve as oo,dirname as so}from"path";import{fileURLToPath as io}from"url";var qa=new Map;function Ve(t){let e=qa.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=so(io(import.meta.url)),r=oo(n,"web",t),o=ro(r),s=o.size<8e6?ao("sha1").update(no(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return qa.set(t,a),a}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"/>',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"/>'},Ye=(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>",lo=[["agent","Agent",ae.bot],["client","Client",ae.user],["project","Project",ae.folder],["channel","Channel",ae.route],["node","Node",ae.mesh]],Ua={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 Fa(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 bt(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 yt(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 Fa(t,e=[],a){let{bands:n,gaps:r}=bt(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,y=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:y,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)=>yt(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 co}from"crypto";import{readFileSync as po,statSync as uo}from"fs";import{resolve as mo,dirname as fo}from"path";import{fileURLToPath as ho}from"url";var Wa=new Map;function Ve(t){let e=Wa.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=fo(ho(import.meta.url)),r=mo(n,"web",t),o=uo(r),s=o.size<8e6?co("sha1").update(po(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Wa.set(t,a),a}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"/>',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"/>'},Ye=(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>",go=[["agent","Agent",ae.bot],["client","Client",ae.user],["project","Project",ae.folder],["channel","Channel",ae.route],["node","Node",ae.mesh]],Ga={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 Xa(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">${Ua[e]}</p>
785
+ <p class="ac-sub" id="sub">${Ga[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
@@ -799,7 +799,7 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${lo.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ye(o,13)}${r}</button>`).join("")}
802
+ ${go.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Ye(o,13)}${r}</button>`).join("")}
803
803
  </div>
804
804
  <div class="ac-key">
805
805
  <span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
@@ -819,7 +819,7 @@ refresh();
819
819
  <div id="ax-fleet-root" data-hours="24" data-src="${Ve("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:co,scripts:`<script>${ue({computeBands:vt,packTracks:bt,buildTimeline:za})}const ICON = ${JSON.stringify(ae)};const SUB = ${JSON.stringify(Ua)};${po}</script>`})}var co=`
822
+ </div>`,css:xo,scripts:`<script>${ue({computeBands:bt,packTracks:yt,buildTimeline:Fa})}const ICON = ${JSON.stringify(ae)};const SUB = ${JSON.stringify(Ga)};${vo}</script>`})}var xo=`
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
- `,po=String.raw`
908
+ `,vo=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 Wa(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:uo,scripts:`<script src="${Ve("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var uo=`
1025
+ `;function Ka(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:bo,scripts:`<script src="${Ve("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var bo=`
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 rd}from"http";import{appendFileSync as od,existsSync as Gr,mkdirSync as sd}from"fs";import{readFile as id}from"fs/promises";import{fileURLToPath as ld}from"url";import{dirname as dd,resolve as Pe}from"path";Zr();var Ga='/*! 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 Qe,readFileSync as Ka,writeFileSync as Ja,rmSync as cc,mkdirSync as vo,copyFileSync as bo,readdirSync as yo}from"fs";import{resolve as ke}from"path";pt();var ne={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 Xa(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Ge({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.`})+Xe([{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+fo()+Sa,css:go,scripts:`${e}<script>${Ta}
1047
- ${Ca}
1048
- ${mo}
1049
- ${xo}</script>`})}var mo=`
1046
+ `;import{createServer as gd}from"http";import{appendFileSync as xd,existsSync as Zr,mkdirSync as vd}from"fs";import{readFile as bd}from"fs/promises";import{fileURLToPath as yd}from"url";import{dirname as wd,resolve as Pe}from"path";so();var Ja='/*! 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 Qe,readFileSync as Ya,writeFileSync as Qa,rmSync as kc,mkdirSync as So,copyFileSync as To,readdirSync as Co}from"fs";import{resolve as _e}from"path";ut();var ne={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 Va(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Ge({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.`})+Xe([{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+wo()+Ca,css:_o,scripts:`${e}<script>${Aa}
1047
+ ${Ma}
1048
+ ${yo}
1049
+ ${Eo}</script>`})}var yo=`
1050
1050
  (function(){
1051
1051
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1052
1052
  async function refresh() {
@@ -1107,8 +1107,8 @@ ${xo}</script>`})}var mo=`
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 fo(){let t=ha().business?`<button data-tab="business">Business</button>
1111
- `:"";return ho.replace("__BUSINESS_TABS__",t)}var ho=`
1110
+ })();`;function wo(){let t=xa().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>
@@ -1745,7 +1745,7 @@ ${xo}</script>`})}var mo=`
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
- `,go=`
1748
+ `,_o=`
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
- `,xo=`
1956
+ `,Eo=`
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 Va(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({peers:a,localToken:n}))}async function Ya(t,e){let a=kt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Qa(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ro(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await wo(t),r={"GET /api/admin/state":()=>_o(),"POST /api/admin/agents":()=>Mo(n),"PATCH /api/admin/agents":()=>Io(n),"DELETE /api/admin/agents":()=>$o(n),"POST /api/admin/agents/access":()=>Eo(n),"POST /api/admin/channels/telegram":()=>Lo(n),"DELETE /api/admin/channels/telegram":()=>as(n),"POST /api/admin/channels/telegram/toggle":()=>ns(n),"POST /api/admin/crons":()=>rs(n),"DELETE /api/admin/crons":()=>os(n),"POST /api/admin/config/raw":()=>ss(n),"GET /api/admin/tokens":()=>So(),"POST /api/admin/tokens":()=>To(n),"DELETE /api/admin/tokens":()=>Co(n),"POST /api/admin/agents/test":()=>Ao(n),"POST /api/admin/agents/integrations":()=>Bo(n),"DELETE /api/admin/agents/integrations":()=>zo(n),"PATCH /api/admin/agents/integrations":()=>qo(n),"PATCH /api/admin/channels/telegram":()=>jo(n),"POST /api/admin/channels/slack":()=>Jo(n),"POST /api/admin/channels/slack/toggle":()=>Vo(n),"POST /api/admin/channels/discord":()=>Yo(n),"POST /api/admin/channels/discord/toggle":()=>Qo(n),"POST /api/admin/channels/gitlab":()=>Zo(n),"POST /api/admin/channels/gitlab/toggle":()=>es(n),"GET /api/admin/channels/whatsapp/state":()=>Me("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Me("/webrtc/history"),"POST /api/admin/actions":()=>bs(n),"DELETE /api/admin/actions":()=>ys(n),"POST /api/admin/actions/run":()=>ws(n),"GET /api/admin/channels/whatsapp/chats":()=>Me("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Me("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ie("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ts(n),"POST /api/admin/webhooks":()=>Uo(n),"PATCH /api/admin/webhooks":()=>Fo(n),"DELETE /api/admin/webhooks":()=>Ko(n),"POST /api/admin/mesh/peers":()=>Wo(n),"DELETE /api/admin/mesh/peers":()=>Go(n),"POST /api/admin/mesh/toggle":()=>Xo(n),"GET /api/admin/files":()=>Po(t),"GET /api/admin/files/read":()=>No(t),"PUT /api/admin/files":()=>Oo(n),"POST /api/admin/files/skill":()=>Do(n),"DELETE /api/admin/files/skill":()=>Ho(n),"POST /api/admin/business/orgchart":()=>is(n),"DELETE /api/admin/business/orgchart":()=>ls(n),"POST /api/admin/business/project":()=>ds(n),"DELETE /api/admin/business/project":()=>us(n),"POST /api/admin/business/client":()=>cs(n),"DELETE /api/admin/business/client":()=>ps(n),"POST /api/admin/business/contact":()=>ms(n),"DELETE /api/admin/business/contact":()=>fs(n),"POST /api/admin/boards":()=>hs(n),"DELETE /api/admin/boards":()=>gs(n),"POST /api/admin/boards/columns":()=>xs(n),"DELETE /api/admin/boards/columns":()=>vs(n),"POST /api/admin/notifications":()=>_s(n),"POST /api/admin/screen":()=>Es(n),"POST /api/admin/webhooks/triggers":()=>Ss(n),"POST /api/admin/mesh/health":()=>ks(n),"GET /api/admin/projects":()=>Me("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ie("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ie("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ie("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ie("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ie("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ie("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ie("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ie("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){yt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();yt(e,200,i)}catch(n){yt(e,400,{error:n.message||"admin op failed"})}}function yt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function wo(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 ko(t){let e=ke(process.cwd(),t);if(!Qe(e))return[];let a=[];for(let n of yo(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ka(ke(e,n.name),"utf-8")))}catch{}return a}function kt(){let t=ke(process.cwd(),"agentx.json");return Qe(t)?JSON.parse(Ka(t,"utf-8")):null}function _o(){let t=kt();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||{},y={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:la(w.local),ntfy:Na(t.channels?.ntfy)},g=[];try{g=ko(".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 S=(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:y,boards:S,notifications:T,screen:ya(t.screen),actions:g}}function Eo(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 So(){return new Q().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 To(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 Q().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Co(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Q().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ao(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=Y();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 Mo(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=en(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=ke(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=ke(i,"CLAUDE.md");if(!Qe(d))try{vo(i,{recursive:!0}),Ja(d,`# ${a}
4763
+ `;function Za(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Va({peers:a,localToken:n}))}async function en(t,e){let a=_t();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function tn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await zo(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Ao(t),r={"GET /api/admin/state":()=>Io(),"POST /api/admin/agents":()=>Oo(n),"PATCH /api/admin/agents":()=>No(n),"DELETE /api/admin/agents":()=>Do(n),"POST /api/admin/agents/access":()=>$o(n),"POST /api/admin/channels/telegram":()=>Ho(n),"DELETE /api/admin/channels/telegram":()=>ds(n),"POST /api/admin/channels/telegram/toggle":()=>cs(n),"POST /api/admin/crons":()=>ps(n),"DELETE /api/admin/crons":()=>us(n),"POST /api/admin/config/raw":()=>ms(n),"GET /api/admin/tokens":()=>Lo(),"POST /api/admin/tokens":()=>jo(n),"DELETE /api/admin/tokens":()=>Ro(n),"POST /api/admin/agents/test":()=>Po(n),"POST /api/admin/agents/integrations":()=>Xo(n),"DELETE /api/admin/agents/integrations":()=>Ko(n),"PATCH /api/admin/agents/integrations":()=>Jo(n),"PATCH /api/admin/channels/telegram":()=>Bo(n),"POST /api/admin/channels/slack":()=>as(n),"POST /api/admin/channels/slack/toggle":()=>ns(n),"POST /api/admin/channels/discord":()=>rs(n),"POST /api/admin/channels/discord/toggle":()=>os(n),"POST /api/admin/channels/gitlab":()=>ss(n),"POST /api/admin/channels/gitlab/toggle":()=>is(n),"GET /api/admin/channels/whatsapp/state":()=>$e("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>$e("/webrtc/history"),"POST /api/admin/actions":()=>Ts(n),"DELETE /api/admin/actions":()=>Cs(n),"POST /api/admin/actions/run":()=>As(n),"GET /api/admin/channels/whatsapp/chats":()=>$e("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>$e("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ie("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ls(n),"POST /api/admin/webhooks":()=>Vo(n),"PATCH /api/admin/webhooks":()=>Yo(n),"DELETE /api/admin/webhooks":()=>ts(n),"POST /api/admin/mesh/peers":()=>Qo(n),"DELETE /api/admin/mesh/peers":()=>Zo(n),"POST /api/admin/mesh/toggle":()=>es(n),"GET /api/admin/files":()=>qo(t),"GET /api/admin/files/read":()=>Uo(t),"PUT /api/admin/files":()=>Fo(n),"POST /api/admin/files/skill":()=>Wo(n),"DELETE /api/admin/files/skill":()=>Go(n),"POST /api/admin/business/orgchart":()=>fs(n),"DELETE /api/admin/business/orgchart":()=>hs(n),"POST /api/admin/business/project":()=>gs(n),"DELETE /api/admin/business/project":()=>bs(n),"POST /api/admin/business/client":()=>xs(n),"DELETE /api/admin/business/client":()=>vs(n),"POST /api/admin/business/contact":()=>ys(n),"DELETE /api/admin/business/contact":()=>ws(n),"POST /api/admin/boards":()=>ks(n),"DELETE /api/admin/boards":()=>_s(n),"POST /api/admin/boards/columns":()=>Es(n),"DELETE /api/admin/boards/columns":()=>Ss(n),"POST /api/admin/notifications":()=>Is(n),"POST /api/admin/screen":()=>$s(n),"POST /api/admin/webhooks/triggers":()=>Ls(n),"POST /api/admin/mesh/health":()=>Ms(n),"GET /api/admin/projects":()=>$e("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ie("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ie("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ie("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ie("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ie("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ie("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ie("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ie("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){wt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();wt(e,200,i)}catch(n){wt(e,400,{error:n.message||"admin op failed"})}}function wt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ao(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 Mo(t){let e=_e(process.cwd(),t);if(!Qe(e))return[];let a=[];for(let n of Co(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Ya(_e(e,n.name),"utf-8")))}catch{}return a}function _t(){let t=_e(process.cwd(),"agentx.json");return Qe(t)?JSON.parse(Ya(t,"utf-8")):null}function Io(){let t=_t();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||{},y={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:ca(w.local),ntfy:Ha(t.channels?.ntfy)},g=[];try{g=Mo(".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 S=(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:y,boards:S,notifications:T,screen:ka(t.screen),actions:g}}function $o(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 Lo(){return new Q().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 jo(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 Q().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Ro(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Q().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Po(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=Y();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 Oo(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=nn(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=_e(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=_e(i,"CLAUDE.md");if(!Qe(d))try{So(i,{recursive:!0}),Qa(d,`# ${a}
4764
4764
 
4765
4765
  ${s||"You are "+a+"."}
4766
- `)}catch{}return{summary:l}}function Io(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=en(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 $o(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 Lo(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 jo(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 Me(t){let{url:e,headers:a}=_t(),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 ie(t,e){let{url:a,headers:n}=_t(),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 Ro(t,e){try{let{url:a,headers:n}=_t(),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 _t(){let t="http://127.0.0.1:18800",e={};try{let a=Y();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ie(t){let a=kt()?.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 wt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Po(t){let e=wt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ye(Ie(e));return{agentId:e,...a}}function No(t){let e=wt(t,"agent").trim(),a=wt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return ze(Ie(e),a)}function Oo(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=qe(Ie(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Do(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=Ue(Ie(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Ho(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=Fe(Ie(e),a);return{summary:`removed skill "${a}"`,...n}}function Bo(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 zo(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 qo(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 Za=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Uo(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(!Za.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 Fo(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"&&Za.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 Wo(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 Go(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 Xo(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 Ko(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 Jo(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 Vo(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 Yo(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 Qo(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 Zo(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 es(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 ts(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-ATA7Z44S.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 as(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 ns(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 rs(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 os(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 ss(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=ke(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Qe(n))try{bo(n,r)}catch{}Ja(n,JSON.stringify(a,null,2)+`
4767
- `,"utf-8");try{let s=Y().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 en(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function is(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 ls(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 ds(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 cs(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 ps(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 us(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 ms(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 fs(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 hs(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 gs(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 xs(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 vs(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 bs(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 ys(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 ws(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 ks(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 _s(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=da(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=Oa(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 Es(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=wa(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ss(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}}pt();import{resolve as As}from"path";function tn(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 No(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=nn(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 Do(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 Ho(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 Bo(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 $e(t){let{url:e,headers:a}=Et(),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 ie(t,e){let{url:a,headers:n}=Et(),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 zo(t,e){try{let{url:a,headers:n}=Et(),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 Et(){let t="http://127.0.0.1:18800",e={};try{let a=Y();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Le(t){let a=_t()?.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 kt(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function qo(t){let e=kt(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=we(Le(e));return{agentId:e,...a}}function Uo(t){let e=kt(t,"agent").trim(),a=kt(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return ze(Le(e),a)}function Fo(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=qe(Le(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Wo(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=Ue(Le(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Go(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=Fe(Le(e),a);return{summary:`removed skill "${a}"`,...n}}function Xo(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 Ko(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 Jo(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 an=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Vo(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(!an.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 Yo(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"&&an.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 Qo(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 Zo(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 es(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 ts(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 ns(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 rs(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 os(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 ss(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 is(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 ls(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-RAYGNDWT.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 ds(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 cs(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 ps(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 us(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 ms(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=_e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Qe(n))try{To(n,r)}catch{}Qa(n,JSON.stringify(a,null,2)+`
4767
+ `,"utf-8");try{let s=Y().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 nn(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function fs(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 hs(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 gs(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 xs(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 vs(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 bs(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 ys(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 ws(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 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 _s(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 Es(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 Ss(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 Ts(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 Cs(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 As(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 Ms(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 Is(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=pa(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=Ba(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 $s(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=C(a=>(a.screen=_a(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Ls(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}}ut();import{resolve as Ps}from"path";function rn(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:Ts,scripts:`${e}<script>${Cs}</script>`})}var Ts=`
4822
+ </section>`;return $({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:js,scripts:`${e}<script>${Rs}</script>`})}var js=`
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; }`,Cs=`
4926
+ details[open] summary { margin-bottom: 8px; }`,Rs=`
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 nn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(tn({peers:a,localToken:n}))}async function rn(t,e,a){try{let n=t.method==="GET"?void 0:await Os(t),r=Ms(),o={"GET /api/admin/graph/state":()=>Is(r),"POST /api/admin/graph/classifications/approve":()=>$s(r,n),"POST /api/admin/graph/classifications/reject":()=>Ls(r,n),"POST /api/admin/graph/nodes":()=>js(r,n),"PATCH /api/admin/graph/nodes":()=>Rs(r,n),"DELETE /api/admin/graph/nodes":()=>Ps(r,n),"PUT /api/admin/graph/schema":()=>Ns(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Et(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Et(e,200,l)}catch(n){Et(e,400,{error:n?.message||"graph op failed"})}}function Ms(){let t=Y(),e=As(process.cwd(),t.graph.baseDir);return new Yt({baseDir:e})}function Is(t){let e=Y(),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 $s(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=on(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=St(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Ls(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=on(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function on(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 js(t,e){let a=an(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?an(String(e.parentId)):null,o=St({[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 Rs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=St({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ps(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Ns(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 St(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 an(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Et(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Os(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 sn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5146
+ `;function sn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rn({peers:a,localToken:n}))}async function ln(t,e,a){try{let n=t.method==="GET"?void 0:await Fs(t),r=Os(),o={"GET /api/admin/graph/state":()=>Ns(r),"POST /api/admin/graph/classifications/approve":()=>Ds(r,n),"POST /api/admin/graph/classifications/reject":()=>Hs(r,n),"POST /api/admin/graph/nodes":()=>Bs(r,n),"PATCH /api/admin/graph/nodes":()=>zs(r,n),"DELETE /api/admin/graph/nodes":()=>qs(r,n),"PUT /api/admin/graph/schema":()=>Us(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){St(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();St(e,200,l)}catch(n){St(e,400,{error:n?.message||"graph op failed"})}}function Os(){let t=Y(),e=Ps(process.cwd(),t.graph.baseDir);return new Zt({baseDir:e})}function Ns(t){let e=Y(),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 Ds(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=dn(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=Tt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Hs(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=dn(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function dn(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 Bs(t,e){let a=on(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?on(String(e.parentId)):null,o=Tt({[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 zs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Tt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function qs(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Us(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 Tt(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 on(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function St(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Fs(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 cn(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:Ds,scripts:`${e}<script>${Hs}</script>`})}var Ds=`
5179
+ </div>`;return $({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ws,scripts:`${e}<script>${Gs}</script>`})}var Ws=`
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
- `,Hs=`
5228
+ `,Gs=`
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 Bs=["yes","no","later"];function le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function ln(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 dn(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(sn({peers:e,localToken:a}))}async function cn(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 le(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=He(s,{includeSnoozed:n.searchParams.get("all")==="1"});return le(e,200,{...i,settings:we(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await ln(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!Bs.includes(d))return le(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=we(s.configPath),u=await Be(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?(le(e,200,{ok:!0,message:u.message}),!0):(le(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await ln(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=ja(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Ra(l,{configPath:s.configPath,reload:s.reload});return p.success?(le(e,200,{ok:!0,settings:we(s.configPath)}),!0):(le(e,400,{error:p.error}),!0)}}catch(i){return le(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return le(e,404,{error:"Not found"}),!0}import{resolve as Us}from"path";import{existsSync as Fs}from"fs";import Ws from"better-sqlite3";function pn(t={}){let e=`<div class="ax-obs">
5379
+ `;var Xs=["yes","no","later"];function le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function pn(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 un(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(cn({peers:e,localToken:a}))}async function mn(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 le(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=He(s,{includeSnoozed:n.searchParams.get("all")==="1"});return le(e,200,{...i,settings:ke(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await pn(t),l=typeof i.key=="string"?i.key:"",d=i.action;if(!l||!Xs.includes(d))return le(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=ke(s.configPath),u=await Be(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?(le(e,200,{ok:!0,message:u.message}),!0):(le(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await pn(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=Oa(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await Na(l,{configPath:s.configPath,reload:s.reload});return p.success?(le(e,200,{ok:!0,settings:ke(s.configPath)}),!0):(le(e,400,{error:p.error}),!0)}}catch(i){return le(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return le(e,404,{error:"Not found"}),!0}import{resolve as Vs}from"path";import{existsSync as Ys}from"fs";import Qs from"better-sqlite3";function fn(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:zs,scripts:`<script>${qs}</script>`})}var zs=`
5501
+ </div>`;return $({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ks,scripts:`<script>${Js}</script>`})}var Ks=`
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
- `,qs=`
5618
+ `,Js=`
5619
5619
  (function(){
5620
5620
  var panes = document.querySelectorAll('.ax-obs__pane');
5621
5621
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -5999,7 +5999,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5999
5999
 
6000
6000
  load(current);
6001
6001
  })();
6002
- `;var fn={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 hn(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Tt(t){let e=fn[hn(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 Gs(){let t=Us(process.cwd(),".agentx/db.sqlite");if(!Fs(t))return null;try{let e=new Ws(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function gn(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pn({peers:a}))}function Xs(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 de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function xn(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Gs();if(!r)return de(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Xs(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
6002
+ `;var xn={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 vn(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ct(t){let e=xn[vn(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 Zs(){let t=Vs(process.cwd(),".agentx/db.sqlite");if(!Ys(t))return null;try{let e=new Qs(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function bn(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fn({peers:a}))}function ei(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 de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function yn(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Zs();if(!r)return de(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ei(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
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 "):""}
@@ -6014,8 +6014,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
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:vn(f.error)}));return de(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return de(e,200,Ks(r.db)),!0;if(n==="activity")return de(e,200,Js(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=un(i.searchParams.get("range"));return de(e,200,mn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=un(i.searchParams.get("range")),d=mn(r.db,l),p=Vs(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 de(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return de(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function vn(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 Ks(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),y=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Tt(M),0),g=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Tt(M),0),S=t.prepare(`
6017
+ `,u=r.db.prepare(d).all(l).map(f=>({...f,plain:wn(f.error)}));return de(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return de(e,200,ti(r.db)),!0;if(n==="activity")return de(e,200,ai(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=hn(i.searchParams.get("range"));return de(e,200,gn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=hn(i.searchParams.get("range")),d=gn(r.db,l),p=ni(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 de(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return de(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function wn(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 ti(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),y=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Ct(M),0),g=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Ct(M),0),S=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,
@@ -6038,7 +6038,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
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:vn(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:y,spendToday:T,spendDelta:T-g,idleAgentCount:x.length},perAgent:S,perChannel:c,idleAgents:x,recentErrors:v}}function Js(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:wn(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:y,spendToday:T,spendDelta:T-g,idleAgentCount:x.length},perAgent:S,perChannel:c,idleAgents:x,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 un(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 mn(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 hn(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 gn(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,10 +6073,10 @@ 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,y=0,w=0,T=0,g=0,S={},c={};for(let E of n){let I=Tt(E),j=hn(E.model),R=fn[j],B=(E.tier2_input_tokens||0)/1e6*R.input*.5+(E.tier2_output_tokens||0)/1e6*R.output*.5+(E.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,te=(E.input_tokens||0)+(E.tier2_input_tokens||0),z=(E.output_tokens||0)+(E.tier2_output_tokens||0),D=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),H=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=I,E.day>=s&&(p+=I,w+=E.tasks||0),E.day>=i&&E.day<s&&(g+=I,T+=E.tasks||0),E.day===r&&(l+=I),E.day===o&&(d+=I),E.day===r&&(f+=B),E.day>=s&&(y+=B);let J=S[E.day]||(S[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});J.tasks+=E.tasks||0,J.input+=te,J.output+=z,J.cacheRead+=D,J.cacheCreate+=H,J.cost+=I,J.tier2+=B;let q=J.agents[E.agent_id]||(J.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});q.tasks+=E.tasks||0,q.cost+=I,q.tier2+=B,q.input+=te,q.output+=z,q.cacheRead+=D,q.cacheCreate+=H,E.model&&(q.model=E.model);let V=c[E.agent_id]||(c[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});V.tasks+=E.tasks||0,V.cost+=I,V.tier2+=B,V.input+=te,V.output+=z,V.cacheRead+=D,V.cacheCreate+=H,E.model&&(V.model=E.model)}let m=Object.values(S).sort((E,I)=>E.date<I.date?-1:1),h=0,x=0,k=0,v=0,_=0,M=0;for(let E of m)h+=E.tasks,x+=E.input,k+=E.output,v+=E.cacheRead,_+=E.cacheCreate,M+=E.cost;let A=Object.entries(c).map(([E,I])=>({agent_id:E,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((E,I)=>I.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:y,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 Vs(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,d=0,p=0,u=0,f=0,y=0,w=0,T=0,g=0,S={},c={};for(let E of n){let I=Ct(E),j=vn(E.model),R=xn[j],B=(E.tier2_input_tokens||0)/1e6*R.input*.5+(E.tier2_output_tokens||0)/1e6*R.output*.5+(E.tier2_cache_read_tokens||0)/1e6*R.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*R.cacheCreate*.5,te=(E.input_tokens||0)+(E.tier2_input_tokens||0),z=(E.output_tokens||0)+(E.tier2_output_tokens||0),D=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),H=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=I,E.day>=s&&(p+=I,w+=E.tasks||0),E.day>=i&&E.day<s&&(g+=I,T+=E.tasks||0),E.day===r&&(l+=I),E.day===o&&(d+=I),E.day===r&&(f+=B),E.day>=s&&(y+=B);let J=S[E.day]||(S[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});J.tasks+=E.tasks||0,J.input+=te,J.output+=z,J.cacheRead+=D,J.cacheCreate+=H,J.cost+=I,J.tier2+=B;let q=J.agents[E.agent_id]||(J.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});q.tasks+=E.tasks||0,q.cost+=I,q.tier2+=B,q.input+=te,q.output+=z,q.cacheRead+=D,q.cacheCreate+=H,E.model&&(q.model=E.model);let V=c[E.agent_id]||(c[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});V.tasks+=E.tasks||0,V.cost+=I,V.tier2+=B,V.input+=te,V.output+=z,V.cacheRead+=D,V.cacheCreate+=H,E.model&&(V.model=E.model)}let m=Object.values(S).sort((E,I)=>E.date<I.date?-1:1),h=0,x=0,k=0,v=0,_=0,M=0;for(let E of m)h+=E.tasks,x+=E.input,k+=E.output,v+=E.cacheRead,_+=E.cacheCreate,M+=E.cost;let A=Object.entries(c).map(([E,I])=>({agent_id:E,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((E,I)=>I.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:y,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 ni(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 Ys}from"path";import{existsSync as Qs}from"fs";import Zs from"better-sqlite3";function ei(){let t=Ys(process.cwd(),".agentx/intent/ledger.sqlite");if(!Qs(t))return null;try{let e=new Zs(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-bn>6e4&&(bn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var bn=0;function ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ti(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 yn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ei();if(!r)return ve(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ti(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":"",y=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,S=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 ri}from"path";import{existsSync as oi}from"fs";import si from"better-sqlite3";function ii(){let t=ri(process.cwd(),".agentx/intent/ledger.sqlite");if(!oi(t))return null;try{let e=new si(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-kn>6e4&&(kn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var kn=0;function ve(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function li(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 _n(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ii();if(!r)return ve(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=li(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":"",y=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,S=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(`
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
@@ -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 ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}return ve(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function wn(t={}){return $({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6106
+ `;return ve(e,200,{rows:r.db.prepare(y).all(f)}),!0}return ve(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ve(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function En(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 kn(t={}){return $({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6311
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Sn(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 _n(t={}){let e=`<div class="ax-pj__root">
6884
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Tn(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:ai,scripts:`<script>${ni}</script>`})}var ai=`
6911
+ </div>`;return $({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:di,scripts:`<script>${ci}</script>`})}var di=`
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
- `,ni=`
7098
+ `,ci=`
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 Mt,join as xi}from"path";import{existsSync as It,readdirSync as vi,readFileSync as bi}from"fs";import yi from"better-sqlite3";var Sn=String.raw`[\w.-]+(?:/[\w.-]+)+`,ri=new RegExp(`^(?:chat:)?(${Sn}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),oi=new RegExp(`^\\[(?:GitLab|GitHub) (${Sn}) `);function En(t){if(!t)return null;let e=t.match(ri);return e?e[1]:null}function Ct(t){if(!t)return null;let e=t.trimStart().match(oi);return e?e[1]:null}function Ze(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():En(typeof n?.chatId=="string"?n.chatId:null)??En(e)??Ct(a)}function si(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function et(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var ii=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,li=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,di=t=>/^issue/i.test(t)?"issue":"mr";function ci(t){let e=t.subject.match(ii)??t.inputPreview.trimStart().match(li);return e?{kind:di(e[1]),n:Number(e[2])}:null}function pi(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 Tn(t){if(!si(t.projectId))return[];let e=ci(t);return e?[e]:pi(t.inputPreview)}var ui=6e4,mi=5*6e4,fi=40,Cn=6,An=new Map;function Mn(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 Tn(n)){let s=et(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=fi)return[...e.values()]}}return[...e.values()]}async function In(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=et(s.project,s.ref),l=An.get(i);l&&n-l.at<(s.github?mi:ui)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Cn)await Promise.all(o.slice(s,s+Cn).map(async i=>{let l=et(i.project,i.ref),d=null;try{d=i.github?await gi(i,e,a):await hi(i,e,a)}catch{}An.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function $n(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 hi(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 $n(`${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 gi(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 $n(`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 $t(){let t=Mt(process.cwd(),".agentx/intent/ledger.sqlite");if(!It(t))return null;try{let e=new yi(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ln>6e4&&(Ln=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Ln=0;function ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var _e={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},opencode:{label:"OpenCode",color:"#57606a"}};function wi(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in _e)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in _e)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in _e)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in _e)return s}return"workflow"}return t}function Pn(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 ki(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 Nn(t,e,a){return oa(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 _i(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&&!At(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!At(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&&!At(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=jn(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:jn(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 jn(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function At(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 On(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 It,join as Ei}from"path";import{existsSync as $t,readdirSync as Si,readFileSync as Ti}from"fs";import Ci from"better-sqlite3";var An=String.raw`[\w.-]+(?:/[\w.-]+)+`,pi=new RegExp(`^(?:chat:)?(${An}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),ui=new RegExp(`^\\[(?:GitLab|GitHub) (${An}) `);function Cn(t){if(!t)return null;let e=t.match(pi);return e?e[1]:null}function At(t){if(!t)return null;let e=t.trimStart().match(ui);return e?e[1]:null}function Ze(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Cn(typeof n?.chatId=="string"?n.chatId:null)??Cn(e)??At(a)}function mi(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function et(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var fi=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,hi=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,gi=t=>/^issue/i.test(t)?"issue":"mr";function xi(t){let e=t.subject.match(fi)??t.inputPreview.trimStart().match(hi);return e?{kind:gi(e[1]),n:Number(e[2])}:null}function vi(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 Mn(t){if(!mi(t.projectId))return[];let e=xi(t);return e?[e]:vi(t.inputPreview)}var bi=6e4,yi=5*6e4,wi=40,In=6,$n=new Map;function Ln(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 Mn(n)){let s=et(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=wi)return[...e.values()]}}return[...e.values()]}async function jn(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=et(s.project,s.ref),l=$n.get(i);l&&n-l.at<(s.github?yi:bi)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=In)await Promise.all(o.slice(s,s+In).map(async i=>{let l=et(i.project,i.ref),d=null;try{d=i.github?await _i(i,e,a):await ki(i,e,a)}catch{}$n.set(l,{at:n,item:d}),d&&(r[l]=d)}));return r}async function Rn(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 Rn(`${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 _i(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 Rn(`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 Lt(){let t=It(process.cwd(),".agentx/intent/ledger.sqlite");if(!$t(t))return null;try{let e=new Ci(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Pn>6e4&&(Pn=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Pn=0;function ce(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 Ai(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 Dn(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 Mi(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 Hn(t,e,a){return ia(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 Ii(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&&!Mt(l))return{id:l,name:l,avatar:F(l),kind:"a2a"}}let i=o||r||s;if(i&&!Mt(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&&!Mt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=On(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:On(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 On(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Mt(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 Bn(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 Ei(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 Dn(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 $i(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,j)=>`@id${j}`).join(","),M=Object.fromEntries(v.map((I,j)=>[`id${j}`,I])),A=t.prepare(`
@@ -7756,9 +7756,9 @@ ${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 E=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 E)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=[],y=e?.business?.projects??[],w=e?.business?.contactMap??[],T=ht(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Nn(v.source,_,w),A=On(v.source,_),E=v.project??Ze(_,v.subject,A),I=null,j=null;M?(I=M.client,j=M.project||`${M.client}/_chat`):E&&(I=De(E,y),j=E);let R=wi(v.source,v.intent||"",_),B=_e[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:B.label,color:B.color});let te="__system",z,D=_i(v.source,v.intent||"",_);if(D){te=D.id,z=D.kind;let H=M?.displayName||D.name;(!u.has(D.id)||M?.displayName)&&u.set(D.id,{id:D.id,name:H,avatar:F(H),kind:D.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 J=`${v.id}|${H.decided_by}`,q=i.get(J),V=H.decided_at,Kt=q?.resolved_at??null,dt=Kt===null,Yr=q?.duration_ms??(dt?n-V:0),Qr=dt?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",G,Ae;if(I)G=I,Ae=j;else{let ct=T.get(H.agent_id);ct?(G=ct,Ae=`${ct}/_${v.source}`):(G="unmapped",Ae=`unmapped/_${v.source}`)}l.has(G)||l.set(G,{id:G,name:G,color:Pn(G),projects:[]}),d.has(G)||d.set(G,new Set),d.get(G).add(Ae),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:G,projectId:Ae,channelId:R,initiatorId:te,initiatorKind:z,subject:Ei(v.subject),intent:v.intent||"",startedAt:V,resolvedAt:Kt,duration:Yr,active:dt,outcome:Qr,tokens:0,inputPreview:A,system:ki(H.agent_id,e)})}}let g=[...l.values()].map(v=>({...v,projects:[...d.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),S=[],c=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,E=A?v.roles?.[A]?.title:void 0;return typeof E=="string"&&E.trim()?E.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let E={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)};S.push(E),c.add(M)}}for(let v of f)c.has(v.agentId)||(S.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),c.add(v.agentId));S.sort((v,_)=>v.id.localeCompare(_.id));let m=[],h=new Set;for(let[v,_]of Object.entries(_e))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:S,channels:m,initiators:x,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function Lt(t){let e=$t();if(!e)return null;try{return Dn(e.db,me,t)}finally{e.close()}}function Hn(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 y=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:y})}}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=Si(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Pn(f.clientId),projects:[]}),f.projectId!==u.projectId){let y=e.get(f.clientId);y.projects.includes(f.projectId)||e.set(f.clientId,{...y,projects:[...y.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 Si(t){if(t.clientId!=="unmapped")return t;let e=Ct(t.inputPreview);if(!e)return t;let a=me?.business?.projects??[];return{...t,projectId:e,clientId:De(e,a)}}async function tt(t){let e=me?.channels?.gitlab,a=await In(Mn(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 me=null;function Bn(t){me=t}async function zn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=$t();if(!n)return ce(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=qn(parseInt(r.searchParams.get("hours")||"6",10));ce(e,200,await tt(Dn(n.db,me,o)))}catch(r){ce(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Ti=5e3;async function jt(t,e,a,n=Lt){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 E)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=[],y=e?.business?.projects??[],w=e?.business?.contactMap??[],T=gt(e?.business??{});for(let v of o){let _=null;try{_=JSON.parse(v.raw_json)}catch{}let M=Hn(v.source,_,w),A=Bn(v.source,_),E=v.project??Ze(_,v.subject,A),I=null,j=null;M?(I=M.client,j=M.project||`${M.client}/_chat`):E&&(I=De(E,y),j=E);let R=Ai(v.source,v.intent||"",_),B=Ee[R]||{label:R,color:"#6b7280"};p.has(R)||p.set(R,{id:R,label:B.label,color:B.color});let te="__system",z,D=Ii(v.source,v.intent||"",_);if(D){te=D.id,z=D.kind;let H=M?.displayName||D.name;(!u.has(D.id)||M?.displayName)&&u.set(D.id,{id:D.id,name:H,avatar:F(H),kind:D.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 J=`${v.id}|${H.decided_by}`,q=i.get(J),V=H.decided_at,Vt=q?.resolved_at??null,ct=Vt===null,ro=q?.duration_ms??(ct?n-V:0),oo=ct?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",G,Ie;if(I)G=I,Ie=j;else{let pt=T.get(H.agent_id);pt?(G=pt,Ie=`${pt}/_${v.source}`):(G="unmapped",Ie=`unmapped/_${v.source}`)}l.has(G)||l.set(G,{id:G,name:G,color:Dn(G),projects:[]}),d.has(G)||d.set(G,new Set),d.get(G).add(Ie),f.push({id:`${v.id}|${H.decided_by}`,agentId:H.agent_id,clientId:G,projectId:Ie,channelId:R,initiatorId:te,initiatorKind:z,subject:$i(v.subject),intent:v.intent||"",startedAt:V,resolvedAt:Vt,duration:ro,active:ct,outcome:oo,tokens:0,inputPreview:A,system:Mi(H.agent_id,e)})}}let g=[...l.values()].map(v=>({...v,projects:[...d.get(v.id)||[]].sort()})).sort((v,_)=>v.id.localeCompare(_.id)),S=[],c=new Set;if(e){let v=e.business??{},_=M=>{let A=v.orgChart?.[M]?.role,E=A?v.roles?.[A]?.title:void 0;return typeof E=="string"&&E.trim()?E.trim():void 0};for(let[M,A]of Object.entries(e.agents||{})){let E={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)};S.push(E),c.add(M)}}for(let v of f)c.has(v.agentId)||(S.push({id:v.agentId,name:v.agentId,tier:"worker",model:"",role:""}),c.add(v.agentId));S.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:S,channels:m,initiators:x,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function jt(t){let e=Lt();if(!e)return null;try{return zn(e.db,me,t)}finally{e.close()}}function qn(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 y=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:y})}}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=Li(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:Dn(f.clientId),projects:[]}),f.projectId!==u.projectId){let y=e.get(f.clientId);y.projects.includes(f.projectId)||e.set(f.clientId,{...y,projects:[...y.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 Li(t){if(t.clientId!=="unmapped")return t;let e=At(t.inputPreview);if(!e)return t;let a=me?.business?.projects??[];return{...t,projectId:e,clientId:De(e,a)}}async function tt(t){let e=me?.channels?.gitlab,a=await jn(Ln(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 me=null;function Un(t){me=t}async function Fn(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Lt();if(!n)return ce(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Wn(parseInt(r.searchParams.get("hours")||"6",10));ce(e,200,await tt(zn(n.db,me,o)))}catch(r){ce(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var ji=5e3;async function Rt(t,e,a,n=jt){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=qn(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=Wn(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
7763
  `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await tt(p);if(s)break;u?(e.write(`event: snapshot
7764
7764
  `),e.write(`data: ${JSON.stringify(u)}
@@ -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<Ti;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function qn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ci(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Mt(process.cwd(),".agentx/task-history",t,n);if(!It(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Mt(process.cwd(),".agentx/task-history",t,o);return It(s)?Rn(s,e,a):null}return Rn(r,e,a)}function Rn(t,e,a){let n=null,r=1/0;for(let o of vi(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(bi(xi(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 Un(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 ce(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=$t();if(!l)return ce(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 ce(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 ce(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 y=On(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)||y,T=null,g=null;if(p.agent_id){let k=Ci(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 S=me?.business?.projects??[],c=me?.business?.contactMap??[],m=ht(me?.business??{}),h={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=Nn(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||Ze(f,d.subject,y)){let k=d.project||Ze(f,d.subject,y);h={client:De(k,S),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})`})}ce(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){ce(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as $i,readFileSync as Li}from"fs";import{resolve as Wn}from"path";pt();function Fn(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=Ai.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:Mi,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>${Ii}</script>`})}var Ai=`
7772
+ `)}let d=Date.now();for(;!s&&Date.now()-d<ji;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Wn(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ri(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=It(process.cwd(),".agentx/task-history",t,n);if(!$t(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=It(process.cwd(),".agentx/task-history",t,o);return $t(s)?Nn(s,e,a):null}return Nn(r,e,a)}function Nn(t,e,a){let n=null,r=1/0;for(let o of Si(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Ti(Ei(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 Gn(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 ce(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Lt();if(!l)return ce(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 ce(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 ce(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 y=Bn(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)||y,T=null,g=null;if(p.agent_id){let k=Ri(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 S=me?.business?.projects??[],c=me?.business?.contactMap??[],m=gt(me?.business??{}),h={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=Hn(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||Ze(f,d.subject,y)){let k=d.project||Ze(f,d.subject,y);h={client:De(k,S),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})`})}ce(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){ce(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Di,readFileSync as Hi}from"fs";import{resolve as Kn}from"path";ut();function Xn(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=Pi.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:Oi,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>${Ni}</script>`})}var Pi=`
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
- `,Mi=`
8361
+ `,Oi=`
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
- `,Ii=`
8480
+ `,Ni=`
8481
8481
  const $ = (id) => document.getElementById(id);
8482
8482
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
8483
8483
 
@@ -9323,6 +9323,8 @@ function closeTestDrive() {
9323
9323
  p.setAttribute('aria-hidden', 'true');
9324
9324
  }
9325
9325
  $('btn-test-drive')?.addEventListener('click', openTestDrive);
9326
+ // /admin/agents/<id>#chat: AgentX Voice's "Open in chat" lands in the chat.
9327
+ if (location.hash === '#chat') openTestDrive();
9326
9328
  $('td-close')?.addEventListener('click', closeTestDrive);
9327
9329
  document.addEventListener('keydown', (e) => {
9328
9330
  if (e.key === 'Escape' && $('td-panel')?.classList.contains('is-open')) closeTestDrive();
@@ -9331,15 +9333,15 @@ document.addEventListener('keydown', (e) => {
9331
9333
  /* ===== Boot ===== */
9332
9334
  initOptsToggles();
9333
9335
  loadAgent();
9334
- `;function Gn(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fn({agentId:a,peers:n,localToken:r}))}async function Xn(t,e,a){try{let n=t.method==="GET"?void 0:await el(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){at(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>$e(i),"PATCH ":()=>ji(i,n),"PATCH capability":()=>Ni(i,n),"POST mcp":()=>Ri(i,n),"DELETE mcp":()=>Pi(i,n),"GET identity":()=>Oi(i),"GET identity/file":()=>Di(i,String(o.path||"")),"PUT identity/file":()=>Hi(i,n),"GET skills":()=>Bi(i),"POST skills":()=>zi(i,n),"DELETE skills":()=>qi(i,n),"GET skills/tree":()=>Ui(i,String(o.slug||"")),"GET skills/file":()=>Fi(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Wi(i,n),"GET skills/deps":()=>Gi(i,String(o.slug||"")),"POST skills/install":()=>Xi(i,n,t),"POST skills/deps":()=>Ki(i,n,t),"GET channels":()=>Ji(i),"GET activity":()=>Vi(i,t),"GET handovers":()=>Yi(i),"POST handovers":()=>Qi(i,n),"DELETE handovers":()=>Zi(n)}[d];if(!u){at(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();at(e,200,f)}catch(n){at(e,400,{error:n?.message||"agent op failed"})}}function Kn(){let t=Wn(process.cwd(),"agentx.json");return $i(t)?JSON.parse(Li(t,"utf-8")):null}function W(t){let e=Kn();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 $e(t){let{def:e,cfg:a}=W(t),n=e.workspace?ye(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 ji(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:$e(t)}}function Ri(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:$e(t)}}function Pi(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:$e(t)}}function Ni(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:$e(t)}}function Oi(t){let{def:e}=W(t);return ye(e.workspace)}function Di(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return ze(a.workspace,e)}function Hi(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return qe(n.workspace,a,String(e?.content??""))}function Bi(t){let{def:e}=W(t),a=ye(e.workspace);return{skills:a.skills,workspace:a.workspace}}function zi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ue(n.workspace,a,{title:e?.title,content:e?.content})}function qi(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Fe(n.workspace,a)}function Ui(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=xa(a.workspace,e),r=We(a.workspace,e);return{slug:e,tree:n,deps:r}}function Fi(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return va(n.workspace,e,a)}function Wi(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 ba(r.workspace,a,n,String(e?.content??""))}function Gi(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return We(a.workspace,e)}async function Xi(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=Jn(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(`
9335
- `);return Vn(a,r,s,`install-${n}:${Date.now()}`)}async function Ki(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Jn(e?.worker),{def:o}=W(t),s=We(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=Wn(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(`
9336
- `);return Vn(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Jn(t){if(t&&typeof t=="string")return t;let e=Y();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Vn(t,e,a,n){let r=Y(),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 Ji(t){let e=Kn(),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 Vi(t,e){try{let n=(Y().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 Rt(){return new Qt}function Yi(t){let e=Rt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Qi(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=Rt().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 Zi(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:Rt().remove(e,a,n)?"Released":"No active handover for that chat"}}function at(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function el(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 be={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 Yn=[{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 Pt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(be)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9336
+ `;function Jn(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xn({agentId:a,peers:n,localToken:r}))}async function Vn(t,e,a){try{let n=t.method==="GET"?void 0:await il(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){at(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>je(i),"PATCH ":()=>Bi(i,n),"PATCH capability":()=>Ui(i,n),"POST mcp":()=>zi(i,n),"DELETE mcp":()=>qi(i,n),"GET identity":()=>Fi(i),"GET identity/file":()=>Wi(i,String(o.path||"")),"PUT identity/file":()=>Gi(i,n),"GET skills":()=>Xi(i),"POST skills":()=>Ki(i,n),"DELETE skills":()=>Ji(i,n),"GET skills/tree":()=>Vi(i,String(o.slug||"")),"GET skills/file":()=>Yi(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Qi(i,n),"GET skills/deps":()=>Zi(i,String(o.slug||"")),"POST skills/install":()=>el(i,n,t),"POST skills/deps":()=>tl(i,n,t),"GET channels":()=>al(i),"GET activity":()=>nl(i,t),"GET handovers":()=>rl(i),"POST handovers":()=>ol(i,n),"DELETE handovers":()=>sl(n)}[d];if(!u){at(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();at(e,200,f)}catch(n){at(e,400,{error:n?.message||"agent op failed"})}}function Yn(){let t=Kn(process.cwd(),"agentx.json");return Di(t)?JSON.parse(Hi(t,"utf-8")):null}function W(t){let e=Yn();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?we(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 Bi(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 zi(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 qi(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 Ui(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 Fi(t){let{def:e}=W(t);return we(e.workspace)}function Wi(t,e){if(!e)throw new Error("path query param required");let{def:a}=W(t);return ze(a.workspace,e)}function Gi(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=W(t);return qe(n.workspace,a,String(e?.content??""))}function Xi(t){let{def:e}=W(t),a=we(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Ki(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Ue(n.workspace,a,{title:e?.title,content:e?.content})}function Ji(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=W(t);return Fe(n.workspace,a)}function Vi(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t),n=ba(a.workspace,e),r=We(a.workspace,e);return{slug:e,tree:n,deps:r}}function Yi(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=W(t);return ya(n.workspace,e,a)}function Qi(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 wa(r.workspace,a,n,String(e?.content??""))}function Zi(t,e){if(!e)throw new Error("slug query param required");let{def:a}=W(t);return We(a.workspace,e)}async function el(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=Qn(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 Zn(a,r,s,`install-${n}:${Date.now()}`)}async function tl(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Qn(e?.worker),{def:o}=W(t),s=We(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=Kn(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 Zn(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Qn(t){if(t&&typeof t=="string")return t;let e=Y();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Zn(t,e,a,n){let r=Y(),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 al(t){let e=Yn(),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 nl(t,e){try{let n=(Y().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 Pt(){return new ea}function rl(t){let e=Pt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function ol(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=Pt().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 sl(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:Pt().remove(e,a,n)?"Released":"No active handover for that chat"}}function at(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function il(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 be={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 er=[{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 Ot(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(be)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9337
9339
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
9338
9340
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
9339
9341
  <section id="statstrip" class="ax-statstrip"></section>
9340
9342
  <main id="grid" class="ax-live__body"></main>
9341
9343
  </div>
9342
- `;return $({title:`${be.brand} \xB7 ${be.subtitle}`,activeTab:"live",subtitle:be.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:tl,scripts:e+`<script>${al}</script>`,headExtras:`<script>
9344
+ `;return $({title:`${be.brand} \xB7 ${be.subtitle}`,activeTab:"live",subtitle:be.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:ll,scripts:e+`<script>${dl}</script>`,headExtras:`<script>
9343
9345
  // rightExtras for the topbar are injected at runtime \u2014 they reference
9344
9346
  // IDs (#ts, #conn-dot) that the script below addresses directly.
9345
9347
  document.addEventListener('DOMContentLoaded', () => {
@@ -9350,7 +9352,7 @@ loadAgent();
9350
9352
  extras.innerHTML = ${JSON.stringify(a)};
9351
9353
  right.insertBefore(extras, right.firstChild);
9352
9354
  });
9353
- </script>`})}var tl=`
9355
+ </script>`})}var ll=`
9354
9356
  /* --- Page frame --- */
9355
9357
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
9356
9358
 
@@ -9557,7 +9559,7 @@ loadAgent();
9557
9559
  border-top-color: var(--ax-accent); border-radius: 50%;
9558
9560
  animation: ax-spin 800ms linear infinite; display: inline-block;
9559
9561
  }
9560
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,al=`
9562
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,dl=`
9561
9563
  'use strict';
9562
9564
 
9563
9565
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -10128,7 +10130,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10128
10130
  });
10129
10131
  }
10130
10132
 
10131
- `;var Qn=`
10133
+ `;var tr=`
10132
10134
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
10133
10135
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
10134
10136
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -10302,7 +10304,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10302
10304
  .mx-summary{max-width:56vw}
10303
10305
  }
10304
10306
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
10305
- `;var Zn=`<script>
10307
+ `;var ar=`<script>
10306
10308
  window.MX=(function(){
10307
10309
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
10308
10310
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -10411,7 +10413,7 @@ window.MX=(function(){
10411
10413
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
10412
10414
  setHealth:setHealth,get:get};
10413
10415
  })();
10414
- </script>`;var er=`<script>
10416
+ </script>`;var nr=`<script>
10415
10417
  window.MXD=(function(){
10416
10418
  function el(id){return document.getElementById(id)}
10417
10419
  function tz(){return -new Date().getTimezoneOffset()}
@@ -10625,7 +10627,7 @@ window.MXD=(function(){
10625
10627
 
10626
10628
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
10627
10629
  })();
10628
- </script>`;var tr=`<script>
10630
+ </script>`;var rr=`<script>
10629
10631
  (function(){
10630
10632
  var LANES=[
10631
10633
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -10941,7 +10943,7 @@ window.MXD=(function(){
10941
10943
  window.addEventListener('scroll',hideTip,{passive:true});
10942
10944
  load();
10943
10945
  })();
10944
- </script>`;var ar=`<script>
10946
+ </script>`;var or=`<script>
10945
10947
  (function(){
10946
10948
  var showAll=document.getElementById('mx-show-all'),expanded=false;
10947
10949
  var esc=MX.esc;
@@ -11119,7 +11121,7 @@ window.MXD=(function(){
11119
11121
  }
11120
11122
  load();setInterval(load,5000);
11121
11123
  })();
11122
- </script>`;var nr=`
11124
+ </script>`;var sr=`
11123
11125
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
11124
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}
11125
11127
  .mx-rt-wrap > .mx-empty{border:0}
@@ -11160,7 +11162,7 @@ window.MXD=(function(){
11160
11162
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
11161
11163
  .mx-rt-name{max-width:100%}
11162
11164
  }
11163
- `,rr=`<script>
11165
+ `,ir=`<script>
11164
11166
  (function(){
11165
11167
  var root=document.getElementById('mx-routines');
11166
11168
  var bar=document.getElementById('mx-rt-filter');
@@ -11287,7 +11289,7 @@ window.MXD=(function(){
11287
11289
  syncBar();
11288
11290
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
11289
11291
  })();
11290
- </script>`;var or=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],sr=`<script>
11292
+ </script>`;var lr=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],dr=`<script>
11291
11293
  (function(){
11292
11294
  var root=document.getElementById('mx-feed');
11293
11295
  if(!root)return;
@@ -11362,12 +11364,12 @@ window.MXD=(function(){
11362
11364
  }
11363
11365
  load();setInterval(load,5000);
11364
11366
  })();
11365
- </script>`;var X={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 K(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var nl=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],rl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],ol=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function ir(t){let e=Ge({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Xe([{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 X={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 K(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var cl=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],pl=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],ul=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function cr(t){let e=Ge({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Xe([{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">
11366
11368
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
11367
- ${rl.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
+ ${pl.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("")}
11368
11370
  </div>
11369
11371
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
11370
- ${ol.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11372
+ ${ul.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11371
11373
  </div>
11372
11374
  </div>
11373
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">
@@ -11420,7 +11422,7 @@ window.MXD=(function(){
11420
11422
  <section class="mx-section" aria-labelledby="mx-routines-title">
11421
11423
  ${K(X.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>')}
11422
11424
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
11423
- ${nl.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11425
+ ${cl.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11424
11426
  </div>
11425
11427
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
11426
11428
  </section>
@@ -11428,7 +11430,7 @@ window.MXD=(function(){
11428
11430
  <section class="mx-section" aria-labelledby="mx-feed-title">
11429
11431
  ${K(X.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>')}
11430
11432
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
11431
- ${or.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11433
+ ${lr.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11432
11434
  </div>
11433
11435
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
11434
11436
  </section>
@@ -11461,7 +11463,7 @@ window.MXD=(function(){
11461
11463
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
11462
11464
  </header>
11463
11465
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
11464
- </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Qn+nr,scripts:Zn+sl+er+tr+rr+ar+sr})}var sl=`<script>
11466
+ </aside>`;return $({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:tr+sr,scripts:ar+ml+nr+rr+ir+or+dr})}var ml=`<script>
11465
11467
  (function(){
11466
11468
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
11467
11469
  var range=document.getElementById('mx-range');
@@ -11489,7 +11491,7 @@ window.MXD=(function(){
11489
11491
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
11490
11492
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
11491
11493
  })();
11492
- </script>`;async function lr(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 il(s,e.days)}function il(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,y=0,w=0;for(let{node:g,data:S}of t)if(S){a.runs+=S.totals.runs,a.errors+=S.totals.errors,a.hours+=S.totals.hours,a.agents+=S.totals.agents,a.threads+=S.totals.threads;for(let c of S.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 S.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 S.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 S.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=S.rotations.total,p+=S.rotations.tokenSum||0,u+=S.rotations.tokenSamples||0,f=Math.max(f,S.rotations.maxTokens),y+=S.retention.traces,w+=S.retention.tracesWithSteps;for(let c of S.jobs)i.push({...c,node:g.name,nodeUrl:g.url});for(let c of S.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,S)=>g.day.localeCompare(S.day)),origins:[...r.values()].map(g=>({...g,hours:Math.round(g.hours*100)/100})).sort((g,S)=>S.runs-g.runs),causes:[...o.values()].sort((g,S)=>S.count-g.count),jobs:i.sort((g,S)=>S.hours-g.hours),threads:l.sort((g,S)=>S.lastAt-S.firstAt-(g.lastAt-g.firstAt)||S.runs-g.runs),rotations:{total:d,byReason:[...s.entries()].map(([g,S])=>({reason:g,count:S})).sort((g,S)=>S.count-g.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:y,tracesWithSteps:w}}}async function dr(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 cr(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 ll(s,e.day)}function ll(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 pr(t={}){let e=`
11494
+ </script>`;async function pr(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 fl(s,e.days)}function fl(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,y=0,w=0;for(let{node:g,data:S}of t)if(S){a.runs+=S.totals.runs,a.errors+=S.totals.errors,a.hours+=S.totals.hours,a.agents+=S.totals.agents,a.threads+=S.totals.threads;for(let c of S.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 S.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 S.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 S.rotations.byReason)s.set(c.reason,(s.get(c.reason)||0)+c.count);d+=S.rotations.total,p+=S.rotations.tokenSum||0,u+=S.rotations.tokenSamples||0,f=Math.max(f,S.rotations.maxTokens),y+=S.retention.traces,w+=S.retention.tracesWithSteps;for(let c of S.jobs)i.push({...c,node:g.name,nodeUrl:g.url});for(let c of S.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,S)=>g.day.localeCompare(S.day)),origins:[...r.values()].map(g=>({...g,hours:Math.round(g.hours*100)/100})).sort((g,S)=>S.runs-g.runs),causes:[...o.values()].sort((g,S)=>S.count-g.count),jobs:i.sort((g,S)=>S.hours-g.hours),threads:l.sort((g,S)=>S.lastAt-S.firstAt-(g.lastAt-g.firstAt)||S.runs-g.runs),rotations:{total:d,byReason:[...s.entries()].map(([g,S])=>({reason:g,count:S})).sort((g,S)=>S.count-g.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:y,tracesWithSteps:w}}}async function ur(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 mr(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 hl(s,e.day)}function hl(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 fr(t={}){let e=`
11493
11495
  <select id="boardPicker" title="Switch board"></select>
11494
11496
  <div class="search">
11495
11497
  <span class="icon">\u2315</span>
@@ -11590,7 +11592,7 @@ window.MXD=(function(){
11590
11592
  </footer>
11591
11593
  </div>
11592
11594
  </div>
11593
- <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:dl,scripts:`<script>${cl}</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:gl,scripts:`<script>${xl}</script>`,headExtras:`<script>
11594
11596
  // The boards page has its own connection dot + wants body height:100%
11595
11597
  // for the full-viewport kanban layout. Inject the dot into the topbar
11596
11598
  // and override body height at runtime so the shared shell doesn't
@@ -11606,7 +11608,7 @@ window.MXD=(function(){
11606
11608
  right.insertBefore(dot, right.firstChild);
11607
11609
  }
11608
11610
  });
11609
- </script>`})}var dl=`
11611
+ </script>`})}var gl=`
11610
11612
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
11611
11613
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
11612
11614
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -11859,7 +11861,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
11859
11861
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
11860
11862
  .draft-box .draft-row .hint.err { color: var(--red); }
11861
11863
  .draft-box .draft-row .hint.ok { color: var(--green); }
11862
- `,cl=`
11864
+ `,xl=`
11863
11865
  'use strict';
11864
11866
  const state = {
11865
11867
  boards: [], current: null, items: {},
@@ -12912,9 +12914,9 @@ function appendEvents(events) {
12912
12914
  }
12913
12915
 
12914
12916
  loadBoards().catch(e => toast('Init failed: ' + e.message));
12915
- `;function ur(t={}){let a=`<h1>Plain-English glossary</h1>
12917
+ `;function hr(t={}){let a=`<h1>Plain-English glossary</h1>
12916
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>
12917
- ${Yn.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:`${be.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:pl})}var pl=`
12919
+ ${er.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:`${be.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vl})}var vl=`
12918
12920
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
12919
12921
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
12920
12922
  .lead {
@@ -12944,7 +12946,7 @@ article.term .alias {
12944
12946
  }
12945
12947
  article.term p {
12946
12948
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
12947
- }`;function mr(t={}){let e=`<div class="ax-wf__root">
12949
+ }`;function gr(t={}){let e=`<div class="ax-wf__root">
12948
12950
  <aside class="ax-wf__list">
12949
12951
  <header>
12950
12952
  <h2>Workflows</h2>
@@ -13021,7 +13023,7 @@ article.term p {
13021
13023
  </aside>
13022
13024
  </div>
13023
13025
 
13024
- <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:ul,scripts:`<script>${ue({workflowHealth:ra})}${ml}</script>`})}var ul=`
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:bl,scripts:`<script>${ue({workflowHealth:sa})}${yl}</script>`})}var bl=`
13025
13027
  .ax-wf__root {
13026
13028
  display: grid;
13027
13029
  grid-template-columns: 340px 1fr;
@@ -13405,7 +13407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13405
13407
  font-size: 12px; z-index: 50;
13406
13408
  }
13407
13409
  .hint { color: var(--ax-muted); font-size: 11px; }
13408
- `,ml=`
13410
+ `,yl=`
13409
13411
  (() => {
13410
13412
  const $ = (sel) => document.querySelector(sel)
13411
13413
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -14194,7 +14196,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14194
14196
  setInterval(refresh, 15000)
14195
14197
  })
14196
14198
  })();
14197
- `;function fr(t={}){let e=`<div class="ax-proc__root">
14199
+ `;function xr(t={}){let e=`<div class="ax-proc__root">
14198
14200
  <header class="ax-proc__header">
14199
14201
  <h1>Procedures</h1>
14200
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>
@@ -14238,7 +14240,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14238
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>
14239
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>
14240
14242
  </section>
14241
- </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:fl,scripts:`<script>${hl}</script>`})}var fl=`
14243
+ </div>`;return $({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:wl,scripts:`<script>${kl}</script>`})}var wl=`
14242
14244
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
14243
14245
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
14244
14246
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -14264,7 +14266,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14264
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); }
14265
14267
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
14266
14268
  .ax-proc__link:hover { text-decoration: underline; }
14267
- `,hl=`
14269
+ `,kl=`
14268
14270
  (function(){
14269
14271
  function $(sel){ return document.querySelector(sel) }
14270
14272
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -14364,7 +14366,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14364
14366
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
14365
14367
  else bootAll()
14366
14368
  })();
14367
- `;function hr(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14369
+ `;function vr(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14368
14370
  data-task-id="${P(t.taskId)}"
14369
14371
  data-agent-id="${P(t.agentId)}"
14370
14372
  data-node-url="${P(t.nodeUrl)}"
@@ -14407,7 +14409,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14407
14409
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
14408
14410
  </div>
14409
14411
  </footer>
14410
- </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:gl,scripts:`<script>${xl}</script>`})}var gl=`
14412
+ </div>`;return $({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:_l,scripts:`<script>${El}</script>`})}var _l=`
14411
14413
  /* The shell gives <main> no padding, so page content butted straight against
14412
14414
  the sticky topbar. Breathe. */
14413
14415
  .ax-task-page {
@@ -14549,7 +14551,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14549
14551
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
14550
14552
  }
14551
14553
 
14552
- `,xl=`
14554
+ `,El=`
14553
14555
  (function () {
14554
14556
  var root = document.querySelector('.ax-task-page');
14555
14557
  if (!root) return;
@@ -14934,7 +14936,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14934
14936
  });
14935
14937
 
14936
14938
  })();
14937
- `;function gr(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14939
+ `;function br(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
14938
14940
  data-agent-id="${P(t.agentId)}"
14939
14941
  data-agent-name="${P(e)}"
14940
14942
  data-node-url="${P(t.nodeUrl)}">
@@ -14963,7 +14965,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14963
14965
  <div class="ax-history__list" id="hist-list">
14964
14966
  <div class="ax-history__empty">loading\u2026</div>
14965
14967
  </div>
14966
- </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vl,scripts:`<script>${bl}</script>`})}var vl=`
14968
+ </div>`;return $({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Sl,scripts:`<script>${Tl}</script>`})}var Sl=`
14967
14969
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
14968
14970
  flush against the sticky topbar. */
14969
14971
  .ax-history {
@@ -15015,7 +15017,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15015
15017
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
15016
15018
  }
15017
15019
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
15018
- `,bl=`
15020
+ `,Tl=`
15019
15021
  (function () {
15020
15022
  var root = document.querySelector('.ax-history');
15021
15023
  if (!root) return;
@@ -15115,11 +15117,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15115
15117
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15116
15118
  });
15117
15119
  })();
15118
- `;function vr(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 Ee(t,e,l=>xr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:wl(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?Ee(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"])?Ee(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"])?Ee(t,e,l=>{let d=mt.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=ft(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 Ee(t,e,p=>xr(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 yl=["mesh"];function xr(t,e,a,n){let r=mt.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=ft(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 yl)!(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 wl(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(y=>({id:y.id,workflowId:y.workflowId,workflowVersion:y.workflowVersion,homeNode:y.homeNode,status:y.status,pending:y.pending,entityRef:y.entityRef,history:(y.history||[]).slice(-5),parentRunId:y.parentRunId,parentNodeId:y.parentNodeId,rootRunId:y.rootRunId,depth:y.depth,createdAt:y.createdAt,updatedAt:y.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 Ee(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 kl(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 kl(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 wr(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 Se(t,e,l=>yr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Al(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?Se(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"])?Se(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"])?Se(t,e,l=>{let d=ft.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=ht(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 Se(t,e,p=>yr(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 Cl=["mesh"];function yr(t,e,a,n){let r=ft.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=ht(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 Cl)!(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 Al(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(y=>({id:y.id,workflowId:y.workflowId,workflowVersion:y.workflowVersion,homeNode:y.homeNode,status:y.status,pending:y.pending,entityRef:y.entityRef,history:(y.history||[]).slice(-5),parentRunId:y.parentRunId,parentNodeId:y.parentNodeId,rootRunId:y.rootRunId,depth:y.depth,createdAt:y.createdAt,updatedAt:y.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 Se(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 Ml(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 Ml(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)}
15119
15121
 
15120
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)}
15121
15123
 
15122
- `)}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 Ee(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 _l}from"zlib";var El=[41,121,255],Sl=[255,255,255],br=new Map;function Ot(t){let e=br.get(t);return e||(e=Cl(t,Tl(t)),br.set(t,e)),e}function Tl(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?Sl:El;a.set(d,o*e+1+s*3)}return a}function Cl(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]),Nt("IHDR",a),Nt("IDAT",_l(e)),Nt("IEND",Buffer.alloc(0))])}function Nt(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(Ml(n)),Buffer.concat([a,n,r])}var Al=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 Ml(t){let e=4294967295;for(let a of t)e=Al[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function nt(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 Il(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:nt(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:nt(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:nt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function $l(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:nt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Ll=/^\/api\/app\/tasks\/(cancel|followup)$/;async function yr(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 y=jl(s.searchParams.get("timezone")),w=await o.snapshot({date:Rl(y),timezone:y});return a==="/api/app/activity"?re(e,200,{ts:w.ts,tasks:$l(w.nodes)}):re(e,200,{ts:w.ts,nodes:w.nodes.map(Il)})}if(n==="GET"&&a==="/api/app/approvals")return re(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Ll);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 je(t)}catch(y){return re(e,400,{error:y.message})}let p=Le(d.node);if(!p)return re(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let y=Le(d.taskId);if(!y)return re(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(y)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Le(d.message);if(!T)return re(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 y=Le(d.cronId);if(!y||typeof d.enabled!="boolean")return re(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(y)}/enabled`,{enabled:d.enabled})}else{let y=Le(d.key),w=d.action;if(!y||w!=="yes"&&w!=="no"&&w!=="later")return re(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,y,w,u)}return re(e,f.status,f.body)}function Le(t){return typeof t=="string"?t.trim():""}function jl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Rl(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function je(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 re(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Pl=2048,wr=/^[A-Za-z0-9_-]{8,256}$/;async function kr(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 oe(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(y=>y.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return oe(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return oe(e,404,{error:"not found"});if(!s||l)return oe(e,503,{error:l});let d;try{d=await je(t)}catch(y){return oe(e,400,{error:y.message})}let p=Nl(d.endpoint,o.allowedHosts);if(!p){let y="";try{y=new URL(String(d.endpoint)).hostname}catch{}return oe(e,400,{error:`not a known push service${y?`: ${y}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return oe(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=d.keys?.p256dh,f=d.keys?.auth;return typeof u!="string"||!wr.test(u)||typeof f!="string"||!wr.test(f)?oe(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?oe(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}),oe(e,200,{ok:!0}))}function Nl(t,e){if(typeof t!="string"||t.length>Pl)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 oe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ol=50;function Dl(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 _r(t,e,a,n){let{path:r,body:o}=Dl(e),s="",i=[],l=new Map,d=(p,u,f)=>{let{cleanText:y,ui:w}=p==="done"?sa(u):{cleanText:u,ui:void 0},T=Bl(w);return{status:p,text:y,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 zl(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<Ol){let y={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(y),f.id&&l.set(String(f.id),y)}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,Hl(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 Hl(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 Bl(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*zl(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),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 Se(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 Il}from"zlib";var $l=[41,121,255],Ll=[255,255,255],kr=new Map;function Dt(t){let e=kr.get(t);return e||(e=Rl(t,jl(t)),kr.set(t,e)),e}function jl(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?Ll:$l;a.set(d,o*e+1+s*3)}return a}function Rl(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]),Nt("IHDR",a),Nt("IDAT",Il(e)),Nt("IEND",Buffer.alloc(0))])}function Nt(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(Ol(n)),Buffer.concat([a,n,r])}var Pl=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 Ol(t){let e=4294967295;for(let a of t)e=Pl[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function nt(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 Nl(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:nt(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:nt(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:nt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Dl(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:nt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Hl=/^\/api\/app\/tasks\/(cancel|followup)$/;async function _r(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 y=Bl(s.searchParams.get("timezone")),w=await o.snapshot({date:zl(y),timezone:y});return a==="/api/app/activity"?re(e,200,{ts:w.ts,tasks:Dl(w.nodes)}):re(e,200,{ts:w.ts,nodes:w.nodes.map(Nl)})}if(n==="GET"&&a==="/api/app/approvals")return re(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Hl);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 ye(t)}catch(y){return re(e,400,{error:y.message})}let p=Re(d.node);if(!p)return re(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let y=Re(d.taskId);if(!y)return re(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(y)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let T=Re(d.message);if(!T)return re(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 y=Re(d.cronId);if(!y||typeof d.enabled!="boolean")return re(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(y)}/enabled`,{enabled:d.enabled})}else{let y=Re(d.key),w=d.action;if(!y||w!=="yes"&&w!=="no"&&w!=="later")return re(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,y,w,u)}return re(e,f.status,f.body)}function Re(t){return typeof t=="string"?t.trim():""}function Bl(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function zl(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function ye(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 re(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var ql=2048,Er=/^[A-Za-z0-9_-]{8,256}$/;async function Sr(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 oe(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(y=>y.publicKey===i).length:0});if(n==="GET"&&a==="/api/app/alerts")return oe(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe")return oe(e,404,{error:"not found"});if(!s||l)return oe(e,503,{error:l});let d;try{d=await ye(t)}catch(y){return oe(e,400,{error:y.message})}let p=Ul(d.endpoint,o.allowedHosts);if(!p){let y="";try{y=new URL(String(d.endpoint)).hostname}catch{}return oe(e,400,{error:`not a known push service${y?`: ${y}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return oe(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=d.keys?.p256dh,f=d.keys?.auth;return typeof u!="string"||!Er.test(u)||typeof f!="string"||!Er.test(f)?oe(e,400,{error:"keys.p256dh and keys.auth are required"}):d.publicKey!==void 0&&d.publicKey!==i?oe(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}),oe(e,200,{ok:!0}))}function Ul(t,e){if(typeof t!="string"||t.length>ql)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 oe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Fl=50;function Wl(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 Tr(t,e,a,n){let{path:r,body:o}=Wl(e),s="",i=[],l=new Map,d=(p,u,f)=>{let{cleanText:y,ui:w}=p==="done"?la(u):{cleanText:u,ui:void 0},T=Xl(w);return{status:p,text:y,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 Kl(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<Fl){let y={name:String(f.name||"tool").slice(0,80),...f.arg?{arg:String(f.arg).slice(0,80)}:{}};i.push(y),f.id&&l.set(String(f.id),y)}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,Gl(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 Gl(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 Xl(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*Kl(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,`
15123
15125
  `);let s;for(;(s=n.indexOf(`
15124
15126
 
15125
15127
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",d=[];for(let p of i.split(`
@@ -15129,10 +15131,10 @@ data: ${JSON.stringify(s)}
15129
15131
 
15130
15132
  `)},r=setInterval(()=>{a()&&e.write(`: ping
15131
15133
 
15132
- `)},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 Sr=8e3,ql=/^[A-Za-z0-9_.:-]{1,64}$/,Se=new Map;async function Tr(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 O(e,200,{nodes:await Cr(o)});let s=o.store();if(!s)return O(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return O(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 O(e,404,{error:"no such conversation"});let p=Se.get(d.id);return O(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&&Se.get(d.id);if(!d||!p)return O(e,404,{error:"nothing is running in this conversation"});Ar(e);let{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g}=d;return e.write(Dt("conversation",{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g})),e.write(Dt("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return O(e,404,{error:"not found"});let l;try{l=await je(t,64*1024)}catch(d){return O(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=s.get(r.id,String(l.conversationId??""));if(!d)return O(e,404,{error:"no such conversation"});let p=Se.get(d.id);return p?(p.ac.abort(),Ht(d,o,r.name),O(e,200,{stopped:!0})):await Ht(d,o,r.name)?O(e,200,{stopped:!0}):O(e,404,{error:"nothing is running in this conversation"})}return await Fl(e,l,r,s,o),!0}function Ul(t,e,a){let n=Te(e.url),r=new Set,o=[];for(let s of t){let i=Te(s.url),l=a.find(u=>Te(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}})})}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 Cr(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Ul(e.nodes,t.daemon,a)}async function Fl(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Sr){O(t,400,{error:`message must be 1\u2013${Sr} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){O(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!ql.test(T)){O(t,400,{error:"pick an agent"});return}let g=(await Cr(r)).find(c=>c.target===w);if(!g){O(t,400,{error:`unknown node "${w}"`});return}if(!g.online){O(t,409,{error:`${g.name} is offline`});return}let S=g.agents.find(c=>c.id===T);if(!S){O(t,400,{error:`no agent "${T}" on ${g.name}`});return}s=n.create(a.id,{node:w,nodeName:g.name,agent:T,agentName:S.name},o)}if(Se.has(s.id)){O(t,409,{error:"The agent is still answering in this conversation."});return}let i=new rt(r.orphanLimitMs??18e5);Se.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:y}=s;Ar(t),t.write(Dt("conversation",{id:l,title:d,node:p,nodeName:u,agent:f,agentName:y})),i.attach(t);try{let w=await _r(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.`,Ht(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{Se.delete(l),i.finish()}}function Ar(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Dt(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 Ar=8e3,Jl=/^[A-Za-z0-9_.:-]{1,64}$/,Te=new Map;async function Mr(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 N(e,200,{nodes:await Ir(o)});let s=o.store();if(!s)return N(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/conversations")return N(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 N(e,404,{error:"no such conversation"});let p=Te.get(d.id);return N(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&&Te.get(d.id);if(!d||!p)return N(e,404,{error:"nothing is running in this conversation"});$r(e);let{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g}=d;return e.write(Ht("conversation",{id:u,title:f,node:y,nodeName:w,agent:T,agentName:g})),e.write(Ht("resume",{text:p.text,tools:p.tools})),p.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return N(e,404,{error:"not found"});let l;try{l=await ye(t,64*1024)}catch(d){return N(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=s.get(r.id,String(l.conversationId??""));if(!d)return N(e,404,{error:"no such conversation"});let p=Te.get(d.id);return p?(p.ac.abort(),Bt(d,o,r.name),N(e,200,{stopped:!0})):await Bt(d,o,r.name)?N(e,200,{stopped:!0}):N(e,404,{error:"nothing is running in this conversation"})}return await Yl(e,l,r,s,o),!0}function Vl(t,e,a){let n=Ce(e.url),r=new Set,o=[];for(let s of t){let i=Ce(s.url),l=a.find(u=>Ce(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}})})}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 Ir(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Vl(e.nodes,t.daemon,a)}async function Yl(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Ar){N(t,400,{error:`message must be 1\u2013${Ar} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){N(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!Jl.test(T)){N(t,400,{error:"pick an agent"});return}let g=(await Ir(r)).find(c=>c.target===w);if(!g){N(t,400,{error:`unknown node "${w}"`});return}if(!g.online){N(t,409,{error:`${g.name} is offline`});return}let S=g.agents.find(c=>c.id===T);if(!S){N(t,400,{error:`no agent "${T}" on ${g.name}`});return}s=n.create(a.id,{node:w,nodeName:g.name,agent:T,agentName:S.name},o)}if(Te.has(s.id)){N(t,409,{error:"The agent is still answering in this conversation."});return}let i=new rt(r.orphanLimitMs??18e5);Te.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:y}=s;$r(t),t.write(Ht("conversation",{id:l,title:d,node:p,nodeName:u,agent:f,agentName:y})),i.attach(t);try{let w=await Tr(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.`,Bt(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{Te.delete(l),i.finish()}}function $r(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Ht(t,e){return`event: ${t}
15133
15135
  data: ${JSON.stringify(e)}
15134
15136
 
15135
- `}async function Ht(t,e,a){try{let n=Te(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Te(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Te(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 Te(t){return t.replace(/\/+$/,"")}function O(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Mr=`
15137
+ `}async function Bt(t,e,a){try{let n=Ce(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(d=>d.peer===t.node);if(!l)return 0;n=Ce(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Ce(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 Ce(t){return t.replace(/\/+$/,"")}function N(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ql={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},ot=class{constructor(e=Ql,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)}},Zl="That code didn't work. Check it, or run agentx app pair for a new one.",ed=400;async function Lr(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 ye(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await td(a,e.minMs??ed),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:Zl}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function td(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}var jr=`
15136
15138
  (function () {
15137
15139
  var fleetPanel = document.getElementById('panel-fleet');
15138
15140
  var activityPanel = document.getElementById('panel-activity');
@@ -15376,7 +15378,7 @@ data: ${JSON.stringify(e)}
15376
15378
  setInterval(refresh, 15000);
15377
15379
  refresh();
15378
15380
  })();
15379
- `;var Ir=`
15381
+ `;var Rr=`
15380
15382
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
15381
15383
  .fx-head h2 { margin: 4px 0 0; }
15382
15384
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -15433,7 +15435,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15433
15435
  }
15434
15436
  .fx-error:empty { display: none; }
15435
15437
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
15436
- `;var $r=`
15438
+ `;var Pr=`
15437
15439
  (function () {
15438
15440
  var panel = document.getElementById('panel-alerts');
15439
15441
  if (!panel) return;
@@ -15595,7 +15597,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15595
15597
  refresh();
15596
15598
  loadRecent();
15597
15599
  })();
15598
- `;var Lr=`
15600
+ `;var Or=`
15599
15601
  (function () {
15600
15602
  var panel = document.getElementById('panel-chat');
15601
15603
  var V = window.AXChatView;
@@ -15883,7 +15885,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15883
15885
  var last = recall('ax-chat-conv');
15884
15886
  if (last) openConversation(last);
15885
15887
  })();
15886
- `;var jr=`
15888
+ `;var Nr=`
15887
15889
  window.AXChatView = (function () {
15888
15890
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
15889
15891
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -16044,7 +16046,7 @@ window.AXChatView = (function () {
16044
16046
  return { NL: NL, esc: esc, httpUrl: httpUrl, md: md, preview: preview, setTools: setTools, renderUi: renderUi, readStream: readStream,
16045
16047
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
16046
16048
  })();
16047
- `;var Rr=`
16049
+ `;var Dr=`
16048
16050
  body { height: 100dvh; }
16049
16051
  main { min-height: 0; }
16050
16052
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -16127,8 +16129,91 @@ main { min-height: 0; }
16127
16129
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
16128
16130
  }
16129
16131
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
16130
- `;var Bt=`
16131
- var CACHE = 'agentx-app-v2';
16132
+ `;var Hr=`
16133
+ <main class="card">
16134
+ <h1>This phone isn't paired</h1>
16135
+ <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>
16136
+ <form id="pair-form" class="pair-form" novalidate>
16137
+ <label for="pair-code">Pairing code</label>
16138
+ <input id="pair-code" name="code" type="text" placeholder="XXXX-XXXX" maxlength="16"
16139
+ autocomplete="one-time-code" inputmode="text" autocapitalize="characters" autocorrect="off" spellcheck="false" enterkeyhint="go" required>
16140
+ <button type="submit" id="pair-btn">Pair</button>
16141
+ <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>
16142
+ <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
16143
+ </form>
16144
+ <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>
16145
+ <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
16146
+ </main>`,Br=`
16147
+ .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
16148
+ .pair-form label { font-weight: 600; }
16149
+ .pair-form input {
16150
+ box-sizing: border-box; width: 100%; min-height: 60px; padding: 10px 14px;
16151
+ font: 600 26px/1.2 var(--ax-mono); letter-spacing: 0.12em; text-align: center; text-transform: uppercase;
16152
+ color: var(--ax-text); background: var(--ax-surface); border: 2px solid var(--ax-border); border-radius: var(--ax-radius-sm);
16153
+ }
16154
+ .pair-form input::placeholder { color: var(--ax-text-3, var(--ax-text-2)); opacity: 0.6; }
16155
+ .pair-form input:focus { border-color: var(--ax-accent); outline: none; }
16156
+ .pair-form button {
16157
+ min-height: 52px; border: 0; border-radius: var(--ax-radius-pill);
16158
+ font: inherit; font-size: 17px; font-weight: 700; color: #fff; background: var(--ax-accent); cursor: pointer;
16159
+ }
16160
+ .pair-form button:disabled { opacity: 0.55; cursor: default; }
16161
+ .pair-msg { margin: 0; min-height: 1.5em; }
16162
+ .pair-msg.bad { color: var(--ax-red-ink); }
16163
+ [data-theme="dark"] .pair-msg.bad { color: var(--ax-red); }
16164
+ .pair-offline {
16165
+ margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
16166
+ background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
16167
+ }
16168
+ `,zr=`
16169
+ (function () {
16170
+ var form = document.getElementById('pair-form');
16171
+ var input = document.getElementById('pair-code');
16172
+ var btn = document.getElementById('pair-btn');
16173
+ var msg = document.getElementById('pair-msg');
16174
+ var offline = document.getElementById('pair-offline');
16175
+ var busy = false;
16176
+ function setOnline(on) { offline.hidden = on; btn.disabled = busy || !on; }
16177
+ function say(text, bad) { msg.textContent = text; msg.className = bad ? 'pair-msg bad' : 'pair-msg'; }
16178
+ setOnline(navigator.onLine !== false);
16179
+ window.addEventListener('online', function () { setOnline(true); });
16180
+ window.addEventListener('offline', function () { setOnline(false); });
16181
+ input.addEventListener('input', function () { if (msg.className.indexOf('bad') >= 0) say('', false); });
16182
+ function done() { busy = false; setOnline(navigator.onLine !== false); }
16183
+ form.addEventListener('submit', function (ev) {
16184
+ ev.preventDefault();
16185
+ if (busy) return;
16186
+ var code = input.value.trim();
16187
+ if (!code) { say('Type the code shown by agentx app pair.', true); input.focus(); return; }
16188
+ if (navigator.onLine === false) { setOnline(false); return; }
16189
+ busy = true; btn.disabled = true; say('Pairing\u2026', false);
16190
+ fetch('/api/app/pair-code', {
16191
+ method: 'POST',
16192
+ credentials: 'same-origin',
16193
+ headers: { 'Content-Type': 'application/json' },
16194
+ body: JSON.stringify({ code: code }),
16195
+ }).then(function (r) {
16196
+ if (r.ok) { say('Paired. Opening the app\u2026', false); location.replace('/app'); return; }
16197
+ done();
16198
+ if (r.status === 429) {
16199
+ return r.json().catch(function () { return {}; }).then(function (b) {
16200
+ var m = Math.max(1, Math.ceil(((b && b.retryAfter) || 300) / 60));
16201
+ say('Too many attempts. Wait ' + m + (m === 1 ? ' minute' : ' minutes') + ', then try again.', true);
16202
+ });
16203
+ }
16204
+ say("That code didn't work. Check it, or run agentx app pair on the computer for a new one.", true);
16205
+ input.focus(); input.select();
16206
+ }).catch(function () {
16207
+ done();
16208
+ say('Could not reach AgentX. Pairing needs a connection: check this phone is on your tailnet, then try again.', true);
16209
+ });
16210
+ });
16211
+ if ('serviceWorker' in navigator) {
16212
+ navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
16213
+ }
16214
+ })();
16215
+ `;var zt=`
16216
+ var CACHE = 'agentx-app-v3';
16132
16217
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
16133
16218
  self.addEventListener('install', function (e) {
16134
16219
  e.waitUntil(caches.open(CACHE).then(function (c) { return c.addAll(STATIC); }).then(function () { return self.skipWaiting(); }));
@@ -16146,10 +16231,14 @@ self.addEventListener('fetch', function (e) {
16146
16231
  if (req.mode === 'navigate' && url.pathname === '/app') {
16147
16232
  e.respondWith(fetch(req).then(function (res) {
16148
16233
  var copy = res.clone();
16149
- caches.open(CACHE).then(function (c) { return res.ok ? c.put('/app', copy) : res.status === 401 ? c.delete('/app') : null; });
16234
+ caches.open(CACHE).then(function (c) {
16235
+ if (res.ok) return Promise.all([c.put('/app', copy), c.delete('/app/locked')]);
16236
+ if (res.status === 401) return Promise.all([c.put('/app/locked', copy), c.delete('/app')]);
16237
+ return null;
16238
+ });
16150
16239
  return res;
16151
16240
  }).catch(function () {
16152
- return caches.match('/app').then(function (hit) { return hit || Response.error(); });
16241
+ return caches.match('/app').then(function (hit) { return hit || caches.match('/app/locked'); }).then(function (hit) { return hit || Response.error(); });
16153
16242
  }));
16154
16243
  return;
16155
16244
  }
@@ -16195,7 +16284,7 @@ self.addEventListener('notificationclick', function (e) {
16195
16284
  return self.clients.openWindow(target);
16196
16285
  }));
16197
16286
  });
16198
- `;var Wl="<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 zt(t){return`<meta charset="utf-8">
16287
+ `;var ad="<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 qt(t){return`<meta charset="utf-8">
16199
16288
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
16200
16289
  <meta name="theme-color" content="#2979FF">
16201
16290
  <meta name="referrer" content="no-referrer">
@@ -16206,13 +16295,13 @@ self.addEventListener('notificationclick', function (e) {
16206
16295
  <link rel="icon" type="image/png" href="/app/icon-192.png">
16207
16296
  <link rel="apple-touch-icon" href="/app/icon-192.png">
16208
16297
  <title>${t}</title>
16209
- ${Wl}
16210
- <style>${_a}${Kl}</style>`}var Pr=[{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 Nr(){let t=Pr.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=Pr.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
16298
+ ${ad}
16299
+ <style>${Sa}${od}</style>`}var qr=[{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 Ur(){let t=qr.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=qr.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
16211
16300
  <h2>${a.label}</h2>
16212
16301
  <p class="soon">${a.soon}</p>
16213
16302
  </section>`).join("");return`<!doctype html>
16214
16303
  <html lang="en">
16215
- <head>${zt("AgentX")}<style>${Jl}${Ir}${Rr}</style></head>
16304
+ <head>${qt("AgentX")}<style>${sd}${Rr}${Dr}</style></head>
16216
16305
  <body>
16217
16306
  <header class="bar">
16218
16307
  <div>
@@ -16224,32 +16313,28 @@ ${Wl}
16224
16313
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
16225
16314
  <main>${e}</main>
16226
16315
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
16227
- <script>${Gl}</script>
16228
- <script>${Mr}</script>
16229
- <script>${$r}</script>
16230
- <script>${ue({markdownToHtml:Ea})}${jr}${Lr}</script>
16316
+ <script>${nd}</script>
16317
+ <script>${jr}</script>
16318
+ <script>${Pr}</script>
16319
+ <script>${ue({markdownToHtml:Ta})}${Nr}${Or}</script>
16231
16320
  </body>
16232
- </html>`}function Or(){return`<!doctype html>
16321
+ </html>`}function Fr(){return`<!doctype html>
16233
16322
  <html lang="en">
16234
- <head>${zt("Pair \xB7 AgentX")}</head>
16323
+ <head>${qt("Pair \xB7 AgentX")}</head>
16235
16324
  <body>
16236
16325
  <main class="card">
16237
16326
  <h1>Pairing this phone\u2026</h1>
16238
16327
  <p id="msg" role="status">One moment.</p>
16239
16328
  </main>
16240
- <script>${Xl}</script>
16329
+ <script>${rd}</script>
16241
16330
  </body>
16242
- </html>`}function Dr(){return`<!doctype html>
16331
+ </html>`}function Wr(){return`<!doctype html>
16243
16332
  <html lang="en">
16244
- <head>${zt("Not paired \xB7 AgentX")}</head>
16245
- <body>
16246
- <main class="card">
16247
- <h1>This phone isn't paired</h1>
16248
- <p>On the computer running AgentX, run <code>agentx app pair</code> and scan the QR code it shows with this phone's camera.</p>
16249
- <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
16250
- </main>
16333
+ <head>${qt("Not paired \xB7 AgentX")}<style>${Br}</style></head>
16334
+ <body>${Hr}
16335
+ <script>${zr}</script>
16251
16336
  </body>
16252
- </html>`}function Hr(){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 Gl=`
16337
+ </html>`}function Gr(){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 nd=`
16253
16338
  (function () {
16254
16339
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
16255
16340
  function select(tab, focus) {
@@ -16315,12 +16400,12 @@ ${Wl}
16315
16400
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
16316
16401
  }
16317
16402
  })();
16318
- `,Xl=`
16403
+ `,rd=`
16319
16404
  (function () {
16320
16405
  var msg = document.getElementById('msg');
16321
16406
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
16322
16407
  try { history.replaceState(null, '', location.pathname); } catch (e) {}
16323
- if (!m) { msg.textContent = 'This link has no pairing code. Run agentx app pair again and scan the new QR code.'; return; }
16408
+ if (!m) { msg.textContent = 'This link has no pairing key. Run agentx app pair again and scan the new QR code.'; return; }
16324
16409
  fetch('/api/app/session', {
16325
16410
  method: 'POST',
16326
16411
  credentials: 'same-origin',
@@ -16328,11 +16413,11 @@ ${Wl}
16328
16413
  }).then(function (r) {
16329
16414
  if (r.ok) { location.replace('/app'); return; }
16330
16415
  msg.textContent = r.status === 401
16331
- ? 'This pairing code is not valid any more. Run agentx app pair again and scan the new QR code.'
16416
+ ? 'This pairing link is not valid any more. Run agentx app pair again and scan the new QR code.'
16332
16417
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
16333
16418
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
16334
16419
  })();
16335
- `,Kl=`
16420
+ `,od=`
16336
16421
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
16337
16422
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
16338
16423
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -16344,7 +16429,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
16344
16429
  .card h1 { font-size: 22px; margin: 0 0 12px; }
16345
16430
  .muted { color: var(--ax-text-2); }
16346
16431
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
16347
- `,Jl=`
16432
+ `,sd=`
16348
16433
  body { display: flex; flex-direction: column; }
16349
16434
  .bar {
16350
16435
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -16381,7 +16466,7 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
16381
16466
  }
16382
16467
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
16383
16468
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
16384
- `;var zr="agentx_app",Vl=400*86400;async function qr(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Q;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",Hr());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",Bt);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Ot(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Ot(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",Or())}if(n==="POST"&&a==="/api/app/session"){let i=Br(qt(t),o);return i?(e.setHeader("Set-Cookie",`${zr}=${qt(t)}; Path=/; Max-Age=${Vl}; HttpOnly; Secure; SameSite=Strict`),Re(e,200,{device:i.name})):Re(e,401,{error:"invalid or revoked device token"})}let s=Br(Yl(t),o);return s?n==="GET"&&a==="/app"?fe(e,200,"text/html; charset=utf-8",Nr()):n==="GET"&&a==="/api/app/me"?Re(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await yr(t,e,a,n,s.name,r.fleet)||r.push&&await kr(t,e,a,n,s,r.push)||r.chat&&await Tr(t,e,a,n,s,r.chat)?!0:Re(e,404,{error:"not found"}):a==="/app"?fe(e,401,"text/html; charset=utf-8",Dr()):Re(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function Br(t,e){if(!t)return null;let a=e.verify(t);return a&&ge(a,"app")?a:null}function Yl(t){return qt(t)??Ql(t,zr)}function qt(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Ql(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Re(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Zl}from"crypto";var Ce={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},ed=/^c[a-z0-9]{8,32}$/;function td(t){return ed.test(t)}var ot=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
16469
+ `;var Kr="agentx_app",id=400*86400,ld=new ot;async function Jr(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new Q;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",Gr());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",zt);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Dt(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Dt(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",Fr())}if(n==="POST"&&a==="/api/app/session"){let i=Ut(Ft(t),o);return i?(e.setHeader("Set-Cookie",Xr(Ft(t))),Ae(e,200,{device:i.name})):Ae(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Lr(t,{codes:r.pairCodes??new Pa,limiter:r.pairLimiter??ld,verify:l=>Ut(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Xr(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ae(e,i.status,i.body)}let s=Ut(dd(t),o);return s?n==="GET"&&a==="/app"?fe(e,200,"text/html; charset=utf-8",Ur()):n==="GET"&&a==="/api/app/me"?Ae(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await _r(t,e,a,n,s.name,r.fleet)||r.push&&await Sr(t,e,a,n,s,r.push)||r.chat&&await Mr(t,e,a,n,s,r.chat)?!0:Ae(e,404,{error:"not found"}):a==="/app"?fe(e,401,"text/html; charset=utf-8",Wr()):Ae(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}function Ut(t,e){if(!t)return null;let a=e.verify(t);return a&&ge(a,"app")?a:null}function Xr(t){return`${Kr}=${t}; Path=/; Max-Age=${id}; HttpOnly; Secure; SameSite=Strict`}function dd(t){return Ft(t)??cd(t,Kr)}function Ft(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function cd(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function fe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ae(t,e,a){return fe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as pd}from"crypto";var Me={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50},ud=/^c[a-z0-9]{8,32}$/;function md(t){return ud.test(t)}var st=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
16385
16470
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
16386
16471
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
16387
16472
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -16389,30 +16474,30 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
16389
16474
  CREATE TABLE IF NOT EXISTS app_chat_messages (
16390
16475
  id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id TEXT NOT NULL, role TEXT NOT NULL,
16391
16476
  content TEXT NOT NULL, status TEXT, error TEXT, ui TEXT, tools TEXT, at INTEGER NOT NULL);
16392
- 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)}${Zl(4).toString("hex")}`,s={id:o,title:nd(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
16393
- (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(!td(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(ad);return{...Ur(n),messages:r}}list(e,a=Ce.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
16477
+ 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)}${pd(4).toString("hex")}`,s={id:o,title:hd(n),...a,createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
16478
+ (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(!md(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(fd);return{...Vr(n),messages:r}}list(e,a=Me.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
16394
16479
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
16395
16480
  (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
16396
- 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{...Ur(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>Ce.content?n.content.slice(0,Ce.content)+`
16481
+ 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{...Vr(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>Me.content?n.content.slice(0,Me.content)+`
16397
16482
 
16398
- [Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,Ce.toolsPerMessage);return this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, at)
16483
+ [Cut here: the full answer is in the agent's task history.]`:n.content,s=n.tools?.slice(0,Me.toolsPerMessage);return this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, at)
16399
16484
  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
16400
- (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ce.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 = ?
16401
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ce.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 Ur(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 ad(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 nd(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function Bm(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let y of a)try{s.set(y.id,hd(y,t))}catch(w){console.error(` Board "${y.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Pe(process.cwd(),t.workflows.dir):void 0,d=new Zt(l?{baseDir:l}:void 0),p=new ea(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new ta(l?{baseDir:l}:void 0);Bn(t),fa({business:t.business?.enabled===!0}),rd(async(y,w)=>{try{await pd(y,w,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(T){b(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let y=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
16485
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Me.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 = ?
16486
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Me.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 Vr(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 fd(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 hd(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 y of a)try{s.set(y.id,Cd(y,t))}catch(w){console.error(` Board "${y.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Pe(process.cwd(),t.workflows.dir):void 0,d=new ta(l?{baseDir:l}:void 0),p=new aa(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new na(l?{baseDir:l}:void 0);Un(t),ga({business:t.business?.enabled===!0}),gd(async(y,w)=>{try{await _d(y,w,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(T){b(w,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let y=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
16402
16487
  Live dashboard: http://${y}:${n}
16403
16488
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
16404
16489
  Kanban dashboard: http://${y}:${n}
16405
- `),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 cd=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 pd(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ua(t.headers)==="foreign"&&ma(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await qr(t,e,r,o,{nodeName:a.config.node?.name,fleet:Kr(a.config),push:$d(a.config),chat:Ld(a.config)}))return;if(o==="GET"&&cd.has(r)&&Pa("page",r),o==="GET"&&r==="/"){let c=Ma();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(Pt({peers:N(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pr({peers:N(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pt({peers:N(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await he(a.config);if(!c){b(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){b(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 he(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await pe(t):void 0,x=h?.node??m,k=x?c.find(M=>M.url===x):c[0];if(!k){b(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})}:{}});b(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(c){b(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 pe(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}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await he(a.config);if(!c){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wa({peers:N(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fa({peers:N(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(Ba({peers:N(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let c=new AbortController,m=setTimeout(()=>c.abort(),8e3);try{let h=na(await he(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 E=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:A.name,url:A.url,ok:!0,data:await E.json()}}catch(E){return{name:A.name,url:A.url,ok:!1,error:E.message}}}));b(e,200,{nodes:M});return}let x=h.find(M=>M.url===n.searchParams.get("node"));if(!x){b(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))){b(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await aa(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}`}:{}}});b(e,_.status,await _.json())}catch(h){b(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(ir({peers:N(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({peers:N(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mr({peers:N(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fr({peers:N(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Aa({}));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(hr({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:N(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(gr({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:N(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Ia(t,e);return}if(o==="POST"&&r==="/api/setup"){await $a(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await La(t,e);return}if(o==="GET"&&r==="/admin"){Va(t,e,N(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){dn(e,N(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){nn(t,e,N(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}gn(t,e,N(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 Dd(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await jt(t,e,r,h=>Vr(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=Oe(M.url.replace(/\/+$/,""),a.config);if(A){await Wr(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}b(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=Oe(c,a.config);if(!m){b(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Wr(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await xn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Hd(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-JEWMHXYH.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:h});b(e,200,x)}catch(c){b(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(wn({peers:N(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await yn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kn({peers:N(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({peers:N(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 xd(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 zn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await jt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Un(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){Gn(t,e,d[1],N(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 Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ya(t,e);return}if(r.startsWith("/api/admin/approvals")){await cn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await rn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Xn(t,e,r);return}if(r.startsWith("/api/admin/")){await Qa(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(Ga);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){b(e,400,{error:"invalid asset name"});return}let m=Nd("web/"+c);try{let h=await Od(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{b(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);b(e,200,c)}catch(c){b(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});b(e,200,h)}catch(c){b(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 he(a.config);b(e,200,await lr(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){b(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)){b(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 he(a.config);b(e,200,await cr(h,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(h){b(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){b(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){b(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){b(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){b(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){b(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(x)}`}try{await dr(e,await he(a.config),c,h)}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Sd(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){b(e,400,{error:"node, agent, task query params required"});return}await Td(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){b(e,400,{error:"node and agent query params required"});return}await Md(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"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Id(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){b(e,400,{error:"node query param required"});return}await Xt(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();b(e,200,h)}catch(c){b(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){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(c){b(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await pe(t);try{let m=await Rd(a.config,c);b(e,200,m)}catch(m){b(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(!Cd(t,e,[`agent:${c}`]))return;await Ad(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 Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await bd(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"){b(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){b(e,400,{error:"node query param required"});return}await Xt(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
16490
+ `),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 kd=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 _d(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(fa(t.headers)==="foreign"&&ha(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Jr(t,e,r,o,{nodeName:a.config.node?.name,fleet:to(a.config),push:Ud(a.config),chat:Fd(a.config)}))return;if(o==="GET"&&kd.has(r)&&Da("page",r),o==="GET"&&r==="/"){let c=$a();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(Ot({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fr({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ot({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[c]=await he(a.config);if(!c){b(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){b(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 he(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),h=o==="POST"?await pe(t):void 0,x=h?.node??m,k=x?c.find(M=>M.url===x):c[0];if(!k){b(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})}:{}});b(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(c){b(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 pe(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}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[c]=await he(a.config);if(!c){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(c.url+"/api/n8n/workflows",{headers:c.token?{Authorization:`Bearer ${c.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ka({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xa({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(Ua({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=oa(await he(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 E=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:c.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:A.name,url:A.url,ok:!0,data:await E.json()}}catch(E){return{name:A.name,url:A.url,ok:!1,error:E.message}}}));b(e,200,{nodes:M});return}let x=h.find(M=>M.url===n.searchParams.get("node"));if(!x){b(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))){b(e,405,{error:"Unknown monitor operation"});return}let v=o==="POST"?JSON.stringify(await ra(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}`}:{}}});b(e,_.status,await _.json())}catch(h){b(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(cr({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hr({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(gr({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xr({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ia({}));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(vr({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(br({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"){La(t,e);return}if(o==="POST"&&r==="/api/setup"){await ja(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ra(t,e);return}if(o==="GET"&&r==="/admin"){Za(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){un(e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){sn(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}bn(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 Vd(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Rt(t,e,r,h=>no(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=Ne(M.url.replace(/\/+$/,""),a.config);if(A){await Qr(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(v)}`);return}}b(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=Ne(c,a.config);if(!m){b(e,404,{error:`unknown peer: ${c}`});return}let h=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Qr(t,e,m,r+(h==="?"?"":h));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await yn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Yd(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-YFA4ZSRH.js"),h=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:h});b(e,200,x)}catch(c){b(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(En({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await _n(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Sn({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Tn({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 Md(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 Fn(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Rt(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Gn(t,e,r))return;let d=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(d){Jn(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 Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await en(t,e);return}if(r.startsWith("/api/admin/approvals")){await mn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await ln(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Vn(t,e,r);return}if(r.startsWith("/api/admin/")){await tn(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(Ja);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){b(e,400,{error:"invalid asset name"});return}let m=Kd("web/"+c);try{let h=await Jd(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{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await Oe(a.config);b(e,200,c)}catch(c){b(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 Oe(a.config,{date:c,timezone:m});b(e,200,h)}catch(c){b(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 he(a.config);b(e,200,await pr(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){b(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)){b(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 he(a.config);b(e,200,await mr(h,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(h){b(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){b(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){b(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){b(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){b(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){b(e,400,{error:"task required"});return}h=`/analytics/run/${encodeURIComponent(x)}`}try{await ur(e,await he(a.config),c,h)}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){Nd(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){b(e,400,{error:"node, agent, task query params required"});return}await Dd(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){b(e,400,{error:"node and agent query params required"});return}await zd(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"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await qd(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){b(e,400,{error:"node query param required"});return}await Jt(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();b(e,200,h)}catch(c){b(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){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(c){b(e,502,{error:c.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await pe(t);try{let m=await Gd(a.config,c);b(e,200,m)}catch(m){b(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(!Hd(t,e,[`agent:${c}`]))return;await Bd(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 Q,x=m?h.verify(m):null;if(!x||!ge(x,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await $d(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"){b(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){b(e,400,{error:"node query param required"});return}await Jt(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
16406
16491
 
16407
16492
  `)}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 E=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:A.signal});if(!E.ok||!E.body)return;let I=E.body.getReader(),j=new TextDecoder,R="";for(;!x.flag;){let{done:B,value:te}=await I.read();if(B)break;R+=j.decode(te,{stream:!0});let z;for(;(z=R.indexOf(`
16408
16493
 
16409
16494
  `))>=0;){let D=R.slice(0,z);if(R=R.slice(z+2),x.flag)break;try{e.write(D+`
16410
16495
 
16411
- `)}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(j=>({url:j.url,token:j.token}))],M=await Promise.all(_.map(async j=>{let R={};j.token&&(R.Authorization=`Bearer ${j.token}`);try{let B=new AbortController,te=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${j.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:R,signal:B.signal});if(!z.ok)return[];let D=await z.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(te)}}catch{return[]}})),A=new Map;for(let j of k)A.set(j.id,j);for(let j of M)for(let R of j)A.set(R.id,R);let E=Array.from(A.values()).sort((j,R)=>j.updatedAt<R.updatedAt?1:-1).slice(0,m),I=x?E.map(j=>fd(j)):E;b(e,200,{runs:I})}catch(c){b(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){b(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){b(e,200,await v.json());return}}catch{}b(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}`}));b(e,h.status,x)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let y=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(y){try{let c=await pe(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(y[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&vr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,h,x)=>{if(a.token)return!0;let k=gt(m);if(!k)return!0;let v=new Q().verify(k);if(!v)return b(h,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!ge(v,_))return b(h,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(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){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];b(e,200,m)}catch(m){b(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){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),S=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){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}let v=await pe(t),_=x.columns.find(A=>A.id===v.to),M=x.columns.find(A=>A.id===v.from);if(!_){b(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await md(k,h,M,_),Ut({actor:Ft(t),action:"move",boardId:c,itemId:h,payload:{from:v.from,to:v.to}}),b(e,200,{ok:!0})}catch(A){b(e,502,{error:A.message||"transition failed"})}return}if(S){let[,c,m]=S,h=m?decodeURIComponent(m):void 0,x=a.boards.find(v=>v.id===c);if(!x){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!h){let{columns:v,totals:_}=await ud(x,k,n.searchParams);b(e,200,{columns:v,totals:_});return}if(o==="GET"&&h){try{let v=typeof k.getItem=="function"?await k.getItem(h):null;if(!v){b(e,404,{error:"not found"});return}b(e,200,v)}catch(v){b(e,502,{error:v.message})}return}if(o==="PATCH"&&h){let v=await pe(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(h,v):null;if(!_){b(e,501,{error:"update unsupported"});return}Ut({actor:Ft(t),action:"update",boardId:c,itemId:h,payload:v}),b(e,200,_)}catch(_){b(e,502,{error:_.message})}return}if(o==="POST"&&!h){let v=await pe(t);if(!v.title){b(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){b(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});Ut({actor:Ft(t),action:"create",boardId:c,itemId:_.id,payload:{title:v.title}}),b(e,201,_)}catch(_){b(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}}b(e,404,{error:"not found",path:r})}async function ud(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"}):[],y=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 y)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=Jt(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 S=Object.fromEntries(Object.entries(w).map(([c,m])=>[c,m.length]));return{columns:w,totals:S}}async function md(t,e,a,n){let r=Vt(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 fd(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 hd(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 ga(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ut(t){try{let e=Pe(process.cwd(),".agentx");Gr(e)||sd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
16412
- `;od(Pe(e,"board-audit.jsonl"),a)}catch{}}function Ft(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function gd(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,y,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,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(S=>({id:S.id,enabled:S.enabled===!0,schedule:String(S.schedule||""),timezone:S.timezone,agent:String(S.agent||""),kind:typeof S.command=="string"&&S.command.trim()?"command":"agent",model:S.model,nextRun:S.nextRun,retryPending:S.retryPending===!0,consecutiveErrors:Number(S.consecutiveErrors)||0}))}if(u&&u.ok){let g=await u.json();o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(y&&y.ok){let g=await y.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,ia.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)&&Ed(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await vd(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var st=null;function xd(t){if(st)return st;let e=Pe(process.cwd(),".agentx/wiki");return st=Da({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),st}var Wt=new WeakMap;async function vd(t){if(Wt.has(t))return Wt.get(t);try{let e=t.ok?await t.json():null;return Wt.set(t,e),e}catch{return null}}async function lt(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 bd(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||se(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){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function he(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=se(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:se(a,l)})}let s=await lt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:se(a,i.url)});return[...o.values()]}var yd=3e3,wd=6e3,kd=5*6e4,Gt=new Map,it=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=it.get(a);if(n)return n;let r=(async()=>{let o=await he(t,AbortSignal.timeout(yd)),s=await Promise.all(o.map(async i=>{let l=await gd(i.url,i.token,AbortSignal.timeout(wd),e);return e?l:_d(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>it.delete(a));return it.set(a,r),r}function _d(t,e,a=Date.now()){if(e.reachable&&!e.error)return Gt.set(t,{node:e,at:a}),e;let n=Gt.get(t);return!n||a-n.at>kd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function zm(){Gt.clear(),it.clear()}function Ed(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 Sd(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}
16496
+ `)}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(j=>({url:j.url,token:j.token}))],M=await Promise.all(_.map(async j=>{let R={};j.token&&(R.Authorization=`Bearer ${j.token}`);try{let B=new AbortController,te=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${j.url.replace(/\/+$/,"")}/api/workflows/runs${v}`,{headers:R,signal:B.signal});if(!z.ok)return[];let D=await z.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(te)}}catch{return[]}})),A=new Map;for(let j of k)A.set(j.id,j);for(let j of M)for(let R of j)A.set(R.id,R);let E=Array.from(A.values()).sort((j,R)=>j.updatedAt<R.updatedAt?1:-1).slice(0,m),I=x?E.map(j=>Td(j)):E;b(e,200,{runs:I})}catch(c){b(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){b(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){b(e,200,await v.json());return}}catch{}b(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}`}));b(e,h.status,x)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let y=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(y){try{let c=await pe(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(y[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),k=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,k)}catch(c){b(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&wr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,h,x)=>{if(a.token)return!0;let k=xt(m);if(!k)return!0;let v=new Q().verify(k);if(!v)return b(h,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!ge(v,_))return b(h,403,{error:`token missing scope: ${_}`,scopes:v.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(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){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];b(e,200,m)}catch(m){b(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){b(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),S=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){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}let v=await pe(t),_=x.columns.find(A=>A.id===v.to),M=x.columns.find(A=>A.id===v.from);if(!_){b(e,400,{error:`unknown 'to' column: ${v.to}`});return}try{await Sd(k,h,M,_),Wt({actor:Gt(t),action:"move",boardId:c,itemId:h,payload:{from:v.from,to:v.to}}),b(e,200,{ok:!0})}catch(A){b(e,502,{error:A.message||"transition failed"})}return}if(S){let[,c,m]=S,h=m?decodeURIComponent(m):void 0,x=a.boards.find(v=>v.id===c);if(!x){b(e,404,{error:`unknown board: ${c}`});return}let k=a.sources.get(c);if(!k){b(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!h){let{columns:v,totals:_}=await Ed(x,k,n.searchParams);b(e,200,{columns:v,totals:_});return}if(o==="GET"&&h){try{let v=typeof k.getItem=="function"?await k.getItem(h):null;if(!v){b(e,404,{error:"not found"});return}b(e,200,v)}catch(v){b(e,502,{error:v.message})}return}if(o==="PATCH"&&h){let v=await pe(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(h,v):null;if(!_){b(e,501,{error:"update unsupported"});return}Wt({actor:Gt(t),action:"update",boardId:c,itemId:h,payload:v}),b(e,200,_)}catch(_){b(e,502,{error:_.message})}return}if(o==="POST"&&!h){let v=await pe(t);if(!v.title){b(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){b(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});Wt({actor:Gt(t),action:"create",boardId:c,itemId:_.id,payload:{title:v.title}}),b(e,201,_)}catch(_){b(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}}b(e,404,{error:"not found",path:r})}async function Ed(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"}):[],y=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 y)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=Yt(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 S=Object.fromEntries(Object.entries(w).map(([c,m])=>[c,m.length]));return{columns:w,totals:S}}async function Sd(t,e,a,n){let r=Qt(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 Td(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 Cd(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 va(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Wt(t){try{let e=Pe(process.cwd(),".agentx");Zr(e)||vd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
16497
+ `;xd(Pe(e,"board-audit.jsonl"),a)}catch{}}function Gt(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function Ad(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,y,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,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(S=>({id:S.id,enabled:S.enabled===!0,schedule:String(S.schedule||""),timezone:S.timezone,agent:String(S.agent||""),kind:typeof S.command=="string"&&S.command.trim()?"command":"agent",model:S.model,nextRun:S.nextRun,retryPending:S.retryPending===!0,consecutiveErrors:Number(S.consecutiveErrors)||0}))}if(u&&u.ok){let g=await u.json();o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(y&&y.ok){let g=await y.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,da.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)&&Od(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d&&await Id(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var it=null;function Md(t){if(it)return it;let e=Pe(process.cwd(),".agentx/wiki");return it=za({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),it}var Xt=new WeakMap;async function Id(t){if(Xt.has(t))return Xt.get(t);try{let e=t.ok?await t.json():null;return Xt.set(t,e),e}catch{return null}}async function dt(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 $d(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||se(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){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function he(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=se(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:se(a,l)})}let s=await dt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:se(a,i.url)});return[...o.values()]}var Ld=3e3,jd=6e3,Rd=5*6e4,Kt=new Map,lt=new Map;function Oe(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=lt.get(a);if(n)return n;let r=(async()=>{let o=await he(t,AbortSignal.timeout(Ld)),s=await Promise.all(o.map(async i=>{let l=await Ad(i.url,i.token,AbortSignal.timeout(jd),e);return e?l:Pd(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>lt.delete(a));return lt.set(a,r),r}function Pd(t,e,a=Date.now()){if(e.reachable&&!e.error)return Kt.set(t,{node:e,at:a}),e;let n=Kt.get(t);return!n||a-n.at>Rd?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function of(){Kt.clear(),lt.clear()}function Od(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 Nd(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}
16413
16498
  data: ${JSON.stringify(d)}
16414
16499
 
16415
- `)},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 Td(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 lt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(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){b(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(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 Cd(t,e,a){let n=gt(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Q().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ge(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Ad(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await pe(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(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){b(e,502,{error:d.message||"upstream call failed"})}}async function Md(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 lt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(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){b(t,502,{error:u.message||"upstream fetch failed"})}}async function Id(t,e,a,n,r,o){await Xt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Xt(t,e,a,n,r){let o={};try{o=await pe(t)??{}}catch{}let s=await Xr(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Xr(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 lt(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=se(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 $d(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=ca(e.keysFile);return{store:()=>{let r=ut();return r?new ka(r):null},publicKey:()=>pa(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Kr(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 Xr(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=He({root:process.cwd()}).items.map(Fr)}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=Oe(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(Fr)}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=we(),p=await Be({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=Oe(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 Ld(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=se(t.dashboard,e),n=Kr(t);return{store:()=>{let r=ut();return r?new ot(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 Fr(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 jd=`
16500
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Oe(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 Dd(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 dt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of w)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(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){b(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(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 Hd(t,e,a){let n=xt(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Q().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ge(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Bd(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await pe(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(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){b(e,502,{error:d.message||"upstream call failed"})}}async function zd(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 dt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=se(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){b(t,502,{error:u.message||"upstream fetch failed"})}}async function qd(t,e,a,n,r,o){await Jt(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Jt(t,e,a,n,r){let o={};try{o=await pe(t)??{}}catch{}let s=await eo(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function eo(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 dt(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=se(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 Ud(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=ua(e.keysFile);return{store:()=>{let r=mt();return r?new Ea(r):null},publicKey:()=>ma(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function to(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Oe(t,n),async nodePost(n,r,o){let s=await eo(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=He({root:process.cwd()}).items.map(Yr)}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=Ne(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(Yr)}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=ke(),p=await Be({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=Ne(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 Fd(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=se(t.dashboard,e),n=to(t);return{store:()=>{let r=mt();return r?new st(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Oe(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 Yr(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 Wd=`
16416
16501
  You are helping draft a new GitLab issue. Follow these conventions strictly.
16417
16502
 
16418
16503
  Title pattern:
@@ -16444,10 +16529,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
16444
16529
  Shape:
16445
16530
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
16446
16531
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
16447
- `;async function Rd(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):
16532
+ `;async function Gd(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):
16448
16533
  - ${r.knownLabels.slice(0,60).join(`
16449
16534
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
16450
- `),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:jd}})});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=Pd(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(y=>typeof y=="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 Pd(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 Nd(t){let e=dd(ld(import.meta.url));return Pe(e,t)}async function Od(t){return id(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function pe(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 Jr(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function N(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:Jr(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 Dd(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await tt(await Vr(r,a.config)))}async function Vr(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Lt(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=Oe(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 Hn(n)}async function Hd(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),y=f.find(w=>Gr(w));if(!y){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",y]}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}
16535
+ `),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:Wd}})});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=Xd(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(y=>typeof y=="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 Xd(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 Kd(t){let e=wd(yd(import.meta.url));return Pe(e,t)}async function Jd(t){return bd(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function pe(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 ao(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:ao(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 Vd(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await tt(await no(r,a.config)))}async function no(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=jt(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=Ne(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 qn(n)}async function Yd(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),y=f.find(w=>Zr(w));if(!y){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",y]}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}
16451
16536
 
16452
16537
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
16453
16538
  `))>=0;){let y=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
@@ -16455,5 +16540,5 @@ data: ${y.replace(/\n/g," ")}
16455
16540
 
16456
16541
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
16457
16542
 
16458
- `)}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 Wr(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 y=[];t.on("data",w=>y.push(w)),t.on("end",()=>u(Buffer.concat(y))),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){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Oe(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Jr(n),token:n.dashboardToken||n.token}:null}export{Ed as applyAttachSessions,pd as handleBoardRequest,zm as resetLiveCaches,he as resolveNodeTargets,Bm as startBoardDashboard,_d as withLastGood};
16459
- //# sourceMappingURL=board-dashboard-A7PQOI6C.js.map
16543
+ `)}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 Qr(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 y=[];t.on("data",w=>y.push(w)),t.on("end",()=>u(Buffer.concat(y))),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){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Ne(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:ao(n),token:n.dashboardToken||n.token}:null}export{Od as applyAttachSessions,_d as handleBoardRequest,of as resetLiveCaches,he as resolveNodeTargets,rf as startBoardDashboard,Pd as withLastGood};
16544
+ //# sourceMappingURL=board-dashboard-BVRRDYAG.js.map