agentix-cli 0.25.0 → 0.26.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 (57) hide show
  1. package/README.md +2 -0
  2. package/dist/{App-6Y7B3YQH.js → App-BPNHIGUX.js} +2 -2
  3. package/dist/{ChatApp-KIEUJ2DS.js → ChatApp-6XSSZB4U.js} +2 -2
  4. package/dist/{agent-QGZIAZMY.js → agent-5QMITZT6.js} +2 -2
  5. package/dist/{board-dashboard-CQ5F4GPD.js → board-dashboard-M3372FLO.js} +1191 -225
  6. package/dist/board-dashboard-M3372FLO.js.map +1 -0
  7. package/dist/{chunk-JXWAGMI2.js → chunk-BTHHSY7D.js} +7 -7
  8. package/dist/chunk-BTHHSY7D.js.map +1 -0
  9. package/dist/{chunk-TRJTTBE2.js → chunk-BVGJSPW4.js} +2 -2
  10. package/dist/{chunk-53GCFZPR.js → chunk-D46VZ7K7.js} +2 -2
  11. package/dist/{chunk-HA3XI7Z2.js → chunk-E5CXCI33.js} +27 -27
  12. package/dist/chunk-E5CXCI33.js.map +1 -0
  13. package/dist/{chunk-FDMWOPEL.js → chunk-K2CAPYES.js} +2 -2
  14. package/dist/{chunk-TMKLHTCG.js → chunk-METYYZKQ.js} +264 -120
  15. package/dist/chunk-METYYZKQ.js.map +1 -0
  16. package/dist/{chunk-Q6YO7LYE.js → chunk-MTAPOCGA.js} +2 -2
  17. package/dist/{chunk-G57RZCXM.js → chunk-O6YPEOQF.js} +2 -2
  18. package/dist/{chunk-KUCCW2VG.js → chunk-UHE5FCPB.js} +8 -8
  19. package/dist/{chunk-LNXCJWOU.js → chunk-V3U4OF7L.js} +2 -2
  20. package/dist/{chunk-NGSIRE4X.js → chunk-VT5XYFDD.js} +2 -2
  21. package/dist/cli.js +1 -1
  22. package/dist/client-HGKAC6VP.js +2 -0
  23. package/dist/{config-7FSZFRTQ.js → config-A4RWEJHV.js} +2 -2
  24. package/dist/config-mutator-MNSFUN7D.js +2 -0
  25. package/dist/doctor-3Q36ZFE6.js +2 -0
  26. package/dist/index.d.ts +58 -1
  27. package/dist/index.js +1 -1
  28. package/dist/{program-WVAVJFND.js → program-SAUNRCCD.js} +2 -2
  29. package/dist/{registry-T36ZIAWV.js → registry-HK3WQ7BS.js} +2 -2
  30. package/dist/scheduler-6T2SU5ST.js +2 -0
  31. package/package.json +1 -1
  32. package/dist/board-dashboard-CQ5F4GPD.js.map +0 -1
  33. package/dist/chunk-HA3XI7Z2.js.map +0 -1
  34. package/dist/chunk-JXWAGMI2.js.map +0 -1
  35. package/dist/chunk-TMKLHTCG.js.map +0 -1
  36. package/dist/client-GGVVLOOF.js +0 -2
  37. package/dist/config-mutator-POCOYYJ4.js +0 -2
  38. package/dist/doctor-DHLBEKA4.js +0 -2
  39. package/dist/scheduler-GH7TIKYS.js +0 -2
  40. /package/dist/{App-6Y7B3YQH.js.map → App-BPNHIGUX.js.map} +0 -0
  41. /package/dist/{ChatApp-KIEUJ2DS.js.map → ChatApp-6XSSZB4U.js.map} +0 -0
  42. /package/dist/{agent-QGZIAZMY.js.map → agent-5QMITZT6.js.map} +0 -0
  43. /package/dist/{chunk-TRJTTBE2.js.map → chunk-BVGJSPW4.js.map} +0 -0
  44. /package/dist/{chunk-53GCFZPR.js.map → chunk-D46VZ7K7.js.map} +0 -0
  45. /package/dist/{chunk-FDMWOPEL.js.map → chunk-K2CAPYES.js.map} +0 -0
  46. /package/dist/{chunk-Q6YO7LYE.js.map → chunk-MTAPOCGA.js.map} +0 -0
  47. /package/dist/{chunk-G57RZCXM.js.map → chunk-O6YPEOQF.js.map} +0 -0
  48. /package/dist/{chunk-KUCCW2VG.js.map → chunk-UHE5FCPB.js.map} +0 -0
  49. /package/dist/{chunk-LNXCJWOU.js.map → chunk-V3U4OF7L.js.map} +0 -0
  50. /package/dist/{chunk-NGSIRE4X.js.map → chunk-VT5XYFDD.js.map} +0 -0
  51. /package/dist/{client-GGVVLOOF.js.map → client-HGKAC6VP.js.map} +0 -0
  52. /package/dist/{config-7FSZFRTQ.js.map → config-A4RWEJHV.js.map} +0 -0
  53. /package/dist/{config-mutator-POCOYYJ4.js.map → config-mutator-MNSFUN7D.js.map} +0 -0
  54. /package/dist/{doctor-DHLBEKA4.js.map → doctor-3Q36ZFE6.js.map} +0 -0
  55. /package/dist/{program-WVAVJFND.js.map → program-SAUNRCCD.js.map} +0 -0
  56. /package/dist/{registry-T36ZIAWV.js.map → registry-HK3WQ7BS.js.map} +0 -0
  57. /package/dist/{scheduler-GH7TIKYS.js.map → scheduler-6T2SU5ST.js.map} +0 -0
@@ -1,7 +1,7 @@
1
- import{a as bt}from"./chunk-H5D7ATXS.js";import{a as S,b as yt,c as wt,d as kt,e as _t,f as Y,g as pe,h as Me,i as St}from"./chunk-LNXCJWOU.js";import{a as Et}from"./chunk-UCQ2N3KO.js";import{a as C,b as L,g as gt,h as ht,i as G,j as K,k as Ee,l as ft,m as xt,n as vt}from"./chunk-P4VWIVKN.js";import{e as ct,g as ie,h as be,i as ye,j as we,k as ke,l as pt,m as ut,n as mt,o as _e}from"./chunk-3WQFCIB6.js";import{a as Qe,e as Ze,f as et,g as tt,s as ve,u as rt,v as ot,w as je,x as st,y as it}from"./chunk-Q6YO7LYE.js";import"./chunk-M4AMWP3H.js";import{a as lt,b as dt}from"./chunk-LDHPMJ7M.js";import"./chunk-AFRHKA7B.js";import"./chunk-53GCFZPR.js";import"./chunk-FDMWOPEL.js";import{a as at,b as nt,f as W}from"./chunk-JXWAGMI2.js";import{a as fe,b as xe}from"./chunk-ISEBLHWX.js";import{b as Ye}from"./chunk-BFXONUUN.js";import"./chunk-JTJIPNXY.js";import"./chunk-64P4QHSZ.js";import"./chunk-FDWOECJY.js";import"./chunk-VJUTQAPJ.js";import"./chunk-QOYAX2FT.js";import"./chunk-4YCH6IZV.js";import{createServer as Ao}from"http";import{appendFileSync as Io,existsSync as La,mkdirSync as $o}from"fs";import{readFile as jo}from"fs/promises";import{fileURLToPath as Mo}from"url";import{dirname as Lo,resolve as he}from"path";var Tt='/*! 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 Se,readFileSync as At,writeFileSync as It,rmSync as is,mkdirSync as qa,copyFileSync as Ua,readdirSync as Fa}from"fs";import{resolve as le}from"path";var V={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 Ct(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=gt({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.`})+ht([{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 C({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ha()+ft,css:Ba,scripts:`${e}<script>${xt}
2
- ${vt}
3
- ${Oa}
4
- ${za}</script>`})}var Oa=`
1
+ import{a as kt}from"./chunk-H5D7ATXS.js";import{a as C,b as _t,c as Et,d as St,e as Tt,f as Z,g as me,h as Oe,i as At}from"./chunk-V3U4OF7L.js";import{a as Ct}from"./chunk-UCQ2N3KO.js";import{a as M,b as D,g as Te,h as Ce,i as X,j as N,k as Ae,l as bt,m as yt,n as wt}from"./chunk-P4VWIVKN.js";import{e as gt,g as de,h as we,i as ke,j as _e,k as Ee,l as ft,m as xt,n as vt,o as Se}from"./chunk-3WQFCIB6.js";import{a as nt,e as rt,f as ot,g as st,s as ye,u as dt,v as ct,w as Pe,x as pt,y as ut}from"./chunk-MTAPOCGA.js";import"./chunk-M4AMWP3H.js";import{a as mt,b as ht}from"./chunk-LDHPMJ7M.js";import"./chunk-AFRHKA7B.js";import"./chunk-D46VZ7K7.js";import"./chunk-K2CAPYES.js";import{a as it,b as lt,f as G}from"./chunk-BTHHSY7D.js";import{a as ve,b as be}from"./chunk-ISEBLHWX.js";import{b as at}from"./chunk-BFXONUUN.js";import"./chunk-JTJIPNXY.js";import"./chunk-64P4QHSZ.js";import"./chunk-FDWOECJY.js";import"./chunk-VJUTQAPJ.js";import"./chunk-QOYAX2FT.js";import"./chunk-4YCH6IZV.js";import{createServer as qo}from"http";import{appendFileSync as Uo,existsSync as Fa,mkdirSync as Fo}from"fs";import{readFile as Wo}from"fs/promises";import{fileURLToPath as Go}from"url";import{dirname as Xo,resolve as xe}from"path";var Mt='/*! 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 Me,readFileSync as $t,writeFileSync as jt,rmSync as ws,mkdirSync as Za,copyFileSync as en,readdirSync as tn}from"fs";import{resolve as ce}from"path";var J={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 It(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Te({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.`})+Ce([{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 M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ja()+bt,css:Ya,scripts:`${e}<script>${yt}
2
+ ${wt}
3
+ ${Ka}
4
+ ${Qa}</script>`})}var Ka=`
5
5
  (function(){
6
6
  function fmt(n) { return n == null ? '\u2014' : String(n); }
7
7
  async function refresh() {
@@ -62,8 +62,8 @@ ${za}</script>`})}var Oa=`
62
62
  refresh();
63
63
  // Refresh again after the main admin script has had a chance to mutate config.
64
64
  document.addEventListener('ax-config-saved', refresh);
65
- })();`;function Ha(){let t=dt().business?`<button data-tab="business">Business</button>
66
- `:"";return Na.replace("__BUSINESS_TABS__",t)}var Na=`
65
+ })();`;function Ja(){let t=ht().business?`<button data-tab="business">Business</button>
66
+ `:"";return Va.replace("__BUSINESS_TABS__",t)}var Va=`
67
67
  <div id="peer-banner" class="peer-banner">
68
68
  <span class="label">Managing</span>
69
69
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -206,8 +206,8 @@ ${za}</script>`})}var Oa=`
206
206
  <div id="global-msg" class="msg"></div>
207
207
 
208
208
  <section id="tab-agents" class="tab active">
209
- ${K({icon:V.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
210
- ${G({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
209
+ ${N({icon:J.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
210
+ ${X({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
211
211
  <div id="agent-list" class="ax-stack"></div>
212
212
  <div class="add-form">
213
213
  <h3>Add a new agent</h3>
@@ -229,8 +229,8 @@ ${za}</script>`})}var Oa=`
229
229
  </section>
230
230
 
231
231
  <section id="tab-channels" class="tab">
232
- ${K({icon:V.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
233
- ${G({persistKey:"channels",bodyHtml:`<b>How does this work?</b> We give each channel a small "bridge" that forwards messages to AgentX. For chat apps (Telegram, Slack, Discord) you'll paste a bot token \u2014 we keep the value in your <code>.env</code> file and never send it over the network. For webhook-style sources (GitHub, GitLab) we hand you a URL to paste into their dashboard.`})}
232
+ ${N({icon:J.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
233
+ ${X({persistKey:"channels",bodyHtml:`<b>How does this work?</b> We give each channel a small "bridge" that forwards messages to AgentX. For chat apps (Telegram, Slack, Discord) you'll paste a bot token \u2014 we keep the value in your <code>.env</code> file and never send it over the network. For webhook-style sources (GitHub, GitLab) we hand you a URL to paste into their dashboard.`})}
234
234
 
235
235
  <details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
236
236
  <summary class="primary">\u2699 Notifications routing</summary>
@@ -259,10 +259,10 @@ ${za}</script>`})}var Oa=`
259
259
  </div>
260
260
  </details>
261
261
 
262
- <div id="ch-chatapps-label">${Ee({label:"Chat apps"})}</div>
262
+ <div id="ch-chatapps-label">${Ae({label:"Chat apps"})}</div>
263
263
  <div class="ax-connectors" id="ch-chatapps"></div>
264
264
 
265
- <div id="ch-devtools-label">${Ee({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
265
+ <div id="ch-devtools-label">${Ae({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
266
266
  <div class="ax-connectors" id="ch-devtools"></div>
267
267
 
268
268
  <!-- Active-channel configuration panes. One shows at a time; clicking
@@ -280,8 +280,8 @@ ${za}</script>`})}var Oa=`
280
280
  </section>
281
281
 
282
282
  <section id="tab-crons" class="tab">
283
- ${K({icon:V.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
284
- ${G({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
283
+ ${N({icon:J.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
284
+ ${X({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
285
285
  <div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
286
286
 
287
287
  <div class="ax-builder">
@@ -378,8 +378,8 @@ ${za}</script>`})}var Oa=`
378
378
  </section>
379
379
 
380
380
  <section id="tab-webhooks" class="tab">
381
- ${K({icon:V.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
382
- ${G({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
381
+ ${N({icon:J.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
382
+ ${X({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
383
383
  <div id="webhook-list" class="ax-stack"></div>
384
384
  <div class="add-form">
385
385
  <h3>Add a webhook</h3>
@@ -398,10 +398,10 @@ ${za}</script>`})}var Oa=`
398
398
  </section>
399
399
 
400
400
  <section id="tab-mesh" class="tab">
401
- ${K({icon:V.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
401
+ ${N({icon:J.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
402
402
  <div id="mesh-hero" class="ax-mesh-hero"></div>
403
- ${G({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
404
- ${Ee({label:"Connected peers"})}
403
+ ${X({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
404
+ ${Ae({label:"Connected peers"})}
405
405
  <div id="mesh-peers" class="ax-stack"></div>
406
406
  <div class="add-form">
407
407
  <h3>Add a peer</h3>
@@ -428,8 +428,8 @@ ${za}</script>`})}var Oa=`
428
428
  </section>
429
429
 
430
430
  <section id="tab-business" class="tab">
431
- ${K({icon:V.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Mirrors <code>agentx business</code>."})}
432
- ${G({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
431
+ ${N({icon:J.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Mirrors <code>agentx business</code>."})}
432
+ ${X({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
433
433
 
434
434
  <div class="ax-stack" style="margin-top:14px">
435
435
  <h3 style="margin:0 0 6px;font-size:13px">Org chart</h3>
@@ -494,8 +494,8 @@ ${za}</script>`})}var Oa=`
494
494
  </section>
495
495
 
496
496
  <section id="tab-boards-cfg" class="tab">
497
- ${K({icon:V.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Mirrors <code>agentx board add/edit/remove</code> + <code>agentx board column</code>. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
498
- ${G({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
497
+ ${N({icon:J.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Mirrors <code>agentx board add/edit/remove</code> + <code>agentx board column</code>. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
498
+ ${X({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
499
499
 
500
500
  <div class="ax-stack" style="margin-top:14px">
501
501
  <h3 style="margin:0 0 6px;font-size:13px">Boards</h3>
@@ -519,8 +519,8 @@ ${za}</script>`})}var Oa=`
519
519
  </section>
520
520
 
521
521
  <section id="tab-actions" class="tab">
522
- ${K({icon:V.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Mirrors <code>agentx actions</code>."})}
523
- ${G({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
522
+ ${N({icon:J.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Mirrors <code>agentx actions</code>."})}
523
+ ${X({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
524
524
 
525
525
  <div class="ax-stack" style="margin-top:14px">
526
526
  <h3 style="margin:0 0 6px;font-size:13px">Registered actions</h3>
@@ -575,8 +575,8 @@ ${za}</script>`})}var Oa=`
575
575
  </section>
576
576
 
577
577
  <section id="tab-tokens" class="tab">
578
- ${K({icon:V.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
579
- ${G({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
578
+ ${N({icon:J.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
579
+ ${X({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
580
580
  <div id="token-list" class="ax-stack"></div>
581
581
  <div class="add-form">
582
582
  <h3>Mint a new token</h3>
@@ -595,8 +595,8 @@ ${za}</script>`})}var Oa=`
595
595
  </section>
596
596
 
597
597
  <section id="tab-advanced" class="tab">
598
- ${K({icon:V.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
599
- ${G({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
598
+ ${N({icon:J.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
599
+ ${X({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
600
600
 
601
601
  <div class="ax-jv-toolbar">
602
602
  <input class="ax-jv-search" id="jv-search" placeholder="Search keys & values\u2026" />
@@ -622,7 +622,7 @@ ${za}</script>`})}var Oa=`
622
622
  <div class="hint-block">The schema is documented at <code>docs/reference/config-schema.md</code>. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
623
623
  </section>
624
624
  </main>
625
- `,Ba=`
625
+ `,Ya=`
626
626
 
627
627
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
628
628
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -830,7 +830,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
830
830
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
831
831
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
832
832
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
833
- `,za=`
833
+ `,Qa=`
834
834
  const $ = (id) => document.getElementById(id);
835
835
  let state = null;
836
836
 
@@ -3501,11 +3501,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
3501
3501
  })();
3502
3502
 
3503
3503
  refresh();
3504
- `;function $t(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ct({peers:a,localToken:n}))}async function jt(t,e){let a=Pe();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Mt(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await rn(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Wa(t),r={"GET /api/admin/state":()=>Ka(),"POST /api/admin/agents":()=>Za(n),"PATCH /api/admin/agents":()=>en(n),"DELETE /api/admin/agents":()=>tn(n),"POST /api/admin/agents/access":()=>Ja(n),"POST /api/admin/channels/telegram":()=>an(n),"DELETE /api/admin/channels/telegram":()=>Cn(n),"POST /api/admin/channels/telegram/toggle":()=>An(n),"POST /api/admin/crons":()=>In(n),"DELETE /api/admin/crons":()=>$n(n),"POST /api/admin/config/raw":()=>jn(n),"GET /api/admin/tokens":()=>Va(),"POST /api/admin/tokens":()=>Xa(n),"DELETE /api/admin/tokens":()=>Ya(n),"POST /api/admin/agents/test":()=>Qa(n),"POST /api/admin/agents/integrations":()=>pn(n),"DELETE /api/admin/agents/integrations":()=>un(n),"PATCH /api/admin/agents/integrations":()=>mn(n),"PATCH /api/admin/channels/telegram":()=>nn(n),"POST /api/admin/channels/slack":()=>yn(n),"POST /api/admin/channels/slack/toggle":()=>wn(n),"POST /api/admin/channels/discord":()=>kn(n),"POST /api/admin/channels/discord/toggle":()=>_n(n),"POST /api/admin/channels/gitlab":()=>En(n),"POST /api/admin/channels/gitlab/toggle":()=>Sn(n),"GET /api/admin/channels/whatsapp/state":()=>ue("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>ue("/webrtc/history"),"POST /api/admin/actions":()=>qn(n),"DELETE /api/admin/actions":()=>Un(n),"POST /api/admin/actions/run":()=>Fn(n),"GET /api/admin/channels/whatsapp/chats":()=>ue("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>ue("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>Q("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Tn(n),"POST /api/admin/webhooks":()=>gn(n),"PATCH /api/admin/webhooks":()=>hn(n),"DELETE /api/admin/webhooks":()=>bn(n),"POST /api/admin/mesh/peers":()=>fn(n),"DELETE /api/admin/mesh/peers":()=>xn(n),"POST /api/admin/mesh/toggle":()=>vn(n),"GET /api/admin/files":()=>on(t),"GET /api/admin/files/read":()=>sn(t),"PUT /api/admin/files":()=>ln(n),"POST /api/admin/files/skill":()=>dn(n),"DELETE /api/admin/files/skill":()=>cn(n),"POST /api/admin/business/orgchart":()=>Mn(n),"DELETE /api/admin/business/orgchart":()=>Ln(n),"POST /api/admin/business/project":()=>Rn(n),"DELETE /api/admin/business/project":()=>Pn(n),"POST /api/admin/business/contact":()=>Dn(n),"DELETE /api/admin/business/contact":()=>On(n),"POST /api/admin/boards":()=>Hn(n),"DELETE /api/admin/boards":()=>Nn(n),"POST /api/admin/boards/columns":()=>Bn(n),"DELETE /api/admin/boards/columns":()=>zn(n),"POST /api/admin/notifications":()=>Gn(n),"POST /api/admin/webhooks/triggers":()=>Kn(n),"POST /api/admin/mesh/health":()=>Wn(n),"GET /api/admin/projects":()=>ue("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>Q("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>Q("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>Q("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>Q("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>Q("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>Q("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>Q("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>Q("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Le(e,404,{error:`unknown admin endpoint: ${o}`});return}let l=await s();Le(e,200,l)}catch(n){Le(e,400,{error:n.message||"admin op failed"})}}function Le(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Wa(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 Ga(t){let e=le(process.cwd(),t);if(!Se(e))return[];let a=[];for(let n of Fa(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(At(le(e,n.name),"utf-8")))}catch{}return a}function Pe(){let t=le(process.cwd(),"agentx.json");return Se(t)?JSON.parse(At(t,"utf-8")):null}function Ka(){let t=Pe();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([p,m])=>({id:p,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(x=>{let v=x.credentials||{},h={};for(let[y,_]of Object.entries(v))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?h[y]=process.env[_]?"set":"unset":typeof _=="string"&&(h[y]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:h,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([p,m])=>({id:p,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},l={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},i=Object.entries(t.crons||{}).map(([p,m])=>({id:p,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),d=Array.isArray(t.webhooks)?t.webhooks.map(p=>({id:p.id,source:p.source,agentId:p.agentId,secretEnv:p.secretEnv||"",description:p.description||"",enabled:p.enabled!==!1,triggers:p.triggers&&typeof p.triggers=="object"?p.triggers:{},defaultWorkflow:p.defaultWorkflow||""})):[],c={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(p=>({url:p.url,name:p.name,hasToken:!!p.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",g=t.business||{},f={enabled:!!g.enabled,timezone:g.timezone||"UTC",orgChart:g.orgChart||{},projects:Array.isArray(g.projects)?g.projects:[],contactMap:Array.isArray(g.contactMap)?g.contactMap:[]},k=t.notifications||{},T={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued}},R=[];try{R=Ga(".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,x)=>m.id.localeCompare(x.id))}catch{}let P=(Array.isArray(t.boards)?t.boards:[]).map(p=>({id:p.id,name:p.name,source:p.source||{type:"gitlab",projects:[]},primaryToolLabel:p.primaryToolLabel||"",timeRangeDays:p.timeRangeDays??30,closedWindowDays:p.closedWindowDays??30,columns:Array.isArray(p.columns)?p.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:l,crons:i,webhooks:d,mesh:c,daemonUrl:u,nodeName:t.node?.name,business:f,boards:P,notifications:T,actions:R}}function Ja(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}=S(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 Va(){return new Y().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 Xa(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 Y().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Ya(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Y().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Qa(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 c=W();r=c.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=c.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let l=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),i=await l.text(),d;try{d=JSON.parse(i)}catch{d={content:i}}if(!l.ok)throw new Error(d?.error||`daemon HTTP ${l.status}`);return{chatId:n,response:d}}function Za(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=Rt(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 l=le(process.cwd(),"agents",e),{summary:i}=S(c=>{if(c.agents=c.agents||{},c.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:l,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),c.agents[e]=u,`added agent "${e}"`}),d=le(l,"CLAUDE.md");if(!Se(d))try{qa(l,{recursive:!0}),It(d,`# ${a}
3504
+ `;function Lt(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(It({peers:a,localToken:n}))}async function Rt(t,e){let a=Be();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Dt(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await fn(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await an(t),r={"GET /api/admin/state":()=>rn(),"POST /api/admin/agents":()=>pn(n),"PATCH /api/admin/agents":()=>un(n),"DELETE /api/admin/agents":()=>mn(n),"POST /api/admin/agents/access":()=>on(n),"POST /api/admin/channels/telegram":()=>hn(n),"DELETE /api/admin/channels/telegram":()=>Hn(n),"POST /api/admin/channels/telegram/toggle":()=>Nn(n),"POST /api/admin/crons":()=>Bn(n),"DELETE /api/admin/crons":()=>zn(n),"POST /api/admin/config/raw":()=>qn(n),"GET /api/admin/tokens":()=>sn(),"POST /api/admin/tokens":()=>ln(n),"DELETE /api/admin/tokens":()=>dn(n),"POST /api/admin/agents/test":()=>cn(n),"POST /api/admin/agents/integrations":()=>kn(n),"DELETE /api/admin/agents/integrations":()=>_n(n),"PATCH /api/admin/agents/integrations":()=>En(n),"PATCH /api/admin/channels/telegram":()=>gn(n),"POST /api/admin/channels/slack":()=>$n(n),"POST /api/admin/channels/slack/toggle":()=>jn(n),"POST /api/admin/channels/discord":()=>Ln(n),"POST /api/admin/channels/discord/toggle":()=>Rn(n),"POST /api/admin/channels/gitlab":()=>Dn(n),"POST /api/admin/channels/gitlab/toggle":()=>Pn(n),"GET /api/admin/channels/whatsapp/state":()=>he("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>he("/webrtc/history"),"POST /api/admin/actions":()=>Zn(n),"DELETE /api/admin/actions":()=>er(n),"POST /api/admin/actions/run":()=>tr(n),"GET /api/admin/channels/whatsapp/chats":()=>he("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>he("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ee("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>On(n),"POST /api/admin/webhooks":()=>Sn(n),"PATCH /api/admin/webhooks":()=>Tn(n),"DELETE /api/admin/webhooks":()=>In(n),"POST /api/admin/mesh/peers":()=>Cn(n),"DELETE /api/admin/mesh/peers":()=>An(n),"POST /api/admin/mesh/toggle":()=>Mn(n),"GET /api/admin/files":()=>xn(t),"GET /api/admin/files/read":()=>vn(t),"PUT /api/admin/files":()=>bn(n),"POST /api/admin/files/skill":()=>yn(n),"DELETE /api/admin/files/skill":()=>wn(n),"POST /api/admin/business/orgchart":()=>Un(n),"DELETE /api/admin/business/orgchart":()=>Fn(n),"POST /api/admin/business/project":()=>Wn(n),"DELETE /api/admin/business/project":()=>Gn(n),"POST /api/admin/business/contact":()=>Xn(n),"DELETE /api/admin/business/contact":()=>Kn(n),"POST /api/admin/boards":()=>Jn(n),"DELETE /api/admin/boards":()=>Vn(n),"POST /api/admin/boards/columns":()=>Yn(n),"DELETE /api/admin/boards/columns":()=>Qn(n),"POST /api/admin/notifications":()=>nr(n),"POST /api/admin/webhooks/triggers":()=>rr(n),"POST /api/admin/mesh/health":()=>ar(n),"GET /api/admin/projects":()=>he("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ee("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ee("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ee("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ee("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ee("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ee("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ee("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ee("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){He(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();He(e,200,i)}catch(n){He(e,400,{error:n.message||"admin op failed"})}}function He(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function an(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 nn(t){let e=ce(process.cwd(),t);if(!Me(e))return[];let a=[];for(let n of tn(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse($t(ce(e,n.name),"utf-8")))}catch{}return a}function Be(){let t=ce(process.cwd(),"agentx.json");return Me(t)?JSON.parse($t(t,"utf-8")):null}function rn(){let t=Be();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(g=>{let x=g.credentials||{},h={};for(let[b,_]of Object.entries(x))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?h[b]=process.env[_]?"set":"unset":typeof _=="string"&&(h[b]="literal");return{kind:g.kind,label:g.label,enabled:g.enabled!==!1,credentials:x,credStatus:h,metadata:g.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||{},v={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[]},k=t.notifications||{},A={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued}},E=[];try{E=nn(".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,g)=>m.id.localeCompare(g.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:v,boards:S,notifications:A,actions:E}}function on(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 sn(){return new Z().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function ln(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new Z().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function dn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new Z().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function cn(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=G();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 pn(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=Ot(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=ce(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=ce(i,"CLAUDE.md");if(!Me(d))try{Za(i,{recursive:!0}),jt(d,`# ${a}
3505
3505
 
3506
3506
  ${s||"You are "+a+"."}
3507
- `)}catch{}return{summary:i}}function en(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=S(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=Rt(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 tn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=S(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 an(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}=S(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 nn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=S(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 ue(t){let{url:e,headers:a}=De(),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 Q(t,e){let{url:a,headers:n}=De(),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 rn(t,e){try{let{url:a,headers:n}=De(),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 De(){let t="http://127.0.0.1:18800",e={};try{let a=W();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function me(t){let a=Pe()?.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 Re(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function on(t){let e=Re(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ie(me(e));return{agentId:e,...a}}function sn(t){let e=Re(t,"agent").trim(),a=Re(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return be(me(e),a)}function ln(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=ye(me(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function dn(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=we(me(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function cn(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=ke(me(e),a);return{summary:`removed skill "${a}"`,...n}}function pn(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 i of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let d=o[i];if(typeof d=="string"&&d.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(d.trim()))throw new Error(`${i} must be uppercase identifier (got "${d}")`);r[i]=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[i,d]of Object.entries(t?.metadata||{}))(typeof d=="string"||typeof d=="number"||typeof d=="boolean")&&(s[i]=d);let{summary:l}=S(i=>{if(!i.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(i.agents[e].integrations=Array.isArray(i.agents[e].integrations)?i.agents[e].integrations:[],i.agents[e].integrations.find(d=>d.kind===a&&d.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return i.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:l}}function un(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}=S(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let l=s.integrations||[],i=l.findIndex(d=>d.kind===a&&d.label===n);if(i===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return l.splice(i,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function mn(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}=S(s=>{let l=s.agents?.[e];if(!l)throw new Error(`Unknown agent "${e}"`);let d=(l.integrations||[]).find(c=>c.kind===a&&c.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 Lt=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function gn(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(!Lt.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:l}=S(i=>{if(s){if(!(i.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(!i.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(i.webhooks=Array.isArray(i.webhooks)?i.webhooks:[],i.webhooks.find(c=>c.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),i.webhooks.push(d),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:l}}function hn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=S(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Lt.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 fn(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}=S(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(l=>l.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 xn(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=S(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 vn(t){let e=!!t?.enabled,{summary:a}=S(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 bn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=S(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 yn(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}=S(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 wn(t){let e=!!t?.enabled,{summary:a}=S(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 kn(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}=S(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 _n(t){let e=!!t?.enabled,{summary:a}=S(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 En(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}=S(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 Sn(t){let e=!!t?.enabled,{summary:a}=S(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 Tn(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-GH7TIKYS.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(l){throw new Error(`Invalid cron: ${l.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let l=0;l<3;l++)s=a(e,s,r),o.push(s.toISOString())}catch(l){throw new Error(`Cron preview failed: ${l.message}`)}return{human:n,next:o,timezone:r}}function Cn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=S(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 An(t){let e=!!t?.enabled,{summary:a}=S(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 In(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}=S(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 $n(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=S(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function jn(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=le(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Se(n))try{Ua(n,r)}catch{}It(n,JSON.stringify(a,null,2)+`
3508
- `,"utf-8");try{let s=W().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 Rt(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Mn(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():"",l=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:i}=S(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:l},`orgChart "${e}" upserted`));return{summary:i}}async function Ln(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=S(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 Rn(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}=S(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(i=>i.id===e),l={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...l}:o.business.projects.push(l),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function Pn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=S(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 Dn(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}=S(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 On(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}=S(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(l=>{for(let i of a)if(l[i]!==t[i])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 Hn(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(i=>i.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:l}=S(i=>{i.boards=Array.isArray(i.boards)?i.boards:[];let d=i.boards.findIndex(u=>u.id===e),c={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(c.primaryToolLabel=r),d>=0){let u=i.boards[d];return i.boards[d]={...u,...c,columns:u.columns,labels:u.labels},`board "${e}" updated`}return i.boards.push(c),`board "${e}" added`});return{summary:l}}async function Nn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=S(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 Bn(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}=S(s=>{let i=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!i)throw new Error(`board "${e}" not found`);i.columns=Array.isArray(i.columns)?i.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 c=i.columns.findIndex(u=>u.id===a);return c>=0?(i.columns[c]={...i.columns[c],...d},`column "${a}" updated`):(i.columns.push(d),`column "${a}" added to board "${e}"`)});return{summary:o}}async function zn(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}=S(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(i=>i.id===e);if(!s)throw new Error(`board "${e}" not found`);let l=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(i=>i.id!==a),s.columns.length===l)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function qn(t){let{ActionStore:e}=await import("./store-I3HEWVLQ.js"),{actionSchema:a}=await import("./types-Y6ZCZ52Z.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 Un(t){let{ActionStore:e}=await import("./store-I3HEWVLQ.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 Fn(t){let{ActionStore:e}=await import("./store-I3HEWVLQ.js"),{runAction:a}=await import("./runner-BFYDWPUO.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 Wn(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}=S(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 Gn(t){let{summary:e}=S(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`)}}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function Kn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=S(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[l,i]of Object.entries(t.triggers))typeof i=="string"&&i.trim()&&(s[String(l)]=i.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}}import{resolve as Xn}from"path";function Pt(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
3507
+ `)}catch{}return{summary:l}}function un(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=Ot(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 mn(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 hn(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 gn(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 he(t){let{url:e,headers:a}=ze(),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 ee(t,e){let{url:a,headers:n}=ze(),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 fn(t,e){try{let{url:a,headers:n}=ze(),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 ze(){let t="http://127.0.0.1:18800",e={};try{let a=G();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ge(t){let a=Be()?.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 Ne(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function xn(t){let e=Ne(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=de(ge(e));return{agentId:e,...a}}function vn(t){let e=Ne(t,"agent").trim(),a=Ne(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return we(ge(e),a)}function bn(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=ke(ge(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function yn(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=_e(ge(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function wn(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=Ee(ge(e),a);return{summary:`removed skill "${a}"`,...n}}function kn(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 _n(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 En(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 Pt=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Sn(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(!Pt.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 Tn(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"&&Pt.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 Cn(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 An(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 Mn(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 In(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 $n(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 jn(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 Ln(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 Rn(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 Dn(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 Pn(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 On(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-6T2SU5ST.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 Hn(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 Nn(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 Bn(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 zn(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 qn(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=ce(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Me(n))try{en(n,r)}catch{}jt(n,JSON.stringify(a,null,2)+`
3508
+ `,"utf-8");try{let s=G().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 Ot(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function Un(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 Fn(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 Wn(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 Gn(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 Xn(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 Kn(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 Jn(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 Vn(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 Yn(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 Qn(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 Zn(t){let{ActionStore:e}=await import("./store-I3HEWVLQ.js"),{actionSchema:a}=await import("./types-Y6ZCZ52Z.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 er(t){let{ActionStore:e}=await import("./store-I3HEWVLQ.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 tr(t){let{ActionStore:e}=await import("./store-I3HEWVLQ.js"),{runAction:a}=await import("./runner-BFYDWPUO.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 ar(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 nr(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`)}}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function rr(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}}import{resolve as ir}from"path";function Ht(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
3509
3509
 
3510
3510
  <div id="disabled-banner" class="banner warn" style="display:none">
3511
3511
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -3560,7 +3560,7 @@ ${s||"You are "+a+"."}
3560
3560
  <h2>Recent classifications</h2>
3561
3561
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
3562
3562
  <div id="recent"></div>
3563
- </section>`;return C({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Jn,scripts:`${e}<script>${Vn}</script>`})}var Jn=`
3563
+ </section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:or,scripts:`${e}<script>${sr}</script>`})}var or=`
3564
3564
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
3565
3565
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
3566
3566
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -3664,7 +3664,7 @@ details {
3664
3664
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
3665
3665
  }
3666
3666
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
3667
- details[open] summary { margin-bottom: 8px; }`,Vn=`
3667
+ details[open] summary { margin-bottom: 8px; }`,sr=`
3668
3668
  const $ = (id) => document.getElementById(id);
3669
3669
  const state = { schema: null, nodes: [], pending: [], recent: [] };
3670
3670
 
@@ -3884,7 +3884,7 @@ $('btn-save-schema').addEventListener('click', async () => {
3884
3884
  $('btn-reload-schema').addEventListener('click', refresh);
3885
3885
 
3886
3886
  refresh();
3887
- `;function Ot(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pt({peers:a,localToken:n}))}async function Ht(t,e,a){try{let n=t.method==="GET"?void 0:await or(t),r=Yn(),o={"GET /api/admin/graph/state":()=>Qn(r),"POST /api/admin/graph/classifications/approve":()=>Zn(r,n),"POST /api/admin/graph/classifications/reject":()=>er(r,n),"POST /api/admin/graph/nodes":()=>tr(r,n),"PATCH /api/admin/graph/nodes":()=>ar(r,n),"DELETE /api/admin/graph/nodes":()=>nr(r,n),"PUT /api/admin/graph/schema":()=>rr(r,n)},s=`${t.method} ${a}`,l=o[s];if(!l){Oe(e,404,{error:`unknown graph endpoint: ${s}`});return}let i=await l();Oe(e,200,i)}catch(n){Oe(e,400,{error:n?.message||"graph op failed"})}}function Yn(){let t=W(),e=Xn(process.cwd(),t.graph.baseDir);return new Ye({baseDir:e})}function Qn(t){let e=W(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let i of r)s.has(i.msgHash)||s.set(i.msgHash,i);let l=[];for(let i of s.values())i.status==="pending"&&!o[i.msgHash]&&l.push(i);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:l,recent:r.slice(0,25),counts:{nodes:n.length,pending:l.length,fingerprints:Object.keys(o).length}}}function Zn(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Nt(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=He(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function er(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=Nt(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function Nt(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 tr(t,e){let a=Dt(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Dt(String(e.parentId)):null,o=He({[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 ar(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=He({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function nr(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function rr(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 He(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 Dt(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Oe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function or(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)})}import{resolve as lr}from"path";import{existsSync as dr}from"fs";import cr from"better-sqlite3";function Bt(t={}){let e=`<div class="ax-obs">
3887
+ `;function Bt(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ht({peers:a,localToken:n}))}async function zt(t,e,a){try{let n=t.method==="GET"?void 0:await fr(t),r=lr(),o={"GET /api/admin/graph/state":()=>dr(r),"POST /api/admin/graph/classifications/approve":()=>cr(r,n),"POST /api/admin/graph/classifications/reject":()=>pr(r,n),"POST /api/admin/graph/nodes":()=>ur(r,n),"PATCH /api/admin/graph/nodes":()=>mr(r,n),"DELETE /api/admin/graph/nodes":()=>hr(r,n),"PUT /api/admin/graph/schema":()=>gr(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){qe(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();qe(e,200,l)}catch(n){qe(e,400,{error:n?.message||"graph op failed"})}}function lr(){let t=G(),e=ir(process.cwd(),t.graph.baseDir);return new at({baseDir:e})}function dr(t){let e=G(),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 cr(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=qt(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=Ue(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function pr(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=qt(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function qt(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 ur(t,e){let a=Nt(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Nt(String(e.parentId)):null,o=Ue({[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 mr(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ue({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function hr(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function gr(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 Ue(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 Nt(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function qe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function fr(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)})}import{resolve as br}from"path";import{existsSync as yr}from"fs";import wr from"better-sqlite3";function Ut(t={}){let e=`<div class="ax-obs">
3888
3888
  <header class="ax-obs__head">
3889
3889
  <h1>Health</h1>
3890
3890
  <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>
@@ -4006,7 +4006,7 @@ refresh();
4006
4006
  </div>
4007
4007
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
4008
4008
  </section>
4009
- </div>`;return C({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:sr,scripts:`<script>${ir}</script>`})}var sr=`
4009
+ </div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:xr,scripts:`<script>${vr}</script>`})}var xr=`
4010
4010
  .ax-obs { padding: 16px 24px; }
4011
4011
  .ax-obs__head { margin-bottom: 16px; }
4012
4012
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -4123,7 +4123,7 @@ refresh();
4123
4123
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
4124
4124
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
4125
4125
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
4126
- `,ir=`
4126
+ `,vr=`
4127
4127
  (function(){
4128
4128
  var panes = document.querySelectorAll('.ax-obs__pane');
4129
4129
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -4507,23 +4507,23 @@ refresh();
4507
4507
 
4508
4508
  load(current);
4509
4509
  })();
4510
- `;var Ut={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 Ft(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Ne(t){let e=Ut[Ft(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 pr(){let t=lr(process.cwd(),".agentx/db.sqlite");if(!dr(t))return null;try{let e=new cr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Wt(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bt({peers:a}))}function ur(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 Z(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Gt(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=pr();if(!r)return Z(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ur(t);if(n==="routing"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let d=`
4510
+ `;var Gt={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 Xt(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Fe(t){let e=Gt[Xt(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 kr(){let t=br(process.cwd(),".agentx/db.sqlite");if(!yr(t))return null;try{let e=new wr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function Kt(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ut({peers:a}))}function _r(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 te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Jt(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=kr();if(!r)return te(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=_r(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
4511
4511
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
4512
4512
  FROM route_traces
4513
- ${l.length?"WHERE "+l.join(" AND "):""}
4513
+ ${i.length?"WHERE "+i.join(" AND "):""}
4514
4514
  ORDER BY at DESC LIMIT @limit
4515
- `,c=r.db.prepare(d).all(i);return Z(e,200,{rows:c}),!0}if(n==="rotations"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let d=`
4515
+ `,p=r.db.prepare(d).all(l);return te(e,200,{rows:p}),!0}if(n==="rotations"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
4516
4516
  SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
4517
4517
  FROM rotations
4518
- ${l.length?"WHERE "+l.join(" AND "):""}
4518
+ ${i.length?"WHERE "+i.join(" AND "):""}
4519
4519
  ORDER BY rotated_at DESC LIMIT @limit
4520
- `,c=r.db.prepare(d).all(i);return Z(e,200,{rows:c}),!0}if(n==="errors"){let l=["status = 'error'"],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let d=`
4520
+ `,p=r.db.prepare(d).all(l);return te(e,200,{rows:p}),!0}if(n==="errors"){let i=["status = 'error'"],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let d=`
4521
4521
  SELECT started_at, agent_id, channel, message_preview, error
4522
4522
  FROM task_history
4523
- WHERE ${l.join(" AND ")}
4523
+ WHERE ${i.join(" AND ")}
4524
4524
  ORDER BY started_at DESC LIMIT @limit
4525
- `,u=r.db.prepare(d).all(i).map(g=>({...g,plain:Kt(g.error)}));return Z(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return Z(e,200,mr(r.db)),!0;if(n==="activity")return Z(e,200,gr(r.db,{agent:s})),!0;if(n==="cost"){let l=new URL(t.url||"/","http://_"),i=zt(l.searchParams.get("range"));return Z(e,200,qt(r.db,i)),!0}if(n==="cost.csv"){let l=new URL(t.url||"/","http://_"),i=zt(l.searchParams.get("range")),d=qt(r.db,i),c=hr(d.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${i||"all"}d-${Date.now()}.csv"`}),e.end(c),!0}return Z(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return Z(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Kt(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(`
4526
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function mr(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,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,i=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,c=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=_=>c.length?c[Math.min(c.length-1,Math.floor(c.length*_))].duration_ms:0,g=u(.5),f=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,$)=>_+Ne($),0),R=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,$)=>_+Ne($),0),P=t.prepare(`
4525
+ `,u=r.db.prepare(d).all(l).map(f=>({...f,plain:Vt(f.error)}));return te(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return te(e,200,Er(r.db)),!0;if(n==="activity")return te(e,200,Sr(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Ft(i.searchParams.get("range"));return te(e,200,Wt(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Ft(i.searchParams.get("range")),d=Wt(r.db,l),p=Tr(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 te(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return te(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Vt(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(`
4526
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Er(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),v=u(.95),A=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,j)=>_+Fe(j),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,j)=>_+Fe(j),0),S=t.prepare(`
4527
4527
  SELECT agent_id,
4528
4528
  COUNT(*) AS tasks,
4529
4529
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -4533,7 +4533,7 @@ refresh();
4533
4533
  WHERE started_at >= ?
4534
4534
  GROUP BY agent_id
4535
4535
  ORDER BY tasks DESC LIMIT 10
4536
- `).all(a),p=t.prepare(`
4536
+ `).all(a),c=t.prepare(`
4537
4537
  SELECT COALESCE(channel, 'unknown') AS channel,
4538
4538
  COUNT(*) AS tasks,
4539
4539
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -4541,12 +4541,12 @@ refresh();
4541
4541
  WHERE started_at >= ?
4542
4542
  GROUP BY channel
4543
4543
  ORDER BY tasks DESC
4544
- `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),x=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),v=m.filter(_=>!x.has(_)),y=t.prepare(`
4544
+ `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),g=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),x=m.filter(_=>!g.has(_)),b=t.prepare(`
4545
4545
  SELECT started_at, agent_id, channel, message_preview, error
4546
4546
  FROM task_history
4547
4547
  WHERE status='error' AND started_at >= ?
4548
4548
  ORDER BY started_at DESC LIMIT 5
4549
- `).all(o).map(_=>({..._,plain:Kt(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-l,errorsToday:i,errorRate:s>0?i/s:0,avgDurationMs:Math.round(d),p50DurationMs:g,p95DurationMs:f,spendToday:T,spendDelta:T-R,idleAgentCount:v.length},perAgent:P,perChannel:p,idleAgents:v,recentErrors:y}}function gr(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(`
4549
+ `).all(o).map(_=>({..._,plain:Vt(_.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(d),p50DurationMs:f,p95DurationMs:v,spendToday:A,spendDelta:A-E,idleAgentCount:x.length},perAgent:S,perChannel:c,idleAgents:x,recentErrors:b}}function Sr(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(`
4550
4550
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
4551
4551
  COUNT(*) AS tasks,
4552
4552
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -4554,7 +4554,7 @@ refresh();
4554
4554
  WHERE started_at >= @since ${r}
4555
4555
  GROUP BY hour
4556
4556
  ORDER BY hour
4557
- `).all({since:a,...o}),l=t.prepare(`
4557
+ `).all({since:a,...o}),i=t.prepare(`
4558
4558
  SELECT date(started_at) AS day,
4559
4559
  COUNT(*) AS tasks,
4560
4560
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -4562,7 +4562,7 @@ refresh();
4562
4562
  WHERE started_at >= @since ${r}
4563
4563
  GROUP BY day
4564
4564
  ORDER BY day
4565
- `).all({since:n,...o}),i=t.prepare(`
4565
+ `).all({since:n,...o}),l=t.prepare(`
4566
4566
  SELECT agent_id,
4567
4567
  COUNT(*) AS tasks_7d,
4568
4568
  SUM(CASE WHEN started_at >= @last24 THEN 1 ELSE 0 END) AS tasks_24h,
@@ -4573,7 +4573,7 @@ refresh();
4573
4573
  WHERE started_at >= @since
4574
4574
  GROUP BY agent_id
4575
4575
  ORDER BY tasks_24h DESC, tasks_7d DESC
4576
- `).all({since:n,last24:a});return{hourly:s,daily:l,perAgent:i}}function zt(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 qt(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
4576
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Ft(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 Wt(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
4577
4577
  SELECT day, agent_id, model,
4578
4578
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
4579
4579
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -4581,20 +4581,20 @@ refresh();
4581
4581
  FROM usage_daily
4582
4582
  ${a}
4583
4583
  ORDER BY day
4584
- `).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),l=new Date(Date.now()-14*864e5).toISOString().slice(0,10),i=0,d=0,c=0,u=0,g=0,f=0,k=0,T=0,R=0,P={},p={};for(let b of n){let A=Ne(b),j=Ft(b.model),D=Ut[j],O=(b.tier2_input_tokens||0)/1e6*D.input*.5+(b.tier2_output_tokens||0)/1e6*D.output*.5+(b.tier2_cache_read_tokens||0)/1e6*D.cacheRead*.5+(b.tier2_cache_create_tokens||0)/1e6*D.cacheCreate*.5,X=(b.input_tokens||0)+(b.tier2_input_tokens||0),M=(b.output_tokens||0)+(b.tier2_output_tokens||0),J=(b.cache_read_tokens||0)+(b.tier2_cache_read_tokens||0),te=(b.cache_create_tokens||0)+(b.tier2_cache_create_tokens||0);u+=A,b.day>=s&&(c+=A,k+=b.tasks||0),b.day>=l&&b.day<s&&(R+=A,T+=b.tasks||0),b.day===r&&(i+=A),b.day===o&&(d+=A),b.day===r&&(g+=O),b.day>=s&&(f+=O);let z=P[b.day]||(P[b.day]={date:b.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});z.tasks+=b.tasks||0,z.input+=X,z.output+=M,z.cacheRead+=J,z.cacheCreate+=te,z.cost+=A,z.tier2+=O;let F=z.agents[b.agent_id]||(z.agents[b.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:b.model});F.tasks+=b.tasks||0,F.cost+=A,F.tier2+=O,F.input+=X,F.output+=M,F.cacheRead+=J,F.cacheCreate+=te,b.model&&(F.model=b.model);let q=p[b.agent_id]||(p[b.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:b.model});q.tasks+=b.tasks||0,q.cost+=A,q.tier2+=O,q.input+=X,q.output+=M,q.cacheRead+=J,q.cacheCreate+=te,b.model&&(q.model=b.model)}let m=Object.values(P).sort((b,A)=>b.date<A.date?-1:1),x=0,v=0,h=0,y=0,_=0,$=0;for(let b of m)x+=b.tasks,v+=b.input,h+=b.output,y+=b.cacheRead,_+=b.cacheCreate,$+=b.cost;let I=Object.entries(p).map(([b,A])=>({agent_id:b,...A,tokens:A.input+A.output+A.cacheRead+A.cacheCreate})).sort((b,A)=>A.cost-b.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:i,spendYesterday:d,spend7d:c,spend30d:u,tier2Today:g,tier2_7d:f,tier2PctToday:i>0?g/i:0,spendRange:$,avgDailyRange:m.length?$/m.length:0,tasksRange:x,tokensRange:v+h+y+_,cacheHitRange:y+v>0?y/(y+v):0,costPerTaskRange:x>0?$/x:0,spendDeltaWoW:R>0?(c-R)/R:0,tasksDeltaWoW:T>0?(k-T)/T:0},days:m,perAgent:I}}function hr(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+`
4584
+ `).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,v=0,k=0,A=0,E=0,S={},c={};for(let w of n){let I=Fe(w),L=Xt(w.model),P=Gt[L],O=(w.tier2_input_tokens||0)/1e6*P.input*.5+(w.tier2_output_tokens||0)/1e6*P.output*.5+(w.tier2_cache_read_tokens||0)/1e6*P.cacheRead*.5+(w.tier2_cache_create_tokens||0)/1e6*P.cacheCreate*.5,Q=(w.input_tokens||0)+(w.tier2_input_tokens||0),R=(w.output_tokens||0)+(w.tier2_output_tokens||0),K=(w.cache_read_tokens||0)+(w.tier2_cache_read_tokens||0),ne=(w.cache_create_tokens||0)+(w.tier2_cache_create_tokens||0);u+=I,w.day>=s&&(p+=I,k+=w.tasks||0),w.day>=i&&w.day<s&&(E+=I,A+=w.tasks||0),w.day===r&&(l+=I),w.day===o&&(d+=I),w.day===r&&(f+=O),w.day>=s&&(v+=O);let q=S[w.day]||(S[w.day]={date:w.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});q.tasks+=w.tasks||0,q.input+=Q,q.output+=R,q.cacheRead+=K,q.cacheCreate+=ne,q.cost+=I,q.tier2+=O;let W=q.agents[w.agent_id]||(q.agents[w.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:w.model});W.tasks+=w.tasks||0,W.cost+=I,W.tier2+=O,W.input+=Q,W.output+=R,W.cacheRead+=K,W.cacheCreate+=ne,w.model&&(W.model=w.model);let U=c[w.agent_id]||(c[w.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:w.model});U.tasks+=w.tasks||0,U.cost+=I,U.tier2+=O,U.input+=Q,U.output+=R,U.cacheRead+=K,U.cacheCreate+=ne,w.model&&(U.model=w.model)}let m=Object.values(S).sort((w,I)=>w.date<I.date?-1:1),g=0,x=0,h=0,b=0,_=0,j=0;for(let w of m)g+=w.tasks,x+=w.input,h+=w.output,b+=w.cacheRead,_+=w.cacheCreate,j+=w.cost;let $=Object.entries(c).map(([w,I])=>({agent_id:w,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((w,I)=>I.cost-w.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:d,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:v,tier2PctToday:l>0?f/l:0,spendRange:j,avgDailyRange:m.length?j/m.length:0,tasksRange:g,tokensRange:x+h+b+_,cacheHitRange:b+x>0?b/(b+x):0,costPerTaskRange:g>0?j/g:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:A>0?(k-A)/A:0},days:m,perAgent:$}}function Tr(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+`
4585
4585
  `+a.join(`
4586
4586
  `)+`
4587
- `}import{resolve as fr}from"path";import{existsSync as xr}from"fs";import vr from"better-sqlite3";function br(){let t=fr(process.cwd(),".agentx/intent/ledger.sqlite");if(!xr(t))return null;try{let e=new vr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Jt>6e4&&(Jt=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Jt=0;function re(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function yr(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 Vt(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=br();if(!r)return re(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=yr(o.searchParams.get("since")),l=o.searchParams.get("source")||"",i=o.searchParams.get("project")||"",d=parseInt(o.searchParams.get("limit")||"50",10),c=Number.isFinite(d)?Math.max(1,Math.min(500,d)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",g=s!==void 0?"WHERE decided_at >= @since":"",f=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${g}`).get({since:s}).n,T=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${g} GROUP BY outcome ORDER BY n DESC`).all({since:s}),R=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,P=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),p=r.db.prepare(`
4587
+ `}import{resolve as Cr}from"path";import{existsSync as Ar}from"fs";import Mr from"better-sqlite3";function Ir(){let t=Cr(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ar(t))return null;try{let e=new Mr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Yt>6e4&&(Yt=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Yt=0;function se(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $r(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 Qt(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Ir();if(!r)return se(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=$r(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":"",v=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,A=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,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(`
4588
4588
  SELECT COUNT(*) AS n FROM intent_decisions d
4589
4589
  LEFT JOIN intent_resolutions r
4590
4590
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
4591
4591
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
4592
- `).get().n;return re(e,200,{since:s??null,eventsBySource:f,totalDecisions:k,decisionsByOutcome:T,totalDivergences:R,divergencesBySource:P,inFlight:p}),!0}if(n==="events"){let u=[],g={limit:c};s!==void 0&&(u.push("ts >= @since"),g.since=s),l&&(u.push("source = @source"),g.source=l),i&&(u.push("project = @project"),g.project=i);let f=`
4592
+ `).get().n;return se(e,200,{since:s??null,eventsBySource:v,totalDecisions:k,decisionsByOutcome:A,totalDivergences:E,divergencesBySource:S,inFlight:c}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let v=`
4593
4593
  SELECT id, ts, source, source_event_id, project, subject, intent
4594
4594
  FROM intent_events
4595
4595
  ${u.length?"WHERE "+u.join(" AND "):""}
4596
4596
  ORDER BY ts DESC LIMIT @limit
4597
- `;return re(e,200,{rows:r.db.prepare(f).all(g)}),!0}if(n==="divergences"){let u=[],g={limit:c};s!==void 0&&(u.push("ts >= @since"),g.since=s),l&&(u.push("source = @source"),g.source=l);let f=`
4597
+ `;return se(e,200,{rows:r.db.prepare(v).all(f)}),!0}if(n==="divergences"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i);let v=`
4598
4598
  SELECT ts, source, decided_by,
4599
4599
  legacy_agent_id, legacy_outcome, legacy_reason,
4600
4600
  ledger_agent_id, ledger_outcome, ledger_reason,
@@ -4602,7 +4602,7 @@ refresh();
4602
4602
  FROM intent_divergences
4603
4603
  ${u.length?"WHERE "+u.join(" AND "):""}
4604
4604
  ORDER BY ts DESC LIMIT @limit
4605
- `;return re(e,200,{rows:r.db.prepare(f).all(g)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],g={limit:c};l&&(u.push("e.source = @source"),g.source=l);let f=`
4605
+ `;return se(e,200,{rows:r.db.prepare(v).all(f)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],f={limit:p};i&&(u.push("e.source = @source"),f.source=i);let v=`
4606
4606
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
4607
4607
  d.decided_by, d.decided_at, d.agent_id, d.reason
4608
4608
  FROM intent_decisions d
@@ -4611,7 +4611,7 @@ refresh();
4611
4611
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
4612
4612
  WHERE ${u.join(" AND ")}
4613
4613
  ORDER BY d.decided_at DESC LIMIT @limit
4614
- `;return re(e,200,{rows:r.db.prepare(f).all(g)}),!0}return re(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return re(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Xt(t={}){return C({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
4614
+ `;return se(e,200,{rows:r.db.prepare(v).all(f)}),!0}return se(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return se(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Zt(t={}){return M({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
4615
4615
  <header class="ax-led__head">
4616
4616
  <h1>Intent ledger</h1>
4617
4617
  <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>
@@ -4816,7 +4816,7 @@ refresh();
4816
4816
  }
4817
4817
  load();
4818
4818
  })();
4819
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Yt(t={}){return C({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
4819
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function ea(t={}){return M({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
4820
4820
  <header class="ax-cost__head">
4821
4821
  <div>
4822
4822
  <h1>Cost</h1>
@@ -5389,7 +5389,7 @@ refresh();
5389
5389
  load();
5390
5390
  setInterval(load, 30000);
5391
5391
  })();
5392
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Qt(t={}){let e=`<div class="ax-pj__root">
5392
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function ta(t={}){let e=`<div class="ax-pj__root">
5393
5393
  <aside class="ax-pj__list">
5394
5394
  <header>
5395
5395
  <h2>Projects</h2>
@@ -5416,7 +5416,7 @@ refresh();
5416
5416
  </header>
5417
5417
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
5418
5418
  </section>
5419
- </div>`;return C({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:wr,scripts:`<script>${kr}</script>`})}var wr=`
5419
+ </div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:jr,scripts:`<script>${Lr}</script>`})}var jr=`
5420
5420
  .ax-pj__root {
5421
5421
  display: grid;
5422
5422
  grid-template-columns: 360px 1fr;
@@ -5603,7 +5603,7 @@ refresh();
5603
5603
  }
5604
5604
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
5605
5605
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-fg)); margin-top: 4px; }
5606
- `,kr=`
5606
+ `,Lr=`
5607
5607
  (function(){
5608
5608
  const $ = (sel) => document.querySelector(sel);
5609
5609
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -6253,7 +6253,7 @@ refresh();
6253
6253
  load();
6254
6254
  });
6255
6255
  })();
6256
- `;import{resolve as ze,join as Er}from"path";import{existsSync as qe,readdirSync as Sr,readFileSync as Tr}from"fs";import Cr from"better-sqlite3";function Zt(t={}){let e='<div id="ax-fleet-root"></div>';return C({title:"AgentX \xB7 Activity Graph",activeTab:"graph",subtitle:"Activity Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:_r,scripts:'<script src="/assets/activity-graph.global.js" defer></script>',noMain:!0})}var _r=`
6256
+ `;import{resolve as Ge,join as Dr}from"path";import{existsSync as Xe,readdirSync as Pr,readFileSync as Or}from"fs";import Hr from"better-sqlite3";function aa(t={}){let e='<div id="ax-fleet-root"></div>';return M({title:"AgentX \xB7 Activity Graph",activeTab:"graph",subtitle:"Activity Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Rr,scripts:'<script src="/assets/activity-graph.global.js" defer></script>',noMain:!0})}var Rr=`
6257
6257
  html, body { height: 100%; }
6258
6258
  body { margin: 0; }
6259
6259
  #ax-fleet-root { height: calc(100vh - 48px); }
@@ -6265,31 +6265,31 @@ body { margin: 0; }
6265
6265
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
6266
6266
  text-align: center;
6267
6267
  }
6268
- `;function Te(){let t=ze(process.cwd(),".agentx/intent/ledger.sqlite");if(!qe(t))return null;try{let e=new Cr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ea>6e4&&(ea=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ea=0;function ee(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function na(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zt({peers:a}))}var de={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:"API",color:"#3a7bd5"}};function Ar(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in de)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in de)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in de)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 de)return s}return"workflow"}return t}function Ir(t){let e={mtgl:"#e07a3a",ksi:"#3a7bd5",noqta:"#10b981",hasanah:"#bc8cff","hasanah-lab":"#bc8cff",hexastack:"#06b6d4",hackathonat:"#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 $r(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 ra(t,e){if(!t)return"unmapped";if(e){let n=e.find(r=>r.id===t);if(n?.client)return n.client}let a=t.indexOf("/");return a>0?t.slice(0,a):t}function oa(t){let e=new Map;if(!t)return e;let a=t.business;if(!a)return e;let n=a.projects??[],r=a.orgChart??{};for(let s of n){if(!s.pm)continue;let l=s.client||(s.id.includes("/")?s.id.slice(0,s.id.indexOf("/")):s.id);e.has(s.pm)||e.set(s.pm,l)}function o(s,l=new Set){if(e.has(s))return e.get(s);if(l.has(s))return;l.add(s);let i=r[s];if(!i?.reportsTo)return;let d=o(i.reportsTo,l);return d&&e.set(s,d),d}for(let s of Object.keys(r))o(s);return e}function sa(t,e,a){if(!a.length)return;let n=String(e?.chatId??e?.message?.chat?.id??""),r=String(e?.sender?.username??e?.message?.from?.username??""),o=String(e?.sender?.id??e?.message?.from?.id??""),s=a.filter(l=>!l.channel||l.channel===t);for(let l of s)if(l.chatId&&n&&l.chatId===n)return l;for(let l of s)if(l.username&&r&&l.username===r)return l;for(let l of s)if(l.senderId&&o&&l.senderId===o)return l;for(let l of s)if(!l.chatId&&!l.username&&!l.senderId&&l.channel===t)return l}function jr(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:N(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 i=o.slice(6);if(i&&!Be(i))return{id:i,name:i,avatar:N(i),kind:"a2a"}}let l=o||r||s;if(l&&!Be(r||o||"")){let i=r||o||s,d=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":"mesh";return{id:i,name:o||r||i,avatar:N(l),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,l=typeof s.username=="string"?s.username:null,i=typeof s.name=="string"?s.name:null,d=l||(s.id!=null?String(s.id):null)||i;if(d&&!Be(l||i||"")){let c=typeof n.channel=="string"?n.channel:"",u=ta(c);return{id:d,name:i||l||d,avatar:N(i||l||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 i=s.username||s.name,d=s.name||s.username;return{id:i,name:d,avatar:N(d),kind:"gitlab"}}let l=o.sender;if(l?.login)return{id:l.login,name:l.login,avatar:N(l.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 l=o||r||s;return{id:s,name:l,avatar:N(l),kind:ta(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:N(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:N(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:N(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:N(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:N(o),kind:"whatsapp"}}}return null}function ta(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Be(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 N(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 ia(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}
6268
+ `;function Ie(){let t=Ge(process.cwd(),".agentx/intent/ledger.sqlite");if(!Xe(t))return null;try{let e=new Hr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-na>6e4&&(na=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var na=0;function ae(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function sa(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(aa({peers:a}))}var pe={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"API",color:"#3a7bd5"}};function Nr(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in pe)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in pe)return s}return"workflow"}return t}function Br(t){let e={mtgl:"#e07a3a",ksi:"#3a7bd5",noqta:"#10b981",hasanah:"#bc8cff","hasanah-lab":"#bc8cff",hexastack:"#06b6d4",hackathonat:"#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 zr(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 ia(t,e){if(!t)return"unmapped";if(e){let n=e.find(r=>r.id===t);if(n?.client)return n.client}let a=t.indexOf("/");return a>0?t.slice(0,a):t}function la(t){let e=new Map;if(!t)return e;let a=t.business;if(!a)return e;let n=a.projects??[],r=a.orgChart??{};for(let s of n){if(!s.pm)continue;let i=s.client||(s.id.includes("/")?s.id.slice(0,s.id.indexOf("/")):s.id);e.has(s.pm)||e.set(s.pm,i)}function o(s,i=new Set){if(e.has(s))return e.get(s);if(i.has(s))return;i.add(s);let l=r[s];if(!l?.reportsTo)return;let d=o(l.reportsTo,i);return d&&e.set(s,d),d}for(let s of Object.keys(r))o(s);return e}function da(t,e,a){if(!a.length)return;let n=String(e?.chatId??e?.message?.chat?.id??""),r=String(e?.sender?.username??e?.message?.from?.username??""),o=String(e?.sender?.id??e?.message?.from?.id??""),s=a.filter(i=>!i.channel||i.channel===t);for(let i of s)if(i.chatId&&n&&i.chatId===n)return i;for(let i of s)if(i.username&&r&&i.username===r)return i;for(let i of s)if(i.senderId&&o&&i.senderId===o)return i;for(let i of s)if(!i.chatId&&!i.username&&!i.senderId&&i.channel===t)return i}function qr(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:B(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&&!We(l))return{id:l,name:l,avatar:B(l),kind:"a2a"}}let i=o||r||s;if(i&&!We(r||o||"")){let l=r||o||s,d=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":"mesh";return{id:l,name:o||r||l,avatar:B(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&&!We(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=ra(p);return{id:d,name:l||i||d,avatar:B(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:B(d),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:B(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:B(i),kind:ra(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:B(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:B(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:B(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:B(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:B(o),kind:"whatsapp"}}}return null}function ra(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function We(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 B(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 ca(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}
6269
6269
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
6270
- ${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 Mr(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 Ue(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
6270
+ ${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 Ur(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 Ke(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
6271
6271
  SELECT id, ts, source, project, subject, intent, raw_json
6272
6272
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
6273
- `).all(r),s=new Map,l=new Map;if(o.length>0){let h=o.map(b=>b.id),y=h.map((b,A)=>`@id${A}`).join(","),_=Object.fromEntries(h.map((b,A)=>[`id${A}`,b])),$=t.prepare(`
6273
+ `).all(r),s=new Map,i=new Map;if(o.length>0){let h=o.map(w=>w.id),b=h.map((w,I)=>`@id${I}`).join(","),_=Object.fromEntries(h.map((w,I)=>[`id${I}`,w])),j=t.prepare(`
6274
6274
  SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
6275
- FROM intent_decisions WHERE event_id IN (${y}) ORDER BY decided_at ASC
6276
- `).all(_);for(let b of $)s.has(b.event_id)||s.set(b.event_id,[]),s.get(b.event_id).push(b);let I=t.prepare(`
6275
+ FROM intent_decisions WHERE event_id IN (${b}) ORDER BY decided_at ASC
6276
+ `).all(_);for(let w of j)s.has(w.event_id)||s.set(w.event_id,[]),s.get(w.event_id).push(w);let $=t.prepare(`
6277
6277
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
6278
- FROM intent_resolutions WHERE decision_event_id IN (${y})
6279
- `).all(_);for(let b of I)l.set(`${b.decision_event_id}|${b.decision_decided_by}`,b)}let i=new Map,d=new Map,c=new Map,u=new Map,g=[],f=e?.business?.projects??[],k=e?.business?.contactMap??[],T=oa(e);for(let h of o){let y=null;try{y=JSON.parse(h.raw_json)}catch{}let _=sa(h.source,y,k),$=null,I=null;_?($=_.client,I=_.project||`${_.client}/_chat`):h.project&&($=ra(h.project,f),I=h.project);let b=Ar(h.source,h.intent||"",y),A=de[b]||{label:b,color:"#6b7280"};c.has(b)||c.set(b,{id:b,label:A.label,color:A.color});let j="__system",D,O=jr(h.source,h.intent||"",y);if(O){j=O.id,D=O.kind;let M=_?.displayName||O.name;(!u.has(O.id)||_?.displayName)&&u.set(O.id,{id:O.id,name:M,avatar:N(M),kind:O.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let X=ia(h.source,y);for(let M of s.get(h.id)??[]){if(M.outcome!=="dispatched"||!M.agent_id)continue;let J=`${h.id}|${M.decided_by}`,te=l.get(J),z=M.decided_at,F=te?.resolved_at??null,q=F===null,Pa=te?.duration_ms??(q?n-z:0),Da=q?"active":te?.status==="error"||te?.status==="fail"?"error":"completed",U,ce;if($)U=$,ce=I;else{let $e=T.get(M.agent_id);$e?(U=$e,ce=`${$e}/_${h.source}`):(U="unmapped",ce=`unmapped/_${h.source}`)}i.has(U)||i.set(U,{id:U,name:U,color:Ir(U),projects:[]}),d.has(U)||d.set(U,new Set),d.get(U).add(ce),g.push({id:`${h.id}|${M.decided_by}`,agentId:M.agent_id,clientId:U,projectId:ce,channelId:b,initiatorId:j,initiatorKind:D,subject:Mr(h.subject),intent:h.intent||"",startedAt:z,resolvedAt:F,duration:Pa,active:q,outcome:Da,tokens:0,inputPreview:X,system:$r(M.agent_id,e)})}}let R=[...i.values()].map(h=>({...h,projects:[...d.get(h.id)||[]].sort()})).sort((h,y)=>h.id.localeCompare(y.id)),P=[],p=new Set;if(e)for(let[h,y]of Object.entries(e.agents||{})){let _={id:h,name:y.name||h,tier:y.tier==="claude-code"?"lead":"worker",model:y.model||"",role:y.systemPrompt?y.systemPrompt.split(/[.\n]/)[0].slice(0,60):y.tier||""};P.push(_),p.add(h)}for(let h of g)p.has(h.agentId)||(P.push({id:h.agentId,name:h.agentId,tier:"worker",model:"",role:""}),p.add(h.agentId));P.sort((h,y)=>h.id.localeCompare(y.id));let m=[],x=new Set;for(let[h,y]of Object.entries(de))m.push({id:h,label:y.label,color:y.color}),x.add(h);for(let h of c.values())x.has(h.id)||m.push(h);let v=[...u.values()];return v.find(h=>h.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"}),{now:n,windowH:a,clients:R,agents:P,channels:m,initiators:v,dispatches:g}}function la(t){let e=Te();if(!e)return null;try{return Ue(e.db,oe,t)}finally{e.close()}}function da(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,l=0;for(let{nodeId:i,snap:d}of t){d.now>s&&(s=d.now),d.windowH>l&&(l=d.windowH);for(let c of d.clients){let u=e.get(c.id);if(!u)e.set(c.id,{...c,projects:[...c.projects]});else{let g=Array.from(new Set([...u.projects,...c.projects])).sort();e.set(c.id,{...u,projects:g})}}for(let c of d.agents)a.has(c.id)||a.set(c.id,c);for(let c of d.channels)n.has(c.id)||n.set(c.id,c);for(let c of d.initiators)r.has(c.id)||r.set(c.id,c);for(let c of d.dispatches)o.push({...c,nodeId:i,id:`${i}::${c.id}`})}return{now:s||Date.now(),windowH:l||6,clients:[...e.values()].sort((i,d)=>i.id.localeCompare(d.id)),agents:[...a.values()].sort((i,d)=>i.id.localeCompare(d.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((i,d)=>d.startedAt-i.startedAt)}}var oe=null;function ca(t){oe=t}async function pa(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Te();if(!n)return ee(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=ma(parseInt(r.searchParams.get("hours")||"6",10));ee(e,200,Ue(n.db,oe,o))}catch(r){ee(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Lr=5e3;async function ua(t,e,a){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
6278
+ FROM intent_resolutions WHERE decision_event_id IN (${b})
6279
+ `).all(_);for(let w of $)i.set(`${w.decision_event_id}|${w.decision_decided_by}`,w)}let l=new Map,d=new Map,p=new Map,u=new Map,f=[],v=e?.business?.projects??[],k=e?.business?.contactMap??[],A=la(e);for(let h of o){let b=null;try{b=JSON.parse(h.raw_json)}catch{}let _=da(h.source,b,k),j=null,$=null;_?(j=_.client,$=_.project||`${_.client}/_chat`):h.project&&(j=ia(h.project,v),$=h.project);let w=Nr(h.source,h.intent||"",b),I=pe[w]||{label:w,color:"#6b7280"};p.has(w)||p.set(w,{id:w,label:I.label,color:I.color});let L="__system",P,O=qr(h.source,h.intent||"",b);if(O){L=O.id,P=O.kind;let R=_?.displayName||O.name;(!u.has(O.id)||_?.displayName)&&u.set(O.id,{id:O.id,name:R,avatar:B(R),kind:O.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let Q=ca(h.source,b);for(let R of s.get(h.id)??[]){if(R.outcome!=="dispatched"||!R.agent_id)continue;let K=`${h.id}|${R.decided_by}`,ne=i.get(K),q=R.decided_at,W=ne?.resolved_at??null,U=W===null,Ga=ne?.duration_ms??(U?n-q:0),Xa=U?"active":ne?.status==="error"||ne?.status==="fail"?"error":"completed",F,ue;if(j)F=j,ue=$;else{let De=A.get(R.agent_id);De?(F=De,ue=`${De}/_${h.source}`):(F="unmapped",ue=`unmapped/_${h.source}`)}l.has(F)||l.set(F,{id:F,name:F,color:Br(F),projects:[]}),d.has(F)||d.set(F,new Set),d.get(F).add(ue),f.push({id:`${h.id}|${R.decided_by}`,agentId:R.agent_id,clientId:F,projectId:ue,channelId:w,initiatorId:L,initiatorKind:P,subject:Ur(h.subject),intent:h.intent||"",startedAt:q,resolvedAt:W,duration:Ga,active:U,outcome:Xa,tokens:0,inputPreview:Q,system:zr(R.agent_id,e)})}}let E=[...l.values()].map(h=>({...h,projects:[...d.get(h.id)||[]].sort()})).sort((h,b)=>h.id.localeCompare(b.id)),S=[],c=new Set;if(e)for(let[h,b]of Object.entries(e.agents||{})){let _={id:h,name:b.name||h,tier:b.tier==="claude-code"?"lead":"worker",model:b.model||"",role:b.systemPrompt?b.systemPrompt.split(/[.\n]/)[0].slice(0,60):b.tier||""};S.push(_),c.add(h)}for(let h of f)c.has(h.agentId)||(S.push({id:h.agentId,name:h.agentId,tier:"worker",model:"",role:""}),c.add(h.agentId));S.sort((h,b)=>h.id.localeCompare(b.id));let m=[],g=new Set;for(let[h,b]of Object.entries(pe))m.push({id:h,label:b.label,color:b.color}),g.add(h);for(let h of p.values())g.has(h.id)||m.push(h);let x=[...u.values()];return x.find(h=>h.id==="__system")||x.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"}),{now:n,windowH:a,clients:E,agents:S,channels:m,initiators:x,dispatches:f}}function pa(t){let e=Ie();if(!e)return null;try{return Ke(e.db,ie,t)}finally{e.close()}}function ua(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0;for(let{nodeId:l,snap:d}of t){d.now>s&&(s=d.now),d.windowH>i&&(i=d.windowH);for(let p of d.clients){let u=e.get(p.id);if(!u)e.set(p.id,{...p,projects:[...p.projects]});else{let f=Array.from(new Set([...u.projects,...p.projects])).sort();e.set(p.id,{...u,projects:f})}}for(let p of d.agents)a.has(p.id)||a.set(p.id,p);for(let p of d.channels)n.has(p.id)||n.set(p.id,p);for(let p of d.initiators)r.has(p.id)||r.set(p.id,p);for(let p of d.dispatches)o.push({...p,nodeId:l,id:`${l}::${p.id}`})}return{now:s||Date.now(),windowH:i||6,clients:[...e.values()].sort((l,d)=>l.id.localeCompare(d.id)),agents:[...a.values()].sort((l,d)=>l.id.localeCompare(d.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((l,d)=>d.startedAt-l.startedAt)}}var ie=null;function ma(t){ie=t}async function ha(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Ie();if(!n)return ae(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=fa(parseInt(r.searchParams.get("hours")||"6",10));ae(e,200,Ke(n.db,ie,o))}catch(r){ae(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Fr=5e3;async function ga(t,e,a){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
6280
6280
 
6281
- `);let n=new URL(t.url||"/","http://_"),r=ma(parseInt(n.searchParams.get("hours")||"6",10)),o=!1,s=()=>{o=!0};t.on("close",s),t.on("error",s),e.on("close",s),e.on("error",s);let l=setInterval(()=>{if(!o)try{e.write(`: hb
6281
+ `);let n=new URL(t.url||"/","http://_"),r=fa(parseInt(n.searchParams.get("hours")||"6",10)),o=!1,s=()=>{o=!0};t.on("close",s),t.on("error",s),e.on("close",s),e.on("error",s);let i=setInterval(()=>{if(!o)try{e.write(`: hb
6282
6282
 
6283
- `)}catch{s()}},25e3);try{for(;!o;){let i=Te();if(i)try{let c=Ue(i.db,oe,r);e.write(`event: snapshot
6284
- `),e.write(`data: ${JSON.stringify(c)}
6283
+ `)}catch{s()}},25e3);try{for(;!o;){let l=Ie();if(l)try{let p=Ke(l.db,ie,r);e.write(`event: snapshot
6284
+ `),e.write(`data: ${JSON.stringify(p)}
6285
6285
 
6286
- `)}catch(c){e.write(`event: error
6287
- data: ${JSON.stringify({error:c?.message??String(c)})}
6286
+ `)}catch(p){e.write(`event: error
6287
+ data: ${JSON.stringify({error:p?.message??String(p)})}
6288
6288
 
6289
- `)}finally{i.close()}else e.write(`event: error
6289
+ `)}finally{l.close()}else e.write(`event: error
6290
6290
  data: ${JSON.stringify({error:"ledger not available"})}
6291
6291
 
6292
- `);let d=Date.now();for(;!o&&Date.now()-d<Lr;)await new Promise(c=>setTimeout(c,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function ma(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Rr(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=ze(process.cwd(),".agentx/task-history",t,n);if(!qe(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=ze(process.cwd(),".agentx/task-history",t,o);return qe(s)?aa(s,e,a):null}return aa(r,e,a)}function aa(t,e,a){let n=null,r=1/0;for(let o of Sr(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Tr(Er(t,o),"utf-8"))}catch{continue}let l=s.startedAt,i;if(typeof l=="number")i=l;else if(typeof l=="string"){let c=Date.parse(l);if(!Number.isFinite(c))continue;i=c}else continue;let d=Math.abs(i-e);d<r&&d<=a&&(n=s,r=d)}return n}async function ga(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 ee(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),l=r.slice(o+1),i=Te();if(!i)return ee(e,503,{error:"ledger not available"}),!0;try{let d=i.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!d)return ee(e,404,{error:"event not found"}),!0;let c=i.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,l);if(!c)return ee(e,404,{error:"decision not found"}),!0;let u=i.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,l),g=null;try{g=JSON.parse(d.raw_json)}catch{}let f=ia(d.source,g),k=g&&typeof g=="object"&&(g.text||g.message?.text||g.message?.caption||g.object_attributes?.note||g.object_attributes?.description||g.comment?.body||g.issue?.body||(typeof g.message=="string"?g.message:null)||(typeof g.prompt=="string"?g.prompt:null)||null)||f,T=null,R=null;if(c.agent_id){let h=Rr(c.agent_id,c.decided_at);if(h){typeof h.responseText=="string"&&(T=h.responseText);let y=h.transcript;Array.isArray(y)&&(R=y.length)}}let P=oe?.business?.projects??[],p=oe?.business?.contactMap??[],m=oa(oe),x={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},v=sa(d.source,g,p);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(d.project)x={client:ra(d.project,P),project:d.project,via:`project namespace prefix (${d.project})`};else if(c.agent_id){let h=m.get(c.agent_id);h&&(x={client:h,project:`${h}/_${d.source}`,via:`orgChart fallback (agent ${c.agent_id} reports up to a PM whose project belongs to ${h})`})}ee(e,200,{id:r,eventId:s,source:d.source,subject:d.subject,intent:d.intent,project:d.project,decidedBy:c.decided_by,agentId:c.agent_id,outcome:c.outcome,reason:c.reason,startedAt:c.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:k,response:T,transcriptLen:R,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(d){ee(e,500,{error:d?.message??String(d)})}finally{i.close()}return!0}import{existsSync as Hr,readFileSync as Nr}from"fs";import{resolve as fa}from"path";function ha(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=Pr.replace(/__AGENT_ID__/g,L(e));return C({title:`AgentX \xB7 ${L(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${L(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Dr,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>${Or}</script>`})}var Pr=`
6292
+ `);let d=Date.now();for(;!o&&Date.now()-d<Fr;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(i);try{e.end()}catch{}}return!0}function fa(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Wr(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Ge(process.cwd(),".agentx/task-history",t,n);if(!Xe(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Ge(process.cwd(),".agentx/task-history",t,o);return Xe(s)?oa(s,e,a):null}return oa(r,e,a)}function oa(t,e,a){let n=null,r=1/0;for(let o of Pr(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Or(Dr(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 xa(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 ae(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Ie();if(!l)return ae(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 ae(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 ae(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 v=ca(d.source,f),k=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)||v,A=null,E=null;if(p.agent_id){let h=Wr(p.agent_id,p.decided_at);if(h){typeof h.responseText=="string"&&(A=h.responseText);let b=h.transcript;Array.isArray(b)&&(E=b.length)}}let S=ie?.business?.projects??[],c=ie?.business?.contactMap??[],m=la(ie),g={client:"unmapped",project:`unmapped/_${d.source}`,via:"fallback"},x=da(d.source,f,c);if(x)g={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)g={client:ia(d.project,S),project:d.project,via:`project namespace prefix (${d.project})`};else if(p.agent_id){let h=m.get(p.agent_id);h&&(g={client:h,project:`${h}/_${d.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${h})`})}ae(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:k,response:A,transcriptLen:E,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:g})}catch(d){ae(e,500,{error:d?.message??String(d)})}finally{l.close()}return!0}import{existsSync as Jr,readFileSync as Vr}from"fs";import{resolve as ba}from"path";function va(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=Gr.replace(/__AGENT_ID__/g,D(e));return M({title:`AgentX \xB7 ${D(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${D(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Xr,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>${Kr}</script>`})}var Gr=`
6293
6293
  <!-- Breadcrumb -->
6294
6294
  <div class="ax-crumb">
6295
6295
  <a href="/admin">Settings</a>
@@ -6878,7 +6878,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
6878
6878
  </div>
6879
6879
  </div>
6880
6880
  </div>
6881
- `,Dr=`
6881
+ `,Xr=`
6882
6882
  /* Agent-specific layout + legacy styles for bits the migration left in
6883
6883
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
6884
6884
  * primitives live in components.css.ts. */
@@ -6997,7 +6997,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
6997
6997
 
6998
6998
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
6999
6999
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
7000
- `,Or=`
7000
+ `,Kr=`
7001
7001
  const $ = (id) => document.getElementById(id);
7002
7002
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
7003
7003
 
@@ -7851,15 +7851,15 @@ document.addEventListener('keydown', (e) => {
7851
7851
  /* ===== Boot ===== */
7852
7852
  initOptsToggles();
7853
7853
  loadAgent();
7854
- `;function xa(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ha({agentId:a,peers:n,localToken:r}))}async function va(t,e,a){try{let n=t.method==="GET"?void 0:await io(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){Ce(e,404,{error:`unknown agent endpoint: ${a}`});return}let l=s[1],i=s[2]||"",d=`${t.method} ${i}`,u={"GET ":()=>ge(l),"PATCH ":()=>Br(l,n),"PATCH capability":()=>Ur(l,n),"POST mcp":()=>zr(l,n),"DELETE mcp":()=>qr(l,n),"GET identity":()=>Fr(l),"GET identity/file":()=>Wr(l,String(o.path||"")),"PUT identity/file":()=>Gr(l,n),"GET skills":()=>Kr(l),"POST skills":()=>Jr(l,n),"DELETE skills":()=>Vr(l,n),"GET skills/tree":()=>Xr(l,String(o.slug||"")),"GET skills/file":()=>Yr(l,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Qr(l,n),"GET skills/deps":()=>Zr(l,String(o.slug||"")),"POST skills/install":()=>eo(l,n,t),"POST skills/deps":()=>to(l,n,t),"GET channels":()=>ao(l),"GET activity":()=>no(l,t),"GET handovers":()=>ro(l),"POST handovers":()=>oo(l,n),"DELETE handovers":()=>so(n)}[d];if(!u){Ce(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let g=await u();Ce(e,200,g)}catch(n){Ce(e,400,{error:n?.message||"agent op failed"})}}function ba(){let t=fa(process.cwd(),"agentx.json");return Hr(t)?JSON.parse(Nr(t,"utf-8")):null}function B(t){let e=ba();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 ge(t){let{def:e,cfg:a}=B(t),n=e.workspace?ie(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 Br(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}=S(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:ge(t)}}function zr(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(l=>String(l)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[l,i]of Object.entries(e.env))typeof i=="string"&&(o[l]=i);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=S(l=>{if(!l.agents?.[t])throw new Error(`Agent "${t}" not found`);return l.agents[t].mcp=l.agents[t].mcp||{},l.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:ge(t)}}function qr(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=S(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:ge(t)}}function Ur(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}=S(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,l]of Object.entries(a))l===void 0?delete o[s]:o[s]=l;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:ge(t)}}function Fr(t){let{def:e}=B(t);return ie(e.workspace)}function Wr(t,e){if(!e)throw new Error("path query param required");let{def:a}=B(t);return be(a.workspace,e)}function Gr(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=B(t);return ye(n.workspace,a,String(e?.content??""))}function Kr(t){let{def:e}=B(t),a=ie(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Jr(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=B(t);return we(n.workspace,a,{title:e?.title,content:e?.content})}function Vr(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=B(t);return ke(n.workspace,a)}function Xr(t,e){if(!e)throw new Error("slug query param required");let{def:a}=B(t),n=pt(a.workspace,e),r=_e(a.workspace,e);return{slug:e,tree:n,deps:r}}function Yr(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=B(t);return ut(n.workspace,e,a)}function Qr(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=B(t);return mt(r.workspace,a,n,String(e?.content??""))}function Zr(t,e){if(!e)throw new Error("slug query param required");let{def:a}=B(t);return _e(a.workspace,e)}async function eo(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=ya(e?.worker),{def:o}=B(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(`
7855
- `);return wa(a,r,s,`install-${n}:${Date.now()}`)}async function to(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=ya(e?.worker),{def:o}=B(t),s=_e(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 l=fa(o.workspace,".claude","skills",n),i=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${l}`,`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(`
7856
- `);return wa(a,r,i,`deps-${t}-${n}:${Date.now()}`)}function ya(t){if(t&&typeof t=="string")return t;let e=W();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function wa(t,e,a,n){let r=W(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},l=t.headers.authorization;l?s.Authorization=String(l):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let i=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 i.text(),c;try{c=JSON.parse(d)}catch{c={content:d}}if(!i.ok)throw new Error(c?.error||`daemon /task HTTP ${i.status}`);return{worker:e,taskId:c?.taskId,content:c?.content,duration:c?.duration,error:c?.error}}function ao(t){let e=ba(),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 no(t,e){try{let n=(W().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(l=>l.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 Fe(){return new Qe}function ro(t){let e=Fe(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function oo(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,l=e?.summary?String(e.summary):void 0,i=e?.expiresAt?String(e.expiresAt):void 0,d=Fe().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:l,expiresAt:i,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:d}}function so(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:Fe().remove(e,a,n)?"Released":"No active handover for that chat"}}function Ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function io(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 se={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 ka=[{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 We(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(se)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
7854
+ `;function ya(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(va({agentId:a,peers:n,localToken:r}))}async function wa(t,e,a){try{let n=t.method==="GET"?void 0:await bo(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){$e(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",d=`${t.method} ${l}`,u={"GET ":()=>fe(i),"PATCH ":()=>Yr(i,n),"PATCH capability":()=>eo(i,n),"POST mcp":()=>Qr(i,n),"DELETE mcp":()=>Zr(i,n),"GET identity":()=>to(i),"GET identity/file":()=>ao(i,String(o.path||"")),"PUT identity/file":()=>no(i,n),"GET skills":()=>ro(i),"POST skills":()=>oo(i,n),"DELETE skills":()=>so(i,n),"GET skills/tree":()=>io(i,String(o.slug||"")),"GET skills/file":()=>lo(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>co(i,n),"GET skills/deps":()=>po(i,String(o.slug||"")),"POST skills/install":()=>uo(i,n,t),"POST skills/deps":()=>mo(i,n,t),"GET channels":()=>ho(i),"GET activity":()=>go(i,t),"GET handovers":()=>fo(i),"POST handovers":()=>xo(i,n),"DELETE handovers":()=>vo(n)}[d];if(!u){$e(e,404,{error:`unknown agent sub-endpoint: ${d}`});return}let f=await u();$e(e,200,f)}catch(n){$e(e,400,{error:n?.message||"agent op failed"})}}function ka(){let t=ba(process.cwd(),"agentx.json");return Jr(t)?JSON.parse(Vr(t,"utf-8")):null}function z(t){let e=ka();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 fe(t){let{def:e,cfg:a}=z(t),n=e.workspace?de(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 Yr(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:fe(t)}}function Qr(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:fe(t)}}function Zr(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:fe(t)}}function eo(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:fe(t)}}function to(t){let{def:e}=z(t);return de(e.workspace)}function ao(t,e){if(!e)throw new Error("path query param required");let{def:a}=z(t);return we(a.workspace,e)}function no(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=z(t);return ke(n.workspace,a,String(e?.content??""))}function ro(t){let{def:e}=z(t),a=de(e.workspace);return{skills:a.skills,workspace:a.workspace}}function oo(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=z(t);return _e(n.workspace,a,{title:e?.title,content:e?.content})}function so(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=z(t);return Ee(n.workspace,a)}function io(t,e){if(!e)throw new Error("slug query param required");let{def:a}=z(t),n=ft(a.workspace,e),r=Se(a.workspace,e);return{slug:e,tree:n,deps:r}}function lo(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=z(t);return xt(n.workspace,e,a)}function co(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=z(t);return vt(r.workspace,a,n,String(e?.content??""))}function po(t,e){if(!e)throw new Error("slug query param required");let{def:a}=z(t);return Se(a.workspace,e)}async function uo(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=_a(e?.worker),{def:o}=z(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(`
7855
+ `);return Ea(a,r,s,`install-${n}:${Date.now()}`)}async function mo(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=_a(e?.worker),{def:o}=z(t),s=Se(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=ba(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(`
7856
+ `);return Ea(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function _a(t){if(t&&typeof t=="string")return t;let e=G();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Ea(t,e,a,n){let r=G(),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 ho(t){let e=ka(),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 go(t,e){try{let n=(G().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 Je(){return new nt}function fo(t){let e=Je(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function xo(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=Je().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 vo(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:Je().remove(e,a,n)?"Released":"No active handover for that chat"}}function $e(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function bo(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 le={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 Sa=[{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 Ve(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(le)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
7857
7857
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
7858
7858
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
7859
7859
  <section id="statstrip" class="ax-statstrip"></section>
7860
7860
  <main id="grid" class="ax-live__body"></main>
7861
7861
  </div>
7862
- `;return C({title:`${se.brand} \xB7 ${se.subtitle}`,activeTab:"live",subtitle:se.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:lo,scripts:e+`<script>${co}</script>`,headExtras:`<script>
7862
+ `;return M({title:`${le.brand} \xB7 ${le.subtitle}`,activeTab:"live",subtitle:le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:yo,scripts:e+`<script>${wo}</script>`,headExtras:`<script>
7863
7863
  // rightExtras for the topbar are injected at runtime \u2014 they reference
7864
7864
  // IDs (#ts, #conn-dot) that the script below addresses directly.
7865
7865
  document.addEventListener('DOMContentLoaded', () => {
@@ -7870,7 +7870,7 @@ loadAgent();
7870
7870
  extras.innerHTML = ${JSON.stringify(a)};
7871
7871
  right.insertBefore(extras, right.firstChild);
7872
7872
  });
7873
- </script>`})}var lo=`
7873
+ </script>`})}var yo=`
7874
7874
  /* --- Page frame --- */
7875
7875
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
7876
7876
 
@@ -8071,7 +8071,7 @@ loadAgent();
8071
8071
  border-top-color: var(--ax-accent); border-radius: 50%;
8072
8072
  animation: ax-spin 800ms linear infinite; display: inline-block;
8073
8073
  }
8074
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,co=`
8074
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,wo=`
8075
8075
  'use strict';
8076
8076
 
8077
8077
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -8543,108 +8543,1074 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
8543
8543
  });
8544
8544
  }
8545
8545
 
8546
- `;function _a(t){return C({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,body:`<div class="mx-page">
8547
- <header class="mx-head">
8548
- <div>
8549
- <p class="mx-kicker">Mesh control plane</p>
8550
- <h1>Operational posture</h1>
8551
- <p id="mx-updated" class="mx-muted" aria-live="polite">Connecting to the fleet...</p>
8546
+ `;var Ta=`
8547
+ .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
8548
+ .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
8549
+ .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
8550
+ .mx-section-actions{display:flex;align-items:center;gap:8px;margin-left:auto}
8551
+ .mx-show-all{padding:4px 9px;font-size:11px;border-radius:var(--ax-radius-sm)}
8552
+ .mx-columns{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(280px,.8fr);gap:24px}
8553
+ .mx-two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}
8554
+ .mx-agent-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
8555
+
8556
+ /* --- chart tokens ------------------------------------------------- */
8557
+ /* Scoped to the document root, not .mx-content: the details drawer is a
8558
+ sibling of <main> and needs the same status ramp for its run cells.
8559
+ Matches how tokens.ts carries the theme (data-theme on <html>). */
8560
+ :root{
8561
+ --mx-lane-cron:#3B82F6;--mx-lane-workflow:#C2255C;--mx-lane-direct:#0E9594;
8562
+ --mx-good:#22B573;--mx-warn:#FFB300;--mx-serious:#E8590C;--mx-crit:#F23A3A;
8563
+ --mx-grid:var(--ax-border);--mx-track:var(--ax-surface-3);
8564
+ }
8565
+ [data-theme="dark"]{
8566
+ --mx-lane-cron:#4A86E8;--mx-lane-workflow:#DB3E77;--mx-lane-direct:#159B8B;
8567
+ --mx-good:#4ED89B;--mx-warn:#FFC948;--mx-serious:#FF922B;--mx-crit:#FF6B6B;
8568
+ }
8569
+
8570
+ /* --- toolbar ------------------------------------------------------- */
8571
+ .mx-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin:0 0 22px}
8572
+ .mx-tabs{display:flex;gap:0;border:var(--ax-border-w) solid var(--ax-border-2);border-radius:var(--ax-radius-pill);padding:3px;background:var(--ax-surface)}
8573
+ .mx-tab{border:0;background:transparent;color:var(--ax-text-2);font:600 12px var(--ax-font);padding:6px 14px;border-radius:var(--ax-radius-pill);cursor:pointer}
8574
+ .mx-tab[aria-selected="true"]{background:var(--ax-accent);color:#fff}
8575
+ .mx-tab:focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px}
8576
+ .mx-range{display:flex;gap:6px;margin-left:auto}
8577
+ .mx-range button{border:var(--ax-border-w) solid var(--ax-border-2);background:var(--ax-surface);color:var(--ax-text-2);font:600 11px var(--ax-mono);padding:5px 10px;border-radius:var(--ax-radius-sm);cursor:pointer}
8578
+ .mx-range button[aria-pressed="true"]{border-color:var(--ax-accent);color:var(--ax-accent)}
8579
+ .mx-view[hidden]{display:none}
8580
+
8581
+ /* --- activity lanes ------------------------------------------------ */
8582
+ .mx-lane{display:grid;grid-template-columns:132px minmax(0,1fr) 92px;align-items:center;gap:14px;padding:10px 0;border-bottom:1px solid var(--ax-border)}
8583
+ .mx-lane:last-child{border-bottom:0}
8584
+ .mx-lane__name{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600}
8585
+ .mx-lane__swatch{width:10px;height:10px;border-radius:3px;flex:0 0 auto}
8586
+ .mx-lane__peak{font:10px var(--ax-mono);color:var(--ax-muted);margin-top:2px}
8587
+ .mx-lane__tot{text-align:right;font:11px var(--ax-mono);color:var(--ax-text-2)}
8588
+ .mx-lane__tot b{display:block;font-size:15px;font-family:var(--ax-font);color:var(--ax-text)}
8589
+ .mx-cols{display:flex;align-items:flex-end;gap:2px;height:56px}
8590
+ .mx-col{flex:1 1 0;min-width:2px;height:100%;display:flex;flex-direction:column;justify-content:flex-end;gap:2px;background:none;border:0;padding:0;border-radius:3px;cursor:pointer}
8591
+ .mx-col:hover,.mx-col:focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px}
8592
+ .mx-col i{display:block;font-style:normal;border-radius:3px 3px 0 0}
8593
+ .mx-col i.is-base{border-radius:0 0 3px 3px}
8594
+ .mx-col i.is-fail{background:var(--mx-crit)}
8595
+ .mx-col i.is-empty{height:2px;background:var(--ax-border);border-radius:1px}
8596
+ .mx-axis{display:flex;justify-content:space-between;font:10px var(--ax-mono);color:var(--ax-muted);padding:6px 0 0 146px}
8597
+ .mx-note{margin:12px 0 0;font-size:11px;color:var(--ax-muted);line-height:1.55}
8598
+
8599
+ /* --- horizontal bar lists ------------------------------------------ */
8600
+ .mx-bars{display:grid;gap:9px}
8601
+ .mx-bar{display:grid;grid-template-columns:minmax(96px,150px) minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;background:none;border:0;padding:2px 0;color:inherit;font:inherit;text-align:left;cursor:pointer;border-radius:var(--ax-radius-sm)}
8602
+ .mx-bar:hover .mx-bar__label,.mx-bar:focus-visible .mx-bar__label{color:var(--ax-accent)}
8603
+ .mx-bar:focus-visible{outline:2px solid var(--ax-accent);outline-offset:3px}
8604
+ .mx-bar__label{font-size:12px;font-weight:600;line-height:1.25;overflow-wrap:anywhere}
8605
+ .mx-bar__track{position:relative;height:14px;border-radius:4px;background:var(--mx-track);overflow:hidden}
8606
+ .mx-bar__fill{position:absolute;inset:0 auto 0 0;border-radius:4px}
8607
+ .mx-bar__fail{position:absolute;top:0;bottom:0;border-radius:4px;background:var(--mx-crit);box-shadow:-2px 0 0 var(--ax-surface)}
8608
+ .mx-bar__val{font:11px var(--ax-mono);color:var(--ax-text-2);white-space:nowrap}
8609
+ .mx-bar__val em{font-style:normal;color:var(--ax-muted)}
8610
+
8611
+ /* --- scatter -------------------------------------------------------- */
8612
+ .mx-scatter{position:relative;overflow-x:auto}
8613
+ /* Below ~700px the plot would shrink its 10px axis labels into noise, so
8614
+ it keeps a legible minimum and scrolls inside its own container rather
8615
+ than forcing the page to scroll sideways. */
8616
+ .mx-scatter svg{display:block;width:100%;min-width:660px;height:340px;overflow:visible}
8617
+ .mx-scatter text{font:10px var(--ax-mono);fill:var(--ax-muted)}
8618
+ .mx-scatter .mx-pt{cursor:pointer}
8619
+ .mx-scatter .mx-pt:hover circle,.mx-scatter .mx-pt:hover path,.mx-scatter .mx-pt:hover rect.mx-mark{stroke:var(--ax-text);stroke-width:2}
8620
+ .mx-scatter .mx-lbl{fill:var(--ax-text-2);font-size:10px}
8621
+ .mx-legend{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:12px}
8622
+ .mx-legend span{display:inline-flex;align-items:center;gap:7px;font-size:11px;color:var(--ax-text-2)}
8623
+ .mx-legend svg{width:12px;height:12px;overflow:visible}
8624
+ .mx-tip{position:absolute;z-index:5;pointer-events:none;min-width:170px;padding:9px 11px;border:var(--ax-border-w) solid var(--ax-border-2);border-radius:var(--ax-radius-sm);background:var(--ax-surface);box-shadow:var(--ax-shadow-lg);font-size:11px;line-height:1.5}
8625
+ .mx-tip b{display:block;font-size:12px;margin-bottom:3px}
8626
+ .mx-tip dl{display:grid;grid-template-columns:auto auto;gap:2px 10px;margin:4px 0 0;font-family:var(--ax-mono);font-size:10px}
8627
+ .mx-tip dt{color:var(--ax-muted)}.mx-tip dd{margin:0;text-align:right}
8628
+
8629
+ /* --- lifetime ------------------------------------------------------- */
8630
+ .mx-life{display:grid;grid-template-columns:minmax(150px,200px) minmax(0,1fr) 158px;align-items:center;gap:14px;width:100%;padding:9px 8px;background:none;border:0;border-radius:var(--ax-radius-sm);color:inherit;font:inherit;text-align:left;cursor:pointer}
8631
+ .mx-life:hover,.mx-life:focus-visible{background:var(--ax-surface-2);outline:none}
8632
+ .mx-life__id{min-width:0}
8633
+ .mx-life__id b{display:block;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
8634
+ .mx-life__id span{display:block;font:10px var(--ax-mono);color:var(--ax-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
8635
+ .mx-life__span{position:relative;height:20px}
8636
+ .mx-life__track{position:absolute;top:8px;height:4px;border-radius:2px;background:var(--ax-accent);opacity:.55}
8637
+ .mx-life__tick{position:absolute;top:2px;width:2px;height:16px;border-radius:1px}
8638
+ .mx-life__meta{text-align:right;font:10px var(--ax-mono);color:var(--ax-muted)}
8639
+ .mx-life__meta b{font-family:var(--ax-font);font-size:13px;color:var(--ax-text)}
8640
+ .mx-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
8641
+ .mx-chip{border:var(--ax-border-w) solid var(--ax-border);background:var(--ax-surface);color:var(--ax-text-2);font:600 11px var(--ax-font);padding:4px 11px;border-radius:var(--ax-radius-pill);cursor:pointer}
8642
+ .mx-chip[aria-pressed="true"]{border-color:var(--ax-accent);color:var(--ax-accent)}
8643
+
8644
+ /* --- drawer: stat tiles, conversation list ------------------------- */
8645
+ .mx-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:8px}
8646
+ .mx-stat{padding:9px 11px;border:1px solid var(--ax-border);border-radius:var(--ax-radius-sm);background:var(--ax-surface-2)}
8647
+ .mx-stat b{display:block;font:10px var(--ax-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--ax-muted);font-weight:400}
8648
+ .mx-stat span{display:block;margin-top:3px;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums}
8649
+ .mx-convs{display:grid;gap:4px;max-height:300px;overflow:auto}
8650
+ .mx-conv{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;padding:8px 10px;border:1px solid var(--ax-border);border-radius:var(--ax-radius-sm);background:var(--ax-surface);color:inherit;font:inherit;text-align:left;cursor:pointer}
8651
+ .mx-conv:hover,.mx-conv:focus-visible{border-color:var(--ax-accent);outline:none}
8652
+ .mx-conv__id{min-width:0}
8653
+ .mx-conv__id b{display:block;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
8654
+ .mx-conv__id span{display:block;font:10px var(--ax-mono);color:var(--ax-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
8655
+ .mx-conv__meta{flex:0 0 auto;text-align:right;font:10px var(--ax-mono);color:var(--ax-text-2);line-height:1.5}
8656
+ .mx-tip__hint{margin:6px 0 0;padding-top:5px;border-top:1px solid var(--ax-border);font-size:10px;color:var(--ax-muted)}
8657
+
8658
+ /* --- run grid + step list (drawer) --------------------------------- */
8659
+ #mx-drill,#mx-day,#mx-conv{display:grid;gap:16px}
8660
+ .mx-runs{display:flex;flex-wrap:wrap;gap:3px;margin:6px 0 4px}
8661
+ .mx-run{width:15px;height:15px;border-radius:3px;border:0;padding:0;cursor:pointer}
8662
+ .mx-run:focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px}
8663
+ .mx-run[aria-pressed="true"]{box-shadow:0 0 0 2px var(--ax-surface),0 0 0 4px var(--ax-text)}
8664
+ .mx-touch{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 0}
8665
+ .mx-touch span{border:1px solid var(--ax-border-2);border-radius:var(--ax-radius-pill);padding:2px 9px;font:10px var(--ax-mono);color:var(--ax-text-2)}
8666
+ .mx-touch span.is-zero{color:var(--ax-muted);opacity:.7}
8667
+ .mx-steps{margin:0;padding:0;list-style:none;max-height:260px;overflow:auto;border:1px solid var(--ax-border);border-radius:var(--ax-radius-sm)}
8668
+ .mx-steps li{display:grid;grid-template-columns:30px 1fr auto;gap:8px;padding:5px 9px;font:10px var(--ax-mono);border-bottom:1px solid var(--ax-border)}
8669
+ .mx-steps li:last-child{border-bottom:0}
8670
+ .mx-steps li[data-err="1"]{background:var(--ax-red-t)}
8671
+ .mx-steps .mx-seq{color:var(--ax-muted)}
8672
+
8673
+ /* --- shared bits ---------------------------------------------------- */
8674
+ .mx-item{display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;text-align:left;color:var(--ax-text);font:inherit;text-decoration:none;cursor:pointer}
8675
+ .mx-item:hover,.mx-item:focus-visible{border-color:var(--ax-accent);text-decoration:none;outline:none}
8676
+ .mx-item[hidden]{display:none}.mx-item .ax-avatar{width:34px;height:34px;border-radius:var(--ax-radius-sm)}
8677
+ .mx-item .ax-row-card__actions{flex-shrink:0}.mx-item .ax-sub{min-width:0}
8678
+ .mx-item .ax-sub code{font:11px var(--ax-mono);color:var(--ax-muted)}
8679
+ .mx-summary{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ax-muted)}
8680
+ .mx-node-meta{font:11px var(--ax-mono);color:var(--ax-muted)}
8681
+ .mx-empty{padding:28px 18px;text-align:center;color:var(--ax-muted);font-size:12px;border:1px dashed var(--ax-border-2);border-radius:var(--ax-radius-lg);background:var(--ax-surface)}
8682
+ .mx-link{display:inline-block;margin-top:14px;color:var(--ax-accent);font-size:12px;font-weight:600;text-decoration:none}
8683
+ .mx-link:hover{text-decoration:underline}
8684
+ .mx-scrim{position:fixed;inset:0;background:color-mix(in oklch,var(--ax-bg) 55%,black);z-index:29}
8685
+ .mx-drawer{position:fixed;z-index:30;top:0;right:0;width:min(520px,calc(100vw - 20px));height:100vh;box-sizing:border-box;background:var(--ax-surface);border-left:var(--ax-border-w) solid var(--ax-border-2);transform:translateX(102%);transition:transform 180ms ease;overflow:auto;box-shadow:-12px 0 36px rgba(0,0,0,.2)}
8686
+ .mx-drawer.is-open{transform:translateX(0)}
8687
+ .mx-drawer__head{position:sticky;top:0;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 20px;background:var(--ax-surface);border-bottom:var(--ax-border-w) solid var(--ax-border);z-index:1}
8688
+ .mx-drawer__head .ax-kicker{font:10px var(--ax-mono);letter-spacing:.1em;text-transform:uppercase;color:var(--ax-muted);margin-bottom:4px}
8689
+ .mx-drawer__head h2{margin:0;font-size:18px;font-weight:600;letter-spacing:-.01em}
8690
+ .mx-drawer__head .ax-btn{padding:6px 10px;font-size:11px;box-shadow:none}
8691
+ .mx-drawer__body{padding:20px}
8692
+ .mx-detail{display:grid;gap:16px}
8693
+ .mx-detail h3{margin:0 0 8px;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--ax-muted);font-family:var(--ax-mono)}
8694
+ .mx-detail dl{display:grid;grid-template-columns:118px 1fr;gap:9px 12px;margin:0;font-size:12px}
8695
+ .mx-detail dt{color:var(--ax-muted);font-family:var(--ax-mono);font-size:10px;text-transform:uppercase;letter-spacing:.05em}
8696
+ .mx-detail dd{margin:0;word-break:break-word}
8697
+ .mx-detail pre{margin:0;padding:14px;background:var(--ax-bg);border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-sm);white-space:pre-wrap;font:11px/1.55 var(--ax-mono)}
8698
+ .mx-verdict{display:inline-flex;align-items:center;gap:6px;font-weight:600;font-size:12px}
8699
+ .mx-verdict i{width:10px;height:10px;border-radius:2px;font-style:normal}
8700
+
8701
+ @media(max-width:860px){
8702
+ .mx-content{padding:0 16px 40px}
8703
+ .mx-columns,.mx-agent-grid,.mx-two{grid-template-columns:1fr}
8704
+ .mx-section{margin-bottom:24px}
8705
+ .mx-lane{grid-template-columns:1fr;gap:6px}
8706
+ .mx-lane__tot{text-align:left}
8707
+ .mx-axis{padding-left:0}
8708
+ .mx-bar{grid-template-columns:96px minmax(0,1fr)}
8709
+ .mx-bar__val{grid-column:1 / -1;text-align:right}
8710
+ .mx-life{grid-template-columns:1fr;gap:8px}
8711
+ .mx-life__meta{text-align:left}
8712
+ .mx-section .ax-section-head__text .ax-lead{display:none}
8713
+ .mx-summary{max-width:56vw}
8714
+ }
8715
+ @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
8716
+ `;var Ca=`<script>
8717
+ window.MX=(function(){
8718
+ var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
8719
+ function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
8720
+ function num(v){return Number(v||0).toLocaleString()}
8721
+ /** "1 turn" / "2 turns" \u2014 a count reads as sloppy without it. */
8722
+ function plural(n,one,many){return num(n)+' '+(Number(n)===1?one:(many||one+'s'))}
8723
+ function pct(part,total){return total?Math.round(part/total*1000)/10+'%':'0%'}
8724
+ function age(v){if(!v)return 'unknown';var s=Math.max(0,(Date.now()-new Date(v).getTime())/1000);
8725
+ if(s<60)return Math.floor(s)+'s ago';if(s<3600)return Math.floor(s/60)+'m ago';
8726
+ if(s<86400)return Math.floor(s/3600)+'h ago';return Math.floor(s/86400)+'d ago'}
8727
+ function dur(ms){if(!Number.isFinite(ms)||ms==null)return '-';
8728
+ if(ms<1000)return ms+'ms';if(ms<60000)return (ms/1000).toFixed(1)+'s';
8729
+ if(ms<3600000)return (ms/60000).toFixed(1)+'m';return (ms/3600000).toFixed(1)+'h'}
8730
+ function hours(h){return h>=1?h.toFixed(1)+'h':Math.round(h*60)+'m'}
8731
+ function day(iso){var p=String(iso||'').split('-');return p.length===3?p[2]+'/'+p[1]:iso}
8732
+ function when(ms){return ms?new Date(ms).toLocaleString():'-'}
8733
+
8734
+ var drawer,scrim,closeBtn,lastFocus=null;
8735
+ function mount(){
8736
+ drawer=document.getElementById('mx-drawer');
8737
+ scrim=document.getElementById('mx-scrim');
8738
+ closeBtn=document.getElementById('mx-close');
8739
+ if(!drawer)return;
8740
+ closeBtn.addEventListener('click',close);
8741
+ scrim.addEventListener('click',close);
8742
+ document.addEventListener('keydown',function(e){if(e.key==='Escape'&&drawer.classList.contains('is-open'))close()});
8743
+ }
8744
+ function open(kicker,title,html){
8745
+ lastFocus=document.activeElement;
8746
+ document.getElementById('mx-drawer-kicker').textContent=kicker;
8747
+ document.getElementById('mx-drawer-title').textContent=title;
8748
+ document.getElementById('mx-drawer-body').innerHTML=html;
8749
+ drawer.classList.add('is-open');drawer.setAttribute('aria-hidden','false');
8750
+ scrim.hidden=false;closeBtn.focus();
8751
+ }
8752
+ function close(){
8753
+ if(!drawer)return;
8754
+ drawer.classList.remove('is-open');drawer.setAttribute('aria-hidden','true');
8755
+ scrim.hidden=true;
8756
+ if(lastFocus&&lastFocus.focus)lastFocus.focus();
8757
+ }
8758
+ function body(){return document.getElementById('mx-drawer-body')}
8759
+
8760
+ /** Definition list from [label, value] pairs. Values are escaped. */
8761
+ function fields(pairs){
8762
+ return '<dl>'+pairs.map(function(f){
8763
+ return '<dt>'+esc(f[0])+'</dt><dd>'+esc(f[1])+'</dd>'}).join('')+'</dl>';
8764
+ }
8765
+ function section(title,html){return '<div><h3>'+esc(title)+'</h3>'+html+'</div>'}
8766
+
8767
+ /** Verdicts carry a colour AND a shape AND a label \u2014 never colour alone. */
8768
+ var VERDICT={
8769
+ 'healthy':{label:'Healthy',color:'var(--mx-good)',shape:'circle',
8770
+ why:'Output tracks the runtime it spends.'},
8771
+ 'fragile':{label:'Fragile',color:'var(--mx-warn)',shape:'circle',
8772
+ why:'At least 30% of attempts fail.'},
8773
+ 'zombie':{label:'No real output',color:'var(--mx-serious)',shape:'square',
8774
+ why:'Succeeds, runs a minute or more, returns under 25 tokens.'},
8775
+ 'never-succeeded':{label:'Never succeeded',color:'var(--mx-crit)',shape:'triangle',
8776
+ why:'Every recorded attempt failed. Still scheduled.'}
8777
+ };
8778
+ function verdict(v){return VERDICT[v]||VERDICT.healthy}
8779
+ function mark(v,x,y,r){
8780
+ var c=verdict(v).color;
8781
+ if(verdict(v).shape==='square')
8782
+ return '<rect class="mx-mark" x="'+(x-r)+'" y="'+(y-r)+'" width="'+(r*2)+'" height="'+(r*2)+'" rx="2" fill="'+c+'"/>';
8783
+ if(verdict(v).shape==='triangle')
8784
+ return '<path d="M '+x+' '+(y-r*1.15)+' L '+(x+r*1.1)+' '+(y+r*0.8)+' L '+(x-r*1.1)+' '+(y+r*0.8)+' Z" fill="'+c+'"/>';
8785
+ return '<circle cx="'+x+'" cy="'+y+'" r="'+r+'" fill="'+c+'"/>';
8786
+ }
8787
+ function verdictChip(v){
8788
+ var d=verdict(v);
8789
+ return '<span class="mx-verdict"><i style="background:'+d.color+'"></i>'+esc(d.label)+'</span>';
8790
+ }
8791
+
8792
+ var CAUSE={
8793
+ auth:'Authentication / entitlement',
8794
+ quota:'Usage limit reached',
8795
+ connectivity:'Network or DNS',
8796
+ overload:'Provider overloaded',
8797
+ timeout:'Ran past its time limit',
8798
+ crash:'Runtime crashed',
8799
+ misconfig:'Configuration or missing binary',
8800
+ other:'Unclassified'
8801
+ };
8802
+ function causeLabel(id){return CAUSE[id]||id}
8803
+
8804
+ /** Health-strip cards are written by whichever view owns the number, so
8805
+ * the setter lives here rather than in one of them. */
8806
+ function setHealth(index,value,kind,label){
8807
+ var card=document.querySelectorAll('#mx-health .ax-health-card')[index];
8808
+ if(!card)return;
8809
+ card.querySelector('.ax-hc-num').textContent=String(value);
8810
+ card.querySelector('.ax-hc-dot').className='ax-hc-dot ax-hc-dot--'+kind;
8811
+ if(label){var l=card.querySelector('.ax-hc-lbl');if(l)l.textContent=label}
8812
+ }
8813
+
8814
+ function get(url){
8815
+ return fetch(url,{headers:{Accept:'application/json'}}).then(function(r){
8816
+ if(!r.ok)throw new Error('HTTP '+r.status);return r.json()});
8817
+ }
8818
+
8819
+ mount();
8820
+ return {esc:esc,num:num,plural:plural,pct:pct,age:age,dur:dur,hours:hours,day:day,when:when,
8821
+ open:open,close:close,body:body,fields:fields,section:section,
8822
+ verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
8823
+ setHealth:setHealth,get:get};
8824
+ })();
8825
+ </script>`;var Aa=`<script>
8826
+ window.MXD=(function(){
8827
+ function el(id){return document.getElementById(id)}
8828
+ function tz(){return -new Date().getTimezoneOffset()}
8829
+ function tiles(items){
8830
+ return '<div class="mx-stats">'+items.map(function(t){
8831
+ return '<div class="mx-stat"><b>'+MX.esc(t[0])+'</b><span>'+MX.esc(t[1])+'</span></div>';
8832
+ }).join('')+'</div>';
8833
+ }
8834
+ function miniBars(rows,color){
8835
+ if(!rows.length)return '<p class="mx-note">None recorded.</p>';
8836
+ var max=Math.max.apply(null,rows.map(function(r){return r[1]}))||1;
8837
+ return '<div class="mx-bars">'+rows.map(function(r){
8838
+ return '<div class="mx-bar"><span class="mx-bar__label">'+MX.esc(r[0])+'</span>'
8839
+ +'<span class="mx-bar__track"><span class="mx-bar__fill" style="width:'
8840
+ +Math.max(2,r[1]/max*100)+'%;background:'+color+';opacity:.6"></span></span>'
8841
+ +'<span class="mx-bar__val">'+MX.num(r[1])+'</span></div>';
8842
+ }).join('')+'</div>';
8843
+ }
8844
+
8845
+ // --- One activity column ------------------------------------------
8846
+ //
8847
+ // The column the operator clicked belongs to ONE lane, so the drawer is
8848
+ // scoped to that lane by default. Opening the whole day from a Scheduled
8849
+ // column would answer a question nobody asked, and the numbers would not
8850
+ // match the bar that was clicked.
8851
+ var LANE_NAME={cron:'Scheduled',workflow:'Workflow',direct:'Direct'};
8852
+ function laneOf(channel){
8853
+ return channel==='cron'?'cron':channel==='workflow'?'workflow':'direct';
8854
+ }
8855
+ function openDay(day,lane){
8856
+ MX.open('Activity',day+(lane?' \xB7 '+(LANE_NAME[lane]||lane):''),
8857
+ '<div class="mx-detail"><div id="mx-day">'
8858
+ +'<div class="mx-empty">Loading '+MX.esc(day)+'...</div></div></div>');
8859
+ MX.get('/api/mesh/day?day='+encodeURIComponent(day)+'&tzOffset='+tz()+'&limit=60')
8860
+ .then(function(d){renderDay(d,lane)})
8861
+ .catch(function(e){var h=el('mx-day');if(h)h.innerHTML='<div class="mx-empty">'+MX.esc(e.message)+'</div>'});
8862
+ }
8863
+
8864
+ /** Narrow a fleet day to one lane, using the same origin rule the lanes
8865
+ * themselves are built with. Causes cannot be split this way \u2014 they are
8866
+ * aggregated per day, not per channel \u2014 so they stay fleet-wide and say so. */
8867
+ function scopeDay(d,lane){
8868
+ if(!lane)return {scoped:d,all:d,lane:null};
8869
+ var origins=d.origins.filter(function(o){return laneOf(o.channel)===lane});
8870
+ var conversations=d.conversations.filter(function(c){return laneOf(c.channel)===lane});
8871
+ var totals={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0};
8872
+ origins.forEach(function(o){totals.runs+=o.runs;totals.errors+=o.errors;totals.ms+=o.ms});
8873
+ conversations.forEach(function(c){totals.inputTokens+=c.inputTokens;totals.outputTokens+=c.outputTokens});
8874
+ return {scoped:{day:d.day,nodes:d.nodes,totals:totals,origins:origins,causes:[],conversations:conversations},all:d,lane:lane};
8875
+ }
8876
+ function renderDay(full,lane){
8877
+ var host=el('mx-day');if(!host)return;
8878
+ var view=scopeDay(full,lane),d=view.scoped;
8879
+ if(!d.totals.runs){
8880
+ host.innerHTML='<div class="mx-empty">No '+MX.esc(lane?(LANE_NAME[lane]||lane).toLowerCase()+' ':'')
8881
+ +'work ran on '+MX.esc(d.day)+'.</div>';
8882
+ return;
8883
+ }
8884
+ var down=d.nodes.filter(function(n){return !n.ok});
8885
+ var html=tiles([
8886
+ ['Runs',MX.num(d.totals.runs)],
8887
+ ['Failed',MX.num(d.totals.errors)+' ('+MX.pct(d.totals.errors,d.totals.runs)+')'],
8888
+ ['Runtime',MX.dur(d.totals.ms)],
8889
+ ['Output',MX.num(d.totals.outputTokens)+' tok']
8890
+ ]);
8891
+ if(down.length)html+='<p class="mx-note">Missing '+MX.esc(down.map(function(n){return n.name}).join(', '))+' \u2014 these totals are partial.</p>';
8892
+ if(lane)html+='<p class="mx-note">Scoped to the '+MX.esc((LANE_NAME[lane]||lane).toLowerCase())
8893
+ +' lane you selected. The whole day ran '+MX.num(view.all.totals.runs)+' across every origin.</p>';
8894
+ html+=MX.section(lane?'Channels in this lane':'By origin',miniBars(d.origins.map(function(o){
8895
+ return [o.channel+(o.errors?' ('+o.errors+' failed)':''),o.runs]}),'var(--ax-accent)'));
8896
+ // Causes are grouped per day, not per channel, so they cannot be split
8897
+ // by lane without inventing an attribution. Show the day's, labelled.
8898
+ if(view.all.causes.length)html+=MX.section('Failures'+(lane?' (whole day)':''),
8899
+ miniBars(view.all.causes.map(function(c){return [MX.causeLabel(c.cause),c.count]}),'var(--mx-crit)'));
8900
+ // 60 is the fan-out cap per node, so a full list may be truncated \u2014
8901
+ // label it rather than implying the day had exactly this many.
8902
+ var convCap=d.conversations.length>=60*Math.max(1,d.nodes.filter(function(n){return n.ok}).length);
8903
+ html+=MX.section('Conversations that day ('+(convCap?'busiest '+d.conversations.length:d.conversations.length)+')',
8904
+ '<div class="mx-convs">'+d.conversations.map(function(c,i){
8905
+ return '<button class="mx-conv" type="button" data-conv="'+i+'">'
8906
+ +'<span class="mx-conv__id"><b>'+MX.esc(c.agent)+'</b><span>'+MX.esc(c.channel)+' \xB7 '+MX.esc(c.chatId)+'</span></span>'
8907
+ +'<span class="mx-conv__meta">'+MX.plural(c.turns,'turn')+(c.errors?' \xB7 '+MX.num(c.errors)+' failed':'')
8908
+ +'<br>'+MX.dur(c.ms)+' \xB7 '+MX.num(c.outputTokens)+' tok out</span></button>';
8909
+ }).join('')+'</div><p class="mx-note">Ordered by runtime. Select one for its full history.</p>');
8910
+ host.innerHTML=html;
8911
+ host.querySelectorAll('[data-conv]').forEach(function(b){
8912
+ b.addEventListener('click',function(){openConversation(d.conversations[Number(b.dataset.conv)])});
8913
+ });
8914
+ }
8915
+
8916
+ // --- One recurring job --------------------------------------------
8917
+ function openJob(j){
8918
+ var m=MX.verdict(j.verdict);
8919
+ MX.open('Recurring job',j.label,'<div class="mx-detail">'
8920
+ +'<div>'+MX.verdictChip(j.verdict)+'<p class="mx-note">'+MX.esc(m.why)+'</p></div>'
8921
+ +MX.fields([['Node',j.node],['Agent',j.agent],['Kind',j.kind],
8922
+ ['Runs',MX.num(j.runs)],['Succeeded',MX.num(j.okRuns)],['Failed',MX.num(j.errors)],
8923
+ ['Runtime',MX.hours(j.hours)],['Avg run',j.avgMinutes+' min'],
8924
+ ['Avg output',MX.num(Math.round(j.avgOutput))+' tokens'],['Last run',MX.when(j.lastAt)]])
8925
+ +'<div id="mx-drill">'+MX.section('Attempts','<div class="mx-empty">Loading attempts...</div>')+'</div></div>');
8926
+ MX.get('/api/mesh/job?node='+encodeURIComponent(j.nodeUrl)+'&kind='+encodeURIComponent(j.kind)
8927
+ +'&key='+encodeURIComponent(j.label)+'&limit=150')
8928
+ .then(function(r){renderRunGrid(j.nodeUrl,r.runs||[])})
8929
+ .catch(function(e){var t=el('mx-drill');if(t)t.innerHTML=MX.section('Attempts','<div class="mx-empty">'+MX.esc(e.message)+'</div>')});
8930
+ }
8931
+
8932
+ // --- One conversation, whole life ---------------------------------
8933
+ function openConversation(c){
8934
+ MX.open('Conversation',c.agent,'<div class="mx-detail">'
8935
+ +MX.fields([['Node',c.node],['Channel',c.channel],['Conversation',c.chatId]])
8936
+ +'<div id="mx-conv"><div class="mx-empty">Loading summary...</div></div>'
8937
+ +'<div id="mx-drill">'+MX.section('Attempts','<div class="mx-empty">Loading attempts...</div>')+'</div></div>');
8938
+ var q='node='+encodeURIComponent(c.nodeUrl)+'&agent='+encodeURIComponent(c.agent)
8939
+ +'&channel='+encodeURIComponent(c.channel)+'&chat='+encodeURIComponent(c.chatId);
8940
+ MX.get('/api/mesh/conversation?'+q+'&tzOffset='+tz())
8941
+ .then(renderConversation)
8942
+ .catch(function(e){var h=el('mx-conv');if(h)h.innerHTML='<div class="mx-empty">'+MX.esc(e.message)+'</div>'});
8943
+ MX.get('/api/mesh/thread?'+q+'&limit=150')
8944
+ .then(function(r){renderRunGrid(c.nodeUrl,r.runs||[])})
8945
+ .catch(function(e){var t=el('mx-drill');if(t)t.innerHTML=MX.section('Attempts','<div class="mx-empty">'+MX.esc(e.message)+'</div>')});
8946
+ }
8947
+ function renderConversation(s){
8948
+ var host=el('mx-conv');if(!host)return;
8949
+ if(!s.found){host.innerHTML='<div class="mx-empty">No history for this conversation.</div>';return}
8950
+ // Cache reads are shown apart from fresh input on purpose: a long
8951
+ // thread is mostly cache, and one "tokens" number would make every
8952
+ // conversation look equally heavy.
8953
+ var html=tiles([
8954
+ ['Turns',MX.num(s.turns)],
8955
+ ['Failed',MX.num(s.errors)+(s.turns?' ('+MX.pct(s.errors,s.turns)+')':'')],
8956
+ ['Total time',MX.dur(s.totalMs)],
8957
+ ['Avg turn',MX.dur(s.avgMs)],
8958
+ ['Longest turn',MX.dur(s.maxMs)],
8959
+ ['Alive',MX.num(s.spanDays)+' days'],
8960
+ ['Used on',MX.num(s.activeDays)+' days'],
8961
+ ['Session cuts',MX.num(s.cuts.total)]
8962
+ ]);
8963
+ html+=MX.section('Tokens',tiles([
8964
+ ['Input',MX.num(s.inputTokens)],
8965
+ ['Output',MX.num(s.outputTokens)],
8966
+ ['Cache read',MX.num(s.cacheReadTokens)],
8967
+ ['Cache write',MX.num(s.cacheCreateTokens)]
8968
+ ])+'<p class="mx-note">Summed over every recorded turn. Cache reads are kept separate from fresh input.</p>');
8969
+ html+=MX.section('Span',MX.fields([
8970
+ ['First turn',MX.when(s.firstAt)],['Last turn',MX.when(s.lastAt)],
8971
+ ['Busiest day',s.busiestDay?s.busiestDay.day+' ('+MX.plural(s.busiestDay.turns,'turn')+')':'-'],
8972
+ ['Models',s.models.map(function(m){return m.model+' x'+m.turns}).join(', ')||'-']]));
8973
+ if(s.cuts.total)html+=MX.section('Session cuts',miniBars(s.cuts.byReason.map(function(r){
8974
+ return [r.reason,r.count]}),'var(--mx-warn)'));
8975
+ if(s.causes.length)html+=MX.section('Failure causes',miniBars(s.causes.map(function(c){
8976
+ return [MX.causeLabel(c.cause),c.count]}),'var(--mx-crit)'));
8977
+ html+=MX.section('Tools used',
8978
+ (s.tools.length?miniBars(s.tools.map(function(t){return [t.tool,t.used]}),'var(--ax-accent)')
8979
+ :'<p class="mx-note">No step ledger survived retention for this conversation.</p>')
8980
+ +'<p class="mx-note">Counted across the '+MX.num(s.toolRunsCounted)+' of '+MX.num(s.turns)
8981
+ +' turns whose steps are still retained.</p>');
8982
+ host.innerHTML=html;
8983
+ }
8984
+
8985
+ // --- Attempts, then one attempt -----------------------------------
8986
+ function renderRunGrid(nodeUrl,runs){
8987
+ var host=el('mx-drill');if(!host)return;
8988
+ if(!runs.length){host.innerHTML=MX.section('Attempts','<div class="mx-empty">No individual attempts retained.</div>');return}
8989
+ var cells=runs.map(function(r,i){
8990
+ var c=r.status==='ok'?'var(--mx-good)':r.status==='timeout'?'var(--mx-warn)':'var(--mx-crit)';
8991
+ return '<button class="mx-run" type="button" data-run="'+i+'" aria-pressed="false" style="background:'+c+'"'
8992
+ +' title="'+MX.esc(new Date(r.startedAt).toLocaleString()+' \xB7 '+r.status+' \xB7 '+MX.dur(r.durationMs))+'"'
8993
+ +' aria-label="'+MX.esc(new Date(r.startedAt).toLocaleString()+', '+r.status)+'"></button>';
8994
+ }).join('');
8995
+ // Deliberately NOT windowed: "has this ever succeeded?" is a question
8996
+ // about all of history. The counters above it ARE windowed, so say so.
8997
+ var capped=runs.length>=150;
8998
+ host.innerHTML=MX.section('Attempts ('+(capped?'latest 150':runs.length)+', newest first)',
8999
+ '<div class="mx-runs">'+cells+'</div>'
9000
+ +'<p class="mx-note">Full recorded history, not limited to the selected window. Select an attempt to see what it touched.</p>')
9001
+ +'<div id="mx-run-detail"></div>';
9002
+ host.querySelectorAll('[data-run]').forEach(function(b){
9003
+ b.addEventListener('click',function(){
9004
+ host.querySelectorAll('[data-run]').forEach(function(o){o.setAttribute('aria-pressed','false')});
9005
+ b.setAttribute('aria-pressed','true');
9006
+ openRun(nodeUrl,runs[Number(b.dataset.run)]);
9007
+ });
9008
+ });
9009
+ }
9010
+ function openRun(nodeUrl,run){
9011
+ var host=el('mx-run-detail');if(!host)return;
9012
+ host.innerHTML=MX.section('Attempt','<div class="mx-empty">Loading steps...</div>');
9013
+ MX.get('/api/mesh/run?node='+encodeURIComponent(nodeUrl)+'&task='+encodeURIComponent(run.taskId))
9014
+ .then(function(s){
9015
+ var touched='<div class="mx-touch">'
9016
+ +'<span'+(s.reads?'':' class="is-zero"')+'>'+s.reads+' read</span>'
9017
+ +'<span'+(s.writes?'':' class="is-zero"')+'>'+s.writes+' write</span>'
9018
+ +'<span'+(s.sends?'':' class="is-zero"')+'>'+s.sends+' send</span>'
9019
+ +s.tools.map(function(t){return '<span>'+MX.esc(t.tool)+' x'+t.used+(t.failed?' ('+t.failed+' failed)':'')+'</span>'}).join('')
9020
+ +'</div>';
9021
+ var steps=s.steps.length
9022
+ ? '<ul class="mx-steps">'+s.steps.map(function(st){
9023
+ return '<li data-err="'+(st.status==='error'?1:0)+'"><span class="mx-seq">'+st.seq+'</span>'
9024
+ +'<span>'+MX.esc(st.action||st.name)+'</span><span>'+(st.ms==null?'':MX.dur(st.ms))+'</span></li>'}).join('')+'</ul>'
9025
+ : '<div class="mx-empty">Steps for this attempt were pruned by retention. Its totals above are still exact.</div>';
9026
+ host.innerHTML=MX.section('Attempt '+run.taskId.slice(-8),
9027
+ MX.fields([['Started',MX.when(s.startedAt)],['Duration',MX.dur(s.durationMs)],
9028
+ ['Status',s.status],['Model',s.model||'default'],
9029
+ ['Output',MX.num(s.outputTokens||0)+' tokens'],
9030
+ ['Cause',s.cause?MX.causeLabel(s.cause):'-']])
9031
+ +'<p class="mx-note">What this attempt touched</p>'+touched)
9032
+ +MX.section('Steps',steps);
9033
+ })
9034
+ .catch(function(e){host.innerHTML=MX.section('Attempt','<div class="mx-empty">'+MX.esc(e.message)+'</div>')});
9035
+ }
9036
+
9037
+ return {openDay:openDay,openJob:openJob,openConversation:openConversation};
9038
+ })();
9039
+ </script>`;var Ma=`<script>
9040
+ (function(){
9041
+ var LANES=[
9042
+ {id:'cron',name:'Scheduled',hint:'cron jobs'},
9043
+ {id:'workflow',name:'Workflow',hint:'dataflow runs'},
9044
+ {id:'direct',name:'Direct',hint:'chat, API, git hosts'}
9045
+ ];
9046
+ var state={days:30,data:null,channel:'all',threadLimit:25};
9047
+ var tip=null;
9048
+
9049
+ function el(id){return document.getElementById(id)}
9050
+ function showTip(host,html,ev){
9051
+ if(!tip){tip=document.createElement('div');tip.className='mx-tip';document.body.appendChild(tip)}
9052
+ tip.innerHTML=html;tip.style.display='block';
9053
+ var pad=14,w=tip.offsetWidth,h=tip.offsetHeight;
9054
+ var x=Math.min(window.innerWidth-w-8,Math.max(8,ev.clientX+pad));
9055
+ var y=Math.max(8,ev.clientY-h-pad);
9056
+ tip.style.position='fixed';tip.style.left=x+'px';tip.style.top=y+'px';
9057
+ }
9058
+ function hideTip(){if(tip)tip.style.display='none'}
9059
+
9060
+ // --- Activity lanes: one small multiple per origin. Each lane is a
9061
+ // single series scaled to ITS OWN peak, so a 2,400-run workflow day
9062
+ // cannot flatten a 60-run cron day. The peak is printed next to the
9063
+ // lane name \u2014 without it a self-scaled lane would be misleading.
9064
+ function renderLanes(d){
9065
+ var root=el('mx-lanes');
9066
+ if(!d.days.length){root.innerHTML='<div class="mx-empty">No runs recorded in this window.</div>';el('mx-axis').innerHTML='';return}
9067
+ root.innerHTML=LANES.map(function(lane){
9068
+ var ok=[],fail=[],peak=0,tot=0,totFail=0;
9069
+ d.days.forEach(function(day){
9070
+ var b=day[lane.id]||[0,0];
9071
+ ok.push(b[0]);fail.push(b[1]);
9072
+ peak=Math.max(peak,b[0]+b[1]);tot+=b[0]+b[1];totFail+=b[1];
9073
+ });
9074
+ var cols=d.days.map(function(day,i){
9075
+ var total=ok[i]+fail[i];
9076
+ if(!total)return '<button class="mx-col" type="button" data-lane="'+lane.id+'" data-i="'+i+'" aria-label="'+MX.esc(day.day)+': no runs. Open this day"><i class="is-empty"></i></button>';
9077
+ var hOk=Math.max(total?2:0,Math.round(ok[i]/peak*54));
9078
+ var hFail=fail[i]?Math.max(2,Math.round(fail[i]/peak*54)):0;
9079
+ return '<button class="mx-col" type="button" data-lane="'+lane.id+'" data-i="'+i+'"'
9080
+ +' aria-label="'+MX.esc(day.day)+': '+total+' runs, '+fail[i]+' failed. Open this day">'
9081
+ +(hFail?'<i class="is-fail" style="height:'+hFail+'px"></i>':'')
9082
+ +'<i class="is-base" style="height:'+hOk+'px;background:var(--mx-lane-'+lane.id+')"></i>'
9083
+ +'</button>';
9084
+ }).join('');
9085
+ return '<div class="mx-lane">'
9086
+ +'<div class="mx-lane__name"><span class="mx-lane__swatch" style="background:var(--mx-lane-'+lane.id+')"></span>'
9087
+ +'<div>'+MX.esc(lane.name)+'<div class="mx-lane__peak">peak '+MX.num(peak)+'/day</div></div></div>'
9088
+ +'<div class="mx-cols">'+cols+'</div>'
9089
+ +'<div class="mx-lane__tot"><b>'+MX.num(tot)+'</b>'+MX.num(totFail)+' failed</div></div>';
9090
+ }).join('');
9091
+ el('mx-axis').innerHTML='<span>'+MX.esc(d.days[0].day)+'</span><span>'+MX.esc(d.days[d.days.length-1].day)+'</span>';
9092
+ root.querySelectorAll('.mx-col').forEach(function(b){
9093
+ function show(ev){
9094
+ var lane=b.dataset.lane,day=d.days[Number(b.dataset.i)],v=day[lane]||[0,0];
9095
+ showTip(b,'<b>'+MX.esc(day.day)+'</b><dl><dt>Ran</dt><dd>'+MX.num(v[0]+v[1])+'</dd>'
9096
+ +'<dt>Failed</dt><dd>'+MX.num(v[1])+'</dd><dt>Origin</dt><dd>'+MX.esc(lane)+'</dd></dl>'
9097
+ +'<p class="mx-tip__hint">Select for the full day</p>',ev);
9098
+ }
9099
+ b.addEventListener('mousemove',show);
9100
+ b.addEventListener('focus',function(){var r=b.getBoundingClientRect();show({clientX:r.left,clientY:r.top})});
9101
+ b.addEventListener('mouseleave',hideTip);b.addEventListener('blur',hideTip);
9102
+ b.addEventListener('click',function(){hideTip();MXD.openDay(d.days[Number(b.dataset.i)].day,b.dataset.lane)});
9103
+ });
9104
+ }
9105
+
9106
+ // --- Where it breaks: one bar per origin channel, total runs with the
9107
+ // failed share drawn on top of the same track. One measure, one hue.
9108
+ function renderOrigins(d){
9109
+ var root=el('mx-origins');
9110
+ if(!d.origins.length){root.innerHTML='<div class="mx-empty">No runs in this window.</div>';return}
9111
+ var max=d.origins[0].runs||1;
9112
+ root.innerHTML=d.origins.map(function(o,i){
9113
+ var w=Math.max(2,o.runs/max*100),fw=o.runs?o.errors/o.runs*w:0;
9114
+ return '<button class="mx-bar" type="button" data-origin="'+i+'">'
9115
+ +'<span class="mx-bar__label">'+MX.esc(o.channel)+'</span>'
9116
+ +'<span class="mx-bar__track"><span class="mx-bar__fill" style="width:'+w+'%;background:var(--ax-accent);opacity:.35"></span>'
9117
+ +(fw?'<span class="mx-bar__fail" style="left:'+(w-fw)+'%;width:'+fw+'%"></span>':'')+'</span>'
9118
+ +'<span class="mx-bar__val">'+MX.num(o.runs)+' <em>'+MX.pct(o.errors,o.runs)+' failed</em></span></button>';
9119
+ }).join('');
9120
+ root.querySelectorAll('[data-origin]').forEach(function(b){
9121
+ b.addEventListener('click',function(){
9122
+ var o=d.origins[Number(b.dataset.origin)];
9123
+ MX.open('Origin',o.channel,'<div class="mx-detail">'+MX.fields([
9124
+ ['Runs',MX.num(o.runs)],['Failed',MX.num(o.errors)],
9125
+ ['Failure rate',MX.pct(o.errors,o.runs)],['Runtime',MX.hours(o.hours)],
9126
+ ['Window',d.windowDays===0?'today so far':'last '+d.windowDays+' days']
9127
+ ])+'<p class="mx-note">Failure rate is computed over every recorded attempt on this channel, retries included. Runtime is the sum of measured task durations, not wall-clock.</p></div>');
9128
+ });
9129
+ });
9130
+ }
9131
+
9132
+ // --- Why it fails: counts per cause class. Single series, single hue.
9133
+ function renderCauses(d){
9134
+ var root=el('mx-causes');
9135
+ if(!d.causes.length){root.innerHTML='<div class="mx-empty">No failures in this window.</div>';return}
9136
+ var max=d.causes[0].count||1,total=d.causes.reduce(function(v,c){return v+c.count},0);
9137
+ root.innerHTML=d.causes.map(function(c,i){
9138
+ return '<button class="mx-bar" type="button" data-cause="'+i+'">'
9139
+ +'<span class="mx-bar__label">'+MX.esc(MX.causeLabel(c.cause))+'</span>'
9140
+ +'<span class="mx-bar__track"><span class="mx-bar__fill" style="width:'+Math.max(2,c.count/max*100)+'%;background:var(--mx-crit);opacity:.7"></span></span>'
9141
+ +'<span class="mx-bar__val">'+MX.num(c.count)+' <em>'+MX.pct(c.count,total)+'</em></span></button>';
9142
+ }).join('');
9143
+ var known=d.causes.filter(function(c){return c.cause!=='other'}).reduce(function(v,c){return v+c.count},0);
9144
+ el('mx-cause-note').textContent=(known===total
9145
+ ? 'All '+MX.num(total)+' failures matched a known cause class.'
9146
+ : MX.pct(known,total)+' of '+MX.num(total)+' failures matched a known cause class.')
9147
+ +' None of them are the agent reasoning badly \u2014 they are the environment the agent runs in.';
9148
+ root.querySelectorAll('[data-cause]').forEach(function(b){
9149
+ b.addEventListener('click',function(){
9150
+ var c=d.causes[Number(b.dataset.cause)];
9151
+ MX.open('Failure cause',MX.causeLabel(c.cause),'<div class="mx-detail">'+MX.fields([
9152
+ ['Occurrences',MX.num(c.count)],['Share of failures',MX.pct(c.count,total)],
9153
+ ['Agents hit',c.agents.join(', ')||'-']
9154
+ ])+(c.example?MX.section('Representative error','<pre>'+MX.esc(c.example)+'</pre>'):'')+'</div>');
9155
+ });
9156
+ });
9157
+ }
9158
+
9159
+ // --- Effort vs output. x = total runtime, y = mean output tokens on
9160
+ // SUCCESSFUL runs. Both log-scaled because both span four orders of
9161
+ // magnitude. The shaded band is the literal zombie rule, drawn so the
9162
+ // classification is visible rather than asserted.
9163
+ function renderScatter(d){
9164
+ var root=el('mx-scatter'),jobs=d.jobs.filter(function(j){return j.runs>0});
9165
+ if(!jobs.length){root.innerHTML='<div class="mx-empty">No recurring jobs ran in this window.</div>';return}
9166
+ // R is a deliberate right gutter, not just padding: points near the
9167
+ // maximum runtime are exactly the ones that most need a direct label.
9168
+ var W=820,H=340,L=54,R=74,T=18,B=38;
9169
+ var mins=function(j){return Math.max(j.hours*60,0.5)};
9170
+ var lx=function(m){return Math.log10(m)};
9171
+ var ly=function(t){return Math.log10(Math.max(t,0)+1)};
9172
+ var x0=lx(0.5),x1=Math.max(lx(60),Math.max.apply(null,jobs.map(function(j){return lx(mins(j))})));
9173
+ var y1=Math.max(ly(100),Math.max.apply(null,jobs.map(function(j){return ly(j.avgOutput)})));
9174
+ var px=function(m){return L+(lx(m)-x0)/(x1-x0)*(W-L-R)};
9175
+ var py=function(t){return H-B-ly(t)/y1*(H-T-B)};
9176
+ var g='';
9177
+ [1,10,60,600,6000].forEach(function(m){
9178
+ if(lx(m)<x0||lx(m)>x1)return;
9179
+ var gx=px(m),lbl=m<60?m+'m':(m/60)+'h';
9180
+ g+='<line x1="'+gx+'" y1="'+T+'" x2="'+gx+'" y2="'+(H-B)+'" stroke="var(--mx-grid)" stroke-width="1"/>'
9181
+ +'<text x="'+gx+'" y="'+(H-B+16)+'" text-anchor="middle">'+lbl+'</text>';
9182
+ });
9183
+ [0,10,100,1000,10000].forEach(function(t){
9184
+ if(ly(t)>y1)return;
9185
+ var gy=py(t);
9186
+ g+='<line x1="'+L+'" y1="'+gy+'" x2="'+(W-R)+'" y2="'+gy+'" stroke="var(--mx-grid)" stroke-width="1"/>'
9187
+ +'<text x="'+(L-8)+'" y="'+(gy+3)+'" text-anchor="end">'+MX.num(t)+'</text>';
9188
+ });
9189
+ var bandTop=py(25);
9190
+ var band='<rect x="'+L+'" y="'+bandTop+'" width="'+(W-L-R)+'" height="'+(H-B-bandTop)+'" fill="var(--mx-serious)" opacity=".08"/>'
9191
+ +'<text x="'+(W-R-4)+'" y="'+(bandTop+13)+'" text-anchor="end">under 25 tokens returned</text>';
9192
+
9193
+ // Direct labels for every job that is not healthy \u2014 but only where one
9194
+ // fits. Candidates are tried right, left, above, below; a label that
9195
+ // still collides is dropped rather than stacked into an unreadable
9196
+ // smear. Hover and keyboard focus still name every point.
9197
+ var taken=[],marks='',labels='';
9198
+ function fits(b){
9199
+ for(var i=0;i<taken.length;i++){var t=taken[i];
9200
+ if(b.x<t.x+t.w&&t.x<b.x+b.w&&b.y<t.y+t.h&&t.y<b.y+b.h)return false}
9201
+ return true;
9202
+ }
9203
+ // Pass 1: every mark, and every mark's footprint, so a label placed in
9204
+ // pass 2 can never be dropped behind a point drawn after it.
9205
+ var placed=jobs.map(function(j,i){
9206
+ var r=Math.max(4,Math.min(15,Math.sqrt(j.runs)*1.1));
9207
+ return {j:j,i:i,r:r,cx:px(mins(j)),cy:py(j.avgOutput)};
9208
+ });
9209
+ placed.forEach(function(o){
9210
+ taken.push({x:o.cx-o.r,y:o.cy-o.r,w:o.r*2,h:o.r*2});
9211
+ marks+='<g class="mx-pt" tabindex="0" role="button" data-job="'+o.i+'"'
9212
+ +' aria-label="'+MX.esc(o.j.label+', '+MX.verdict(o.j.verdict).label+', '+o.j.runs+' runs, '+Math.round(o.j.avgOutput)+' tokens average output')+'">'
9213
+ +MX.mark(o.j.verdict,o.cx,o.cy,o.r)+'</g>';
9214
+ });
9215
+ // Pass 2: label the jobs that need acting on, worst runtime first.
9216
+ placed.filter(function(o){return o.j.verdict!=='healthy'})
9217
+ .sort(function(a,b){return b.j.hours-a.j.hours})
9218
+ .forEach(function(o){
9219
+ // Roboto Mono at 10px advances ~6.1px per character; the estimate
9220
+ // must over- rather than under-shoot or two labels touch.
9221
+ var w=o.j.label.length*6.2+10,h=13;
9222
+ var spots=[[o.cx+o.r+5,o.cy-h/2],[o.cx-o.r-5-w,o.cy-h/2],[o.cx-w/2,o.cy-o.r-4-h],[o.cx-w/2,o.cy+o.r+4]];
9223
+ for(var k=0;k<spots.length;k++){
9224
+ var b={x:spots[k][0],y:spots[k][1],w:w,h:h};
9225
+ if(b.x<L||b.x+w>W-2||b.y<T-6||b.y+h>H-B+2)continue;
9226
+ if(!fits(b))continue;
9227
+ taken.push(b);
9228
+ labels+='<text class="mx-lbl" x="'+b.x+'" y="'+(b.y+10)+'">'+MX.esc(o.j.label)+'</text>';
9229
+ break;
9230
+ }
9231
+ });
9232
+ root.innerHTML='<svg viewBox="0 0 '+W+' '+H+'" role="img" aria-label="Runtime against output for every recurring job">'
9233
+ +band+g
9234
+ +'<line x1="'+L+'" y1="'+(H-B)+'" x2="'+(W-R)+'" y2="'+(H-B)+'" stroke="var(--ax-border-2)" stroke-width="2"/>'
9235
+ +'<text x="'+L+'" y="'+(H-6)+'">total runtime in window</text>'
9236
+ +'<text x="'+(L-8)+'" y="'+(T-5)+'" text-anchor="end">tokens</text>'
9237
+ +marks+labels+'</svg>';
9238
+ el('mx-scatter-legend').innerHTML=['healthy','fragile','zombie','never-succeeded'].map(function(v){
9239
+ var m=MX.verdict(v);
9240
+ return '<span><svg viewBox="-8 -8 16 16">'+MX.mark(v,0,0,6)+'</svg>'+MX.esc(m.label)+' \u2014 '+MX.esc(m.why)+'</span>';
9241
+ }).join('');
9242
+ root.querySelectorAll('[data-job]').forEach(function(gEl){
9243
+ var j=jobs[Number(gEl.dataset.job)];
9244
+ function show(ev){showTip(gEl,'<b>'+MX.esc(j.label)+'</b>'+MX.esc(j.agent)+' on '+MX.esc(j.node)
9245
+ +'<dl><dt>Verdict</dt><dd>'+MX.esc(MX.verdict(j.verdict).label)+'</dd>'
9246
+ +'<dt>Runs</dt><dd>'+MX.num(j.runs)+'</dd><dt>Failed</dt><dd>'+MX.num(j.errors)+'</dd>'
9247
+ +'<dt>Runtime</dt><dd>'+MX.hours(j.hours)+'</dd><dt>Avg run</dt><dd>'+j.avgMinutes+'m</dd>'
9248
+ +'<dt>Avg output</dt><dd>'+MX.num(Math.round(j.avgOutput))+' tok</dd></dl>',ev)}
9249
+ gEl.addEventListener('mousemove',show);
9250
+ gEl.addEventListener('mouseleave',hideTip);gEl.addEventListener('blur',hideTip);
9251
+ gEl.addEventListener('focus',function(){var r=gEl.getBoundingClientRect();show({clientX:r.left,clientY:r.top})});
9252
+ gEl.addEventListener('click',function(){MXD.openJob(j)});
9253
+ gEl.addEventListener('keydown',function(ev){if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();MXD.openJob(j)}});
9254
+ });
9255
+ }
9256
+
9257
+ function renderThreads(d){
9258
+ var root=el('mx-threads');
9259
+ var chans=['all'].concat(d.origins.map(function(o){return o.channel}));
9260
+ el('mx-thread-chips').innerHTML=chans.map(function(c){
9261
+ return '<button class="mx-chip" type="button" data-chan="'+MX.esc(c)+'" aria-pressed="'+(state.channel===c)+'">'+MX.esc(c==='all'?'All channels':c)+'</button>';
9262
+ }).join('');
9263
+ el('mx-thread-chips').querySelectorAll('[data-chan]').forEach(function(b){
9264
+ b.addEventListener('click',function(){state.channel=b.dataset.chan;state.threadLimit=25;renderThreads(d)});
9265
+ });
9266
+ var rows=d.threads.filter(function(t){return state.channel==='all'||t.channel===state.channel});
9267
+ if(!rows.length){root.innerHTML='<div class="mx-empty">No threads on this channel in the window.</div>';return}
9268
+ var t0=d.windowStart,t1=d.generatedAt,span=Math.max(1,t1-t0);
9269
+ var CUT={'tier-2':'var(--mx-warn)','max-turns':'var(--ax-accent)','stale':'var(--ax-muted)'};
9270
+ var shown=rows.slice(0,state.threadLimit);
9271
+ root.innerHTML=shown.map(function(t,i){
9272
+ var left=Math.max(0,(t.firstAt-t0)/span*100);
9273
+ var width=Math.min(100-left,Math.max(0.6,(t.lastAt-t.firstAt)/span*100));
9274
+ // Ticks sit at the real timestamp of each recorded cut. When a thread
9275
+ // has more cuts than the payload carries, the count says so.
9276
+ var ticks=(t.cuts||[]).map(function(c){
9277
+ var pos=(c.at-t0)/span*100;
9278
+ if(pos<0||pos>100)return '';
9279
+ return '<span class="mx-life__tick" style="left:'+pos+'%;background:'+(CUT[c.reason]||'var(--ax-muted)')+'"></span>';
9280
+ }).join('');
9281
+ var cutLabel=t.rotations>t.cutsShown
9282
+ ? MX.num(t.cutsShown)+' of '+MX.num(t.rotations)+' cuts'
9283
+ : MX.num(t.rotations)+' cuts';
9284
+ return '<button class="mx-life" type="button" data-thread="'+i+'">'
9285
+ +'<span class="mx-life__id"><b>'+MX.esc(t.agent)+'</b><span>'+MX.esc(t.channel)+' \xB7 '+MX.esc(t.chatId)+'</span></span>'
9286
+ +'<span class="mx-life__span"><span class="mx-life__track" style="left:'+left+'%;width:'+width+'%"></span>'+ticks+'</span>'
9287
+ +'<span class="mx-life__meta"><b>'+MX.num(t.runs)+'</b> runs \xB7 '+MX.num(t.errors)+' failed<br>'
9288
+ +MX.esc(cutLabel)+' \xB7 '+MX.age(t.lastAt)+'</span></button>';
9289
+ }).join('');
9290
+ if(rows.length>shown.length){
9291
+ root.innerHTML+='<button class="ax-btn ax-btn--ghost mx-show-all" id="mx-more-threads" type="button">Show '
9292
+ +Math.min(25,rows.length-shown.length)+' more of '+rows.length+'</button>';
9293
+ root.querySelector('#mx-more-threads').addEventListener('click',function(){
9294
+ state.threadLimit+=25;renderThreads(d);
9295
+ });
9296
+ }
9297
+ root.querySelectorAll('[data-thread]').forEach(function(b){
9298
+ b.addEventListener('click',function(){MXD.openConversation(shown[Number(b.dataset.thread)])});
9299
+ });
9300
+ }
9301
+
9302
+ function renderRotations(d){
9303
+ var r=d.rotations,root=el('mx-rotations');
9304
+ if(!r.total){root.innerHTML='<div class="mx-empty">No session cuts recorded in this window.</div>';return}
9305
+ var max=r.byReason[0]?r.byReason[0].count:1;
9306
+ var avg=r.tokenSamples?Math.round(r.tokenSum/r.tokenSamples):0;
9307
+ root.innerHTML=r.byReason.map(function(x){
9308
+ return '<div class="mx-bar"><span class="mx-bar__label">'+MX.esc(x.reason)+'</span>'
9309
+ +'<span class="mx-bar__track"><span class="mx-bar__fill" style="width:'+Math.max(2,x.count/max*100)+'%;background:var(--ax-accent);opacity:.45"></span></span>'
9310
+ +'<span class="mx-bar__val">'+MX.num(x.count)+' <em>'+MX.pct(x.count,r.total)+'</em></span></div>';
9311
+ }).join('');
9312
+ el('mx-rot-note').textContent=MX.num(r.total)+' session cuts. Where a token count was recorded, the average thread carried '
9313
+ +MX.num(avg)+' input tokens at the cut; the largest carried '+MX.num(r.maxTokens)+'.';
9314
+ }
9315
+
9316
+ function renderNodes(d){
9317
+ var down=d.nodes.filter(function(n){return !n.ok});
9318
+ var txt='Merged from '+d.nodes.filter(function(n){return n.ok}).length+' of '+d.nodes.length+' nodes'
9319
+ +' \xB7 '+(d.windowDays===0?'today so far':'last '+d.windowDays+' days')
9320
+ +' \xB7 '+MX.num(d.totals.runs)+' runs, '+MX.num(d.totals.errors)+' failed'
9321
+ +' \xB7 steps retained for '+MX.num(d.retention.tracesWithSteps)+' of '+MX.num(d.retention.traces)+' runs';
9322
+ if(down.length)txt+=' \xB7 UNREACHABLE: '+down.map(function(n){return n.name+' ('+(n.error||'no answer')+')'}).join(', ');
9323
+ el('mx-analytics-updated').textContent=txt;
9324
+ var attention=d.jobs.filter(function(j){return j.verdict!=='healthy'}).length;
9325
+ MX.setHealth(3,attention,attention?'warn':'ok','Jobs needing review');
9326
+ }
9327
+
9328
+ function render(d){
9329
+ state.data=d;
9330
+ // The server knows where the window really starts; deriving it from
9331
+ // windowDays here breaks the Today range, whose start is local
9332
+ // midnight rather than a whole number of days back.
9333
+ d.windowStart=Number.isFinite(d.since)?d.since:(d.generatedAt-d.windowDays*86400000);
9334
+ renderNodes(d);renderLanes(d);renderOrigins(d);renderCauses(d);
9335
+ renderScatter(d);renderThreads(d);renderRotations(d);
9336
+ }
9337
+
9338
+ function load(){
9339
+ el('mx-analytics-updated').textContent='Reading node histories...';
9340
+ MX.get('/api/mesh/analytics?days='+state.days+'&tzOffset='+(-new Date().getTimezoneOffset())+'&limit=80')
9341
+ .then(render)
9342
+ .catch(function(e){el('mx-analytics-updated').textContent='Analytics unavailable: '+e.message});
9343
+ }
9344
+
9345
+ document.querySelectorAll('#mx-range button').forEach(function(b){
9346
+ b.addEventListener('click',function(){
9347
+ state.days=Number(b.dataset.days);
9348
+ document.querySelectorAll('#mx-range button').forEach(function(o){o.setAttribute('aria-pressed',String(o===b))});
9349
+ load();
9350
+ });
9351
+ });
9352
+ window.addEventListener('scroll',hideTip,{passive:true});
9353
+ load();
9354
+ })();
9355
+ </script>`;var Ia=`<script>
9356
+ (function(){
9357
+ var showAll=document.getElementById('mx-show-all'),expanded=false;
9358
+ var esc=MX.esc;
9359
+ function initials(v){return String(v||'?').split(/[-_ ]+/).slice(0,2).map(function(x){return x.charAt(0)}).join('').toUpperCase()}
9360
+ function badge(status){
9361
+ var kind=(status==='success'||status==='active'||status==='online')?'ax-badge--live'
9362
+ :(status==='failed'||status==='timeout'||status==='offline')?'ax-badge--err'
9363
+ :status==='retrying'?'ax-badge--warn':'ax-badge--ghost';
9364
+ return '<span class="ax-badge '+kind+'">'+esc(status)+'</span>';
9365
+ }
9366
+ function avatar(text,variant){return '<span class="ax-avatar '+(variant?'ax-avatar--'+variant:'')+'">'+esc(initials(text))+'</span>'}
9367
+ function item(info,actions,attrs,variant){
9368
+ var tag=info.href?'a':'button';
9369
+ return '<'+tag+' class="ax-row-card mx-item" '+(info.href?'href="'+info.href+'"':'type="button"')+' '+(attrs||'')+'>'
9370
+ +avatar(info.avatar||info.title,variant)
9371
+ +'<span class="ax-row-card__info"><span class="ax-name">'+esc(info.title)
9372
+ +(info.slug?' <span class="ax-slug">'+esc(info.slug)+'</span>':'')+'</span>'
9373
+ +'<span class="ax-sub">'+info.sub+'</span></span>'
9374
+ +'<span class="ax-row-card__actions">'+(actions||'')+'</span></'+tag+'>';
9375
+ }
9376
+ function detail(data){
9377
+ return '<div class="mx-detail">'+MX.fields(data.fields)+(data.note?'<pre>'+esc(data.note)+'</pre>':'')+'</div>';
9378
+ }
9379
+ showAll.addEventListener('click',function(){
9380
+ expanded=!expanded;
9381
+ document.querySelectorAll('#mx-runs .mx-item').forEach(function(el,i){el.hidden=!expanded&&i>=8});
9382
+ showAll.textContent=expanded?'Show less':'Show all';
9383
+ });
9384
+
9385
+ function render(s){
9386
+ var nodes=s.nodes||[],reachable=nodes.filter(function(n){return n.reachable});
9387
+ var agents=reachable.flatMap(function(n){return (n.agents||[]).map(function(a){return {node:n,agent:a}})});
9388
+ var tasks=agents.flatMap(function(x){return (x.agent.runningTasks||[]).map(function(t){return {node:x.node,agent:x.agent,task:t}})});
9389
+ var runs=reachable.flatMap(function(n){return (n.cronRuns||[]).map(function(r){return {node:n,run:r}})});
9390
+ var failed=runs.filter(function(x){return x.run.status!=='success'}).length;
9391
+ MX.setHealth(0,reachable.length+'/'+nodes.length,reachable.length===nodes.length?'ok':'warn');
9392
+ MX.setHealth(1,tasks.length,tasks.length?'ok':'off');
9393
+ MX.setHealth(2,failed,failed?'warn':'off');
9394
+ document.getElementById('mx-updated').textContent='Fleet snapshot '+new Date(s.ts).toLocaleTimeString()
9395
+ +' \xB7 '+Intl.DateTimeFormat().resolvedOptions().timeZone;
9396
+ document.getElementById('mx-active-count').textContent=tasks.length+' active';
9397
+ document.getElementById('mx-node-count').textContent=nodes.length+' nodes';
9398
+ document.getElementById('mx-agent-count').textContent=agents.length+' agents';
9399
+ renderRuns(reachable);renderTasks(tasks);renderNodes(nodes);renderAgents(agents);
9400
+ }
9401
+ function renderRuns(nodes){
9402
+ var cards=[];
9403
+ nodes.forEach(function(n){(n.crons||[]).forEach(function(job){
9404
+ var history=(n.cronRuns||[]).filter(function(r){return r.jobId===job.id}),latest=history[0];
9405
+ var status=!job.enabled?'disabled':latest?latest.status:job.retryPending?'retrying':'waiting';
9406
+ var summary=latest?(latest.errorSummary||latest.responseSummary||'No summary')
9407
+ :(job.enabled?'No attempt persisted today':'Schedule disabled');
9408
+ var agent=(n.agents||[]).find(function(a){return a.id===job.agent});
9409
+ cards.push({node:n,job:job,run:latest,status:status,summary:summary,agent:agent});
9410
+ })});
9411
+ var root=document.getElementById('mx-runs');
9412
+ document.getElementById('mx-run-count').textContent=cards.length+' schedules';
9413
+ showAll.hidden=cards.length<=8;
9414
+ if(!cards.length){root.innerHTML='<div class="mx-empty">No schedules reported by reachable nodes.</div>';return}
9415
+ root.innerHTML=cards.map(function(x,i){
9416
+ var sub='<code>'+esc(x.job.agent)+'</code><span>'+esc(x.job.schedule)+'</span>'
9417
+ +'<span class="mx-summary">'+esc(x.summary)+'</span>';
9418
+ var variant=x.status==='success'?'teal':(x.status==='failed'||x.status==='timeout')?'coral':'plain';
9419
+ return item({title:x.job.id,slug:x.node.name,sub:sub},badge(x.status),
9420
+ 'data-run="'+i+'"'+(!expanded&&i>=8?' hidden':''),variant);
9421
+ }).join('');
9422
+ root.querySelectorAll('[data-run]').forEach(function(el){
9423
+ el.addEventListener('click',function(){
9424
+ var x=cards[Number(el.dataset.run)],runtime=(x.agent&&x.agent.tier)||'unknown';
9425
+ var model=x.job.model||(x.agent&&x.agent.model);
9426
+ MX.open('Automation',x.job.id,detail({fields:[
9427
+ ['Node',x.node.name],['Agent',x.job.agent],['Runtime',runtime],
9428
+ ['Model',x.job.model?model:(model?model+' (inherited)':'default')],
9429
+ ['Status',x.status],['Schedule',x.job.schedule],['Timezone',x.job.timezone||'local'],
9430
+ ['Started',x.run?new Date(x.run.startedAt).toLocaleString():'Not today'],
9431
+ ['Duration',x.run?MX.dur(x.run.duration):'-'],
9432
+ ['Retry',x.run&&x.run.isRetry?'Attempt '+x.run.retryAttempt:'No'],
9433
+ ['Task ID',(x.run&&x.run.taskId)||'-'],['Session ID',(x.run&&x.run.sessionId)||'-']
9434
+ ],note:x.summary}));
9435
+ });
9436
+ });
9437
+ }
9438
+ function renderTasks(tasks){
9439
+ var root=document.getElementById('mx-active');
9440
+ if(!tasks.length){root.innerHTML='<div class="mx-empty">The mesh is idle.</div>';return}
9441
+ root.innerHTML=tasks.map(function(x){
9442
+ var href='/tasks/'+encodeURIComponent(x.task.id)+'?node='+encodeURIComponent(x.node.url)
9443
+ +'&agent='+encodeURIComponent(x.agent.id)+'&name='+encodeURIComponent(x.agent.name)
9444
+ +'&channel='+encodeURIComponent(x.task.channel||'unknown');
9445
+ var sub='<code>'+esc(x.node.name)+' / '+esc(x.task.channel||'unknown')+'</code>'
9446
+ +'<span class="mx-summary">'+esc(x.task.messagePreview||'Working')+'</span>';
9447
+ return item({href:href,title:x.agent.name,slug:x.task.sender?'by '+x.task.sender:'',sub:sub},
9448
+ '<span class="mx-node-meta">'+esc(MX.age(x.task.startedAt))+'</span>','','blue');
9449
+ }).join('');
9450
+ }
9451
+ function renderNodes(nodes){
9452
+ var root=document.getElementById('mx-nodes');
9453
+ root.innerHTML=nodes.map(function(n,i){
9454
+ var active=(n.agents||[]).reduce(function(v,a){return v+(a.active||0)},0);
9455
+ var sub='<span>'+esc(n.reachable?n.agents.length+' agents \xB7 '+active+' active':n.error||'unreachable')+'</span>';
9456
+ var status=n.reachable?(active?'active':'online'):'offline';
9457
+ return item({title:n.name,slug:n.id,sub:sub},badge(status),'data-node="'+i+'"',n.reachable?'teal':'coral');
9458
+ }).join('');
9459
+ root.querySelectorAll('[data-node]').forEach(function(el){
9460
+ el.addEventListener('click',function(){
9461
+ var n=nodes[Number(el.dataset.node)];
9462
+ MX.open('Fleet node',n.name,detail({fields:[
9463
+ ['Status',n.reachable?'Reachable':'Unreachable'],['URL',n.url],
9464
+ ['Agents',(n.agents||[]).length],['Schedules',(n.crons||[]).length],
9465
+ ['Uptime',n.uptimeSec?Math.floor(n.uptimeSec/60)+' minutes':'-']
9466
+ ],note:n.error||''}));
9467
+ });
9468
+ });
9469
+ }
9470
+ function renderAgents(items){
9471
+ var root=document.getElementById('mx-agents');
9472
+ if(!items.length){root.innerHTML='<div class="mx-empty">No agent inventory available.</div>';return}
9473
+ root.innerHTML=items.map(function(x,i){
9474
+ var a=x.agent;
9475
+ var sub='<code>'+esc(a.tier)+' \xB7 '+esc(a.model||'default model')+'</code>'
9476
+ +'<span>'+esc(a.skillCount==null?'skills unavailable':a.skillCount+' skills')+' \xB7 '+esc(a.total||0)+' tasks</span>';
9477
+ return item({title:a.name,slug:x.node.name,sub:sub},badge(a.active?'active':'idle'),'data-agent="'+i+'"',a.active?'blue':'plain');
9478
+ }).join('');
9479
+ root.querySelectorAll('[data-agent]').forEach(function(el){
9480
+ el.addEventListener('click',function(){
9481
+ var x=items[Number(el.dataset.agent)],a=x.agent;
9482
+ var history='/agents/'+encodeURIComponent(a.id)+'/history?node='+encodeURIComponent(x.node.url)
9483
+ +'&name='+encodeURIComponent(a.name);
9484
+ MX.open('Agent inventory',a.name,detail({fields:[
9485
+ ['Node',x.node.name],['Agent ID',a.id],['Runtime',a.tier],['Model',a.model||'default'],
9486
+ ['Skills',a.skillCount==null?'Unavailable until node upgrade':a.skillCount],
9487
+ ['Active tasks',a.active||0],['Total tasks',a.total||0],['Errors',a.errors||0]
9488
+ ],note:(a.lastSummary&&a.lastSummary.text)||''})
9489
+ +'<a class="mx-link" href="'+history+'">Open activity history</a>');
9490
+ });
9491
+ });
9492
+ }
9493
+ function load(){
9494
+ var date=new Date().toLocaleDateString('en-CA');
9495
+ var tz=Intl.DateTimeFormat().resolvedOptions().timeZone||'UTC';
9496
+ MX.get('/api/mesh?date='+encodeURIComponent(date)+'&timezone='+encodeURIComponent(tz))
9497
+ .then(render)
9498
+ .catch(function(e){document.getElementById('mx-updated').textContent='Fleet snapshot unavailable: '+e.message});
9499
+ }
9500
+ load();setInterval(load,5000);
9501
+ })();
9502
+ </script>`;var V={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>',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>',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 Y(t,e,a,n,r=""){return N({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var ko=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],_o=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function $a(t){let e=Te({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Ce([{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">
9503
+ <div class="mx-tabs" role="tablist" aria-label="Mesh views">
9504
+ ${ko.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("")}
8552
9505
  </div>
8553
- <div class="mx-health" id="mx-health"></div>
8554
- </header>
9506
+ <div class="mx-range" id="mx-range" role="group" aria-label="History window">
9507
+ ${_o.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
9508
+ </div>
9509
+ </div>
9510
+ <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">
9511
+ <section class="mx-section" aria-labelledby="mx-lanes-title">
9512
+ ${Y(V.activity,"What ran","One lane per origin. Each lane is scaled to its own peak so a quiet channel stays readable next to a busy one. Select a column for the day behind it.","mx-lanes-title")}
9513
+ <div id="mx-lanes"><div class="mx-empty">Loading activity...</div></div>
9514
+ <div class="mx-axis" id="mx-axis"></div>
9515
+ <p class="mx-note">Coloured bars are runs that finished; the red cap on a column is the failures inside that day. Select any column for what ran that day, down to a single conversation.</p>
9516
+ </section>
8555
9517
 
8556
- <section aria-labelledby="mx-auto-title">
8557
- <div class="mx-section-head">
8558
- <div><p class="mx-kicker">Today</p><h2 id="mx-auto-title">Automations</h2></div>
8559
- <div class="mx-legend"><span><i class="ok"></i>Passed</span><span><i class="bad"></i>Failed</span><span><i class="wait"></i>Waiting</span></div>
9518
+ <div class="mx-two">
9519
+ <section class="mx-section" aria-labelledby="mx-origins-title">
9520
+ ${Y(V.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
9521
+ <div class="mx-bars" id="mx-origins"><div class="mx-empty">Loading...</div></div>
9522
+ </section>
9523
+ <section class="mx-section" aria-labelledby="mx-causes-title">
9524
+ ${Y(V.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
9525
+ <div class="mx-bars" id="mx-causes"><div class="mx-empty">Loading...</div></div>
9526
+ <p class="mx-note" id="mx-cause-note"></p>
9527
+ </section>
8560
9528
  </div>
8561
- <div class="mx-runs" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
8562
- </section>
8563
9529
 
8564
- <div class="mx-grid">
8565
- <section aria-labelledby="mx-active-title">
8566
- <div class="mx-section-head"><div><p class="mx-kicker">Now</p><h2 id="mx-active-title">Activity provenance</h2></div><span class="mx-count" id="mx-active-count">0 active</span></div>
8567
- <div class="mx-list" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
9530
+ <section class="mx-section" aria-labelledby="mx-scatter-title">
9531
+ ${Y(V.effort,"Effort against output","Every recurring job, plotted as runtime spent against tokens produced on its successful runs. Both axes are logarithmic.","mx-scatter-title")}
9532
+ <div class="mx-scatter" id="mx-scatter"><div class="mx-empty">Loading jobs...</div></div>
9533
+ <div class="mx-legend" id="mx-scatter-legend"></div>
9534
+ <p class="mx-note">Bubble size is the number of runs. Anything not healthy is labelled on the chart; select it for the attempt history behind the verdict.</p>
8568
9535
  </section>
8569
- <section aria-labelledby="mx-nodes-title">
8570
- <div class="mx-section-head"><div><p class="mx-kicker">Fleet</p><h2 id="mx-nodes-title">Nodes</h2></div><span class="mx-count" id="mx-node-count">0 nodes</span></div>
8571
- <div class="mx-list" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
9536
+ </div>`,r=`<div class="mx-view" id="mx-view-lifetime" role="tabpanel" aria-labelledby="mx-tab-lifetime" hidden>
9537
+ <section class="mx-section" aria-labelledby="mx-threads-title">
9538
+ ${Y(V.lifetime,"Thread lifetimes","A thread is one agent talking on one channel in one conversation. The bar is its real first-to-last span; each tick is a session cut. Select one for its turns, tokens and time.","mx-threads-title")}
9539
+ <div class="mx-chips" id="mx-thread-chips"></div>
9540
+ <div id="mx-threads"><div class="mx-empty">Loading threads...</div></div>
9541
+ <p class="mx-note">Select a thread to walk its runs, then a run to see which tools it touched. Grey ticks are stale cuts, amber ticks are context-full cuts.</p>
8572
9542
  </section>
8573
- </div>
8574
9543
 
8575
- <section aria-labelledby="mx-agents-title">
8576
- <div class="mx-section-head"><div><p class="mx-kicker">Inventory</p><h2 id="mx-agents-title">Agents and skills</h2></div><span class="mx-count" id="mx-agent-count">0 agents</span></div>
8577
- <div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
8578
- </section>
8579
- </div>
9544
+ <section class="mx-section" aria-labelledby="mx-rot-title">
9545
+ ${Y(V.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
9546
+ <div class="mx-bars" id="mx-rotations"><div class="mx-empty">Loading...</div></div>
9547
+ <p class="mx-note" id="mx-rot-note"></p>
9548
+ </section>
9549
+ </div>`,o=`<div class="mx-view" id="mx-view-ops" role="tabpanel" aria-labelledby="mx-tab-ops" hidden>
9550
+ <p id="mx-updated" class="mx-updated" aria-live="polite">Connecting to the fleet...</p>
9551
+
9552
+ <section class="mx-section" aria-labelledby="mx-auto-title">
9553
+ ${Y(V.schedules,"Today's automations","Persisted attempts are authoritative. Select a schedule to inspect its latest result and runtime.","mx-auto-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-run-count">0 schedules</span><button class="ax-btn ax-btn--ghost mx-show-all" id="mx-show-all" type="button" hidden>Show all</button></div>')}
9554
+ <div class="ax-stack" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
9555
+ </section>
9556
+
9557
+ <div class="mx-columns">
9558
+ <section class="mx-section" aria-labelledby="mx-active-title">
9559
+ ${Y(V.activity,"Activity provenance","Who initiated current work and where it is running.","mx-active-title",'<span class="ax-tab-count" id="mx-active-count">0 active</span>')}
9560
+ <div class="ax-stack" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
9561
+ </section>
9562
+ <section class="mx-section" aria-labelledby="mx-nodes-title">
9563
+ ${Y(V.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
9564
+ <div class="ax-stack" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
9565
+ </section>
9566
+ </div>
9567
+
9568
+ <section class="mx-section" aria-labelledby="mx-agents-title">
9569
+ ${Y(V.agents,"Agents and skills","Runtime, model, installed skills, and task totals by node.","mx-agents-title",'<span class="ax-tab-count" id="mx-agent-count">0 agents</span>')}
9570
+ <div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
9571
+ </section>
9572
+ </div>`,s=`${e}<main class="mx-content">
9573
+ ${a}
9574
+ ${n}
9575
+ ${r}
9576
+ ${o}
9577
+ </main>
8580
9578
  <div class="mx-scrim" id="mx-scrim" hidden></div>
8581
9579
  <aside class="mx-drawer" id="mx-drawer" aria-labelledby="mx-drawer-title" aria-hidden="true">
8582
- <button class="mx-close" id="mx-close" type="button" aria-label="Close details">Close</button>
8583
- <p class="mx-kicker" id="mx-drawer-kicker">Details</p>
8584
- <h2 id="mx-drawer-title">Selection</h2>
8585
- <div id="mx-drawer-body"></div>
8586
- </aside>`,css:po,scripts:uo})}var po=`
8587
- body{margin:0;background:var(--ax-bg);color:var(--ax-text);font-family:var(--ax-font)}
8588
- main{max-width:1500px;margin:0 auto;padding:28px 28px 64px}
8589
- .mx-page{display:grid;gap:34px}.mx-head{display:flex;align-items:flex-end;justify-content:space-between;gap:24px}
8590
- .mx-kicker{margin:0 0 6px;color:var(--ax-accent);font:600 10px/1 var(--ax-mono);letter-spacing:.14em;text-transform:uppercase}
8591
- h1,h2{margin:0;letter-spacing:-.03em}h1{font-size:clamp(30px,4vw,54px);line-height:.95}h2{font-size:22px}
8592
- .mx-muted{margin:10px 0 0;color:var(--ax-muted);font-size:12px}.mx-health{display:grid;grid-template-columns:repeat(4,minmax(90px,1fr));gap:8px}
8593
- .mx-stat{min-width:90px;padding:12px 14px;background:var(--ax-surface);border:2px solid var(--ax-border-2);border-radius:var(--ax-radius-sm);box-shadow:var(--ax-shadow);text-align:right}
8594
- .mx-stat strong{display:block;font:700 24px/1 var(--ax-mono)}.mx-stat span{color:var(--ax-muted);font-size:10px;text-transform:uppercase;letter-spacing:.08em}
8595
- .mx-section-head{display:flex;align-items:end;justify-content:space-between;gap:16px;margin-bottom:12px}.mx-count{color:var(--ax-muted);font:11px var(--ax-mono)}
8596
- .mx-legend{display:flex;gap:12px;color:var(--ax-muted);font:10px var(--ax-mono)}.mx-legend span{display:flex;align-items:center;gap:5px}.mx-legend i{width:7px;height:7px;border-radius:50%}
8597
- .ok{background:var(--ax-ok)}.bad{background:var(--ax-err)}.wait{background:var(--ax-muted)}
8598
- .mx-runs{display:flex;gap:9px;overflow-x:auto;padding:0 0 7px;scroll-snap-type:x proximity}
8599
- .mx-run{position:relative;flex:0 0 210px;scroll-snap-align:start;text-align:left;min-height:118px;padding:14px;background:var(--ax-surface);border:2px solid var(--ax-border-2);border-radius:var(--ax-radius-sm);box-shadow:var(--ax-shadow);color:inherit;font:inherit;cursor:pointer;overflow:hidden}
8600
- .mx-run:hover,.mx-run:focus-visible{border-color:var(--ax-accent);transform:translateY(-1px)}.mx-run__top{display:flex;justify-content:space-between;gap:8px}.mx-run__node{font:10px var(--ax-mono);color:var(--ax-muted)}
8601
- .mx-status{width:9px;height:9px;border-radius:50%;margin-top:2px;flex:none}.mx-run h3{margin:18px 0 4px;font-size:15px}.mx-run p{margin:0;color:var(--ax-muted);font:10px/1.4 var(--ax-mono)}
8602
- .mx-peek{position:absolute;inset:auto 0 0;padding:10px 14px;background:var(--ax-text);color:var(--ax-bg);font-size:11px;line-height:1.35;transform:translateY(101%);transition:transform .16s ease;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
8603
- .mx-run:hover .mx-peek,.mx-run:focus-visible .mx-peek{transform:translateY(0)}
8604
- .mx-grid{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(280px,.55fr);gap:28px}.mx-list{display:grid;gap:8px}
8605
- .mx-row{display:grid;grid-template-columns:12px minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px 14px;background:var(--ax-surface);border:1px solid var(--ax-border);border-radius:var(--ax-radius-sm);color:inherit;text-decoration:none}
8606
- button.mx-row{width:100%;font:inherit;text-align:left;cursor:pointer}.mx-row:hover,.mx-row:focus-visible{border-color:var(--ax-border-2);background:var(--ax-surface-2)}
8607
- .mx-dot{width:8px;height:8px;border-radius:50%;background:var(--ax-ok);box-shadow:0 0 0 3px color-mix(in oklch,var(--ax-ok) 15%,transparent)}.mx-dot.off{background:var(--ax-err);box-shadow:none}.mx-dot.busy{background:var(--ax-accent)}
8608
- .mx-row strong{display:block;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mx-row small{display:block;margin-top:3px;color:var(--ax-muted);font:10px var(--ax-mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mx-row time{color:var(--ax-muted);font:10px var(--ax-mono)}
8609
- .mx-agent-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(225px,1fr));gap:8px}.mx-agent{padding:13px 14px;background:var(--ax-surface);border:1px solid var(--ax-border);border-radius:var(--ax-radius-sm);color:inherit;text-decoration:none}
8610
- .mx-agent{font:inherit;text-align:left;cursor:pointer}.mx-agent:hover,.mx-agent:focus-visible{border-color:var(--ax-accent)}.mx-agent__top{display:flex;justify-content:space-between;gap:8px}.mx-agent strong{font-size:13px}.mx-agent code{color:var(--ax-muted);font-size:9px}.mx-agent p{margin:8px 0 0;color:var(--ax-muted);font:10px/1.4 var(--ax-mono)}
8611
- .mx-link{display:inline-block;margin-top:4px;color:var(--ax-accent);font-weight:600;text-decoration:none}.mx-link:hover{text-decoration:underline}
8612
- .mx-empty{padding:24px;border:1px dashed var(--ax-border-2);border-radius:var(--ax-radius-sm);color:var(--ax-muted);font-size:12px;text-align:center;grid-column:1/-1}
8613
- .mx-scrim{position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:29}.mx-drawer{position:fixed;z-index:30;top:0;right:0;width:min(440px,calc(100vw - 24px));height:100vh;box-sizing:border-box;padding:76px 28px 28px;background:var(--ax-surface);border-left:2px solid var(--ax-border-2);transform:translateX(102%);transition:transform .2s ease;overflow:auto;box-shadow:-12px 0 40px rgba(0,0,0,.18)}
8614
- .mx-drawer.is-open{transform:translateX(0)}.mx-close{position:absolute;right:20px;top:20px;padding:7px 11px;border:1px solid var(--ax-border-2);border-radius:8px;background:transparent;color:var(--ax-text);font:11px var(--ax-mono);cursor:pointer}
8615
- .mx-detail{margin-top:22px;display:grid;gap:16px}.mx-detail dl{display:grid;grid-template-columns:100px 1fr;gap:8px;margin:0;font-size:12px}.mx-detail dt{color:var(--ax-muted)}.mx-detail dd{margin:0;word-break:break-word}.mx-detail pre{margin:0;padding:14px;background:var(--ax-bg);border:1px solid var(--ax-border);border-radius:10px;white-space:pre-wrap;font:11px/1.55 var(--ax-mono)}
8616
- @media(max-width:800px){main{padding:22px 14px 48px}.mx-head{align-items:flex-start;flex-direction:column}.mx-health{width:100%;grid-template-columns:repeat(2,1fr)}.mx-grid{grid-template-columns:1fr}.mx-section-head{align-items:flex-start}.mx-legend{display:none}}
8617
- @media(prefers-reduced-motion:reduce){.mx-run,.mx-peek,.mx-drawer{transition:none}}
8618
- `,uo=`<script>
9580
+ <header class="mx-drawer__head">
9581
+ <div><div class="ax-kicker" id="mx-drawer-kicker">Details</div><h2 id="mx-drawer-title">Selection</h2></div>
9582
+ <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
9583
+ </header>
9584
+ <div class="mx-drawer__body" id="mx-drawer-body"></div>
9585
+ </aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ta,scripts:Ca+Eo+Aa+Ma+Ia})}var Eo=`<script>
8619
9586
  (function(){
8620
- var state = null;
8621
- var drawer = document.getElementById('mx-drawer');
8622
- var scrim = document.getElementById('mx-scrim');
8623
- var close = document.getElementById('mx-close');
8624
- function esc(v){return String(v == null ? '' : v).replace(/[&<>"']/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]})}
8625
- function age(v){if(!v)return 'unknown';var s=Math.max(0,(Date.now()-new Date(v).getTime())/1000);if(s<60)return Math.floor(s)+'s ago';if(s<3600)return Math.floor(s/60)+'m ago';return Math.floor(s/3600)+'h ago'}
8626
- function duration(ms){if(!Number.isFinite(ms))return '-';return ms<1000?ms+'ms':(ms/1000).toFixed(ms<10000?1:0)+'s'}
8627
- function statusColor(s){return s==='success'?'var(--ax-ok)':(s==='failed'||s==='timeout')?'var(--ax-err)':'var(--ax-muted)'}
8628
- function openDrawer(kicker,title,html){document.getElementById('mx-drawer-kicker').textContent=kicker;document.getElementById('mx-drawer-title').textContent=title;document.getElementById('mx-drawer-body').innerHTML=html;drawer.classList.add('is-open');drawer.setAttribute('aria-hidden','false');scrim.hidden=false;close.focus()}
8629
- function closeDrawer(){drawer.classList.remove('is-open');drawer.setAttribute('aria-hidden','true');scrim.hidden=true}
8630
- close.addEventListener('click',closeDrawer);scrim.addEventListener('click',closeDrawer);document.addEventListener('keydown',function(e){if(e.key==='Escape')closeDrawer()});
8631
- function detail(data){var fields=data.fields.map(function(f){return '<dt>'+esc(f[0])+'</dt><dd>'+esc(f[1])+'</dd>'}).join('');var note=data.note?'<pre>'+esc(data.note)+'</pre>':'';return '<div class="mx-detail"><dl>'+fields+'</dl>'+note+'</div>'}
8632
- function render(s){state=s;var nodes=s.nodes||[];var reachable=nodes.filter(function(n){return n.reachable});var agents=reachable.flatMap(function(n){return (n.agents||[]).map(function(a){return {node:n,agent:a}})});var tasks=agents.flatMap(function(x){return (x.agent.runningTasks||[]).map(function(t){return {node:x.node,agent:x.agent,task:t}})});var runs=reachable.flatMap(function(n){return (n.cronRuns||[]).map(function(r){return {node:n,run:r}})});
8633
- var failed=runs.filter(function(x){return x.run.status!=='success'}).length;var skillTotal=agents.reduce(function(v,x){return v+(x.agent.skillCount||0)},0);
8634
- document.getElementById('mx-health').innerHTML=[['Nodes',reachable.length+'/'+nodes.length],['Active',tasks.length],['Failures',failed],['Skills',skillTotal]].map(function(v){return '<div class="mx-stat"><strong>'+esc(v[1])+'</strong><span>'+esc(v[0])+'</span></div>'}).join('');
8635
- document.getElementById('mx-updated').textContent='Updated '+new Date(s.ts).toLocaleTimeString()+' \xB7 '+Intl.DateTimeFormat().resolvedOptions().timeZone;
8636
- document.getElementById('mx-active-count').textContent=tasks.length+' active';document.getElementById('mx-node-count').textContent=nodes.length+' nodes';document.getElementById('mx-agent-count').textContent=agents.length+' agents';
8637
- renderRuns(reachable);renderTasks(tasks);renderNodes(nodes);renderAgents(agents);
8638
- }
8639
- function renderRuns(nodes){var cards=[];nodes.forEach(function(n){(n.crons||[]).forEach(function(job){var history=(n.cronRuns||[]).filter(function(r){return r.jobId===job.id});var latest=history[0];var status=!job.enabled?'disabled':latest?latest.status:job.retryPending?'retrying':'waiting';var summary=latest?(latest.errorSummary||latest.responseSummary||'No summary'):(job.enabled?'No attempt persisted today':'Schedule disabled');cards.push({node:n,job:job,run:latest,status:status,summary:summary})})});var root=document.getElementById('mx-runs');if(!cards.length){root.innerHTML='<div class="mx-empty">No schedules reported by reachable nodes.</div>';return}root.innerHTML=cards.map(function(x,i){return '<button class="mx-run" type="button" data-run="'+i+'"><span class="mx-run__top"><span class="mx-run__node">'+esc(x.node.name)+'</span><i class="mx-status" style="background:'+statusColor(x.status)+'"></i></span><h3>'+esc(x.job.id)+'</h3><p>'+esc(x.job.agent)+' \xB7 '+esc(x.job.schedule)+'</p><span class="mx-peek">'+esc(x.summary)+'</span></button>'}).join('');root.querySelectorAll('[data-run]').forEach(function(el){el.addEventListener('click',function(){var x=cards[Number(el.dataset.run)];openDrawer('Automation',x.job.id,detail({fields:[['Node',x.node.name],['Agent',x.job.agent],['Status',x.status],['Schedule',x.job.schedule],['Timezone',x.job.timezone||'local'],['Started',x.run?new Date(x.run.startedAt).toLocaleString():'Not today'],['Duration',x.run?duration(x.run.duration):'-'],['Retry',x.run&&x.run.isRetry?'Attempt '+x.run.retryAttempt:'No'],['Task ID',x.run&&x.run.taskId||'-'],['Session ID',x.run&&x.run.sessionId||'-']],note:x.summary}))})});
8640
- }
8641
- function renderTasks(tasks){var root=document.getElementById('mx-active');if(!tasks.length){root.innerHTML='<div class="mx-empty">The mesh is idle.</div>';return}root.innerHTML=tasks.map(function(x,i){return '<a class="mx-row" href="/tasks/'+encodeURIComponent(x.task.id)+'?node='+encodeURIComponent(x.node.url)+'&agent='+encodeURIComponent(x.agent.id)+'&name='+encodeURIComponent(x.agent.name)+'&channel='+encodeURIComponent(x.task.channel||'unknown')+'"><i class="mx-dot busy"></i><span><strong>'+esc(x.agent.name)+' \xB7 '+esc(x.task.messagePreview||'Working')+'</strong><small>'+esc(x.node.name)+' / '+esc(x.task.channel||'unknown')+(x.task.sender?' / initiated by '+esc(x.task.sender):'')+'</small></span><time>'+esc(age(x.task.startedAt))+'</time></a>'}).join('')}
8642
- function renderNodes(nodes){var root=document.getElementById('mx-nodes');root.innerHTML=nodes.map(function(n,i){var active=(n.agents||[]).reduce(function(v,a){return v+(a.active||0)},0);return '<button class="mx-row" type="button" data-node="'+i+'"><i class="mx-dot '+(n.reachable?(active?'busy':''):'off')+'"></i><span><strong>'+esc(n.name)+'</strong><small>'+esc(n.reachable?(n.agents.length+' agents \xB7 '+active+' active'):(n.error||'unreachable'))+'</small></span><time>'+esc(n.uptimeSec?Math.floor(n.uptimeSec/3600)+'h up':'-')+'</time></button>'}).join('');root.querySelectorAll('[data-node]').forEach(function(el){el.addEventListener('click',function(){var n=nodes[Number(el.dataset.node)];openDrawer('Fleet node',n.name,detail({fields:[['Status',n.reachable?'Reachable':'Unreachable'],['URL',n.url],['Agents',(n.agents||[]).length],['Schedules',(n.crons||[]).length],['Uptime',n.uptimeSec?Math.floor(n.uptimeSec/60)+' minutes':'-']],note:n.error||''}))})})}
8643
- function renderAgents(items){var root=document.getElementById('mx-agents');if(!items.length){root.innerHTML='<div class="mx-empty">No agent inventory available.</div>';return}root.innerHTML=items.map(function(x,i){var a=x.agent;return '<button class="mx-agent" type="button" data-agent="'+i+'"><span class="mx-agent__top"><strong>'+esc(a.name)+'</strong><code>'+esc(x.node.name)+'</code></span><p>'+esc(a.tier)+' \xB7 '+esc(a.model||'default model')+'<br>'+esc(a.skillCount==null?'skills unavailable':a.skillCount+' skills')+' \xB7 '+esc(a.total||0)+' tasks</p></button>'}).join('');root.querySelectorAll('[data-agent]').forEach(function(el){el.addEventListener('click',function(){var x=items[Number(el.dataset.agent)],a=x.agent;var history='/agents/'+encodeURIComponent(a.id)+'/history?node='+encodeURIComponent(x.node.url)+'&name='+encodeURIComponent(a.name);openDrawer('Agent inventory',a.name,detail({fields:[['Node',x.node.name],['Agent ID',a.id],['Runtime',a.tier],['Model',a.model||'default'],['Skills',a.skillCount==null?'Unavailable until node upgrade':a.skillCount],['Active tasks',a.active||0],['Total tasks',a.total||0],['Errors',a.errors||0]],note:a.lastSummary&&a.lastSummary.text||''})+'<a class="mx-link" href="'+history+'">Open activity history</a>')})})}
8644
- function load(){var date=new Date().toLocaleDateString('en-CA');var tz=Intl.DateTimeFormat().resolvedOptions().timeZone||'UTC';fetch('/api/mesh?date='+encodeURIComponent(date)+'&timezone='+encodeURIComponent(tz)).then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.json()}).then(render).catch(function(e){document.getElementById('mx-updated').textContent='Fleet snapshot unavailable: '+e.message})}
8645
- load();setInterval(load,5000);
9587
+ var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
9588
+ var range=document.getElementById('mx-range');
9589
+ var stamp=document.getElementById('mx-analytics-updated');
9590
+ function select(id){
9591
+ tabs.forEach(function(t){
9592
+ var on=t.dataset.view===id;
9593
+ t.setAttribute('aria-selected',String(on));
9594
+ document.getElementById('mx-view-'+t.dataset.view).hidden=!on;
9595
+ });
9596
+ var analytics=id!=='ops';
9597
+ range.hidden=!analytics;stamp.hidden=!analytics;
9598
+ try{localStorage.setItem('mx-view',id)}catch(e){}
9599
+ }
9600
+ tabs.forEach(function(t,i){
9601
+ t.addEventListener('click',function(){select(t.dataset.view)});
9602
+ t.addEventListener('keydown',function(e){
9603
+ var d=e.key==='ArrowRight'?1:e.key==='ArrowLeft'?-1:0;
9604
+ if(!d)return;
9605
+ e.preventDefault();
9606
+ var next=tabs[(i+d+tabs.length)%tabs.length];
9607
+ next.focus();select(next.dataset.view);
9608
+ });
9609
+ });
9610
+ var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
9611
+ select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
8646
9612
  })();
8647
- </script>`;function Ea(t={}){let e=`
9613
+ </script>`;async function ja(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 So(s,e.days)}function So(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,v=0,k=0;for(let{node:E,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 g of["cron","workflow","direct"])m[g][0]+=c[g]?.[0]||0,m[g][1]+=c[g]?.[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 g of c.agents)m.agents.includes(g)||m.agents.push(g);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),v+=S.retention.traces,k+=S.retention.tracesWithSteps;for(let c of S.jobs)i.push({...c,node:E.name,nodeUrl:E.url});for(let c of S.threads)l.push({...c,node:E.name,nodeUrl:E.url})}let A=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:A.length?Math.min(...A):Date.now()-e*864e5,nodes:t.map(E=>({name:E.node.name,url:E.node.url,ok:!!E.data,error:E.error,runs:E.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((E,S)=>E.day.localeCompare(S.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,S)=>S.runs-E.runs),causes:[...o.values()].sort((E,S)=>S.count-E.count),jobs:i.sort((E,S)=>S.hours-E.hours),threads:l.sort((E,S)=>S.lastAt-S.firstAt-(E.lastAt-E.firstAt)||S.runs-E.runs),rotations:{total:d,byReason:[...s.entries()].map(([E,S])=>({reason:E,count:S})).sort((E,S)=>S.count-E.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:v,tracesWithSteps:k}}}async function La(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 Ra(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 To(s,e.day)}function To(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 Da(t={}){let e=`
8648
9614
  <select id="boardPicker" title="Switch board"></select>
8649
9615
  <div class="search">
8650
9616
  <span class="icon">\u2315</span>
@@ -8745,7 +9711,7 @@ button.mx-row{width:100%;font:inherit;text-align:left;cursor:pointer}.mx-row:hov
8745
9711
  </footer>
8746
9712
  </div>
8747
9713
  </div>
8748
- <script src="/sortable.min.js"></script>`;return C({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:mo,scripts:`<script>${go}</script>`,headExtras:`<script>
9714
+ <script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Co,scripts:`<script>${Ao}</script>`,headExtras:`<script>
8749
9715
  // The boards page has its own connection dot + wants body height:100%
8750
9716
  // for the full-viewport kanban layout. Inject the dot into the topbar
8751
9717
  // and override body height at runtime so the shared shell doesn't
@@ -8761,7 +9727,7 @@ button.mx-row{width:100%;font:inherit;text-align:left;cursor:pointer}.mx-row:hov
8761
9727
  right.insertBefore(dot, right.firstChild);
8762
9728
  }
8763
9729
  });
8764
- </script>`})}var mo=`
9730
+ </script>`})}var Co=`
8765
9731
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
8766
9732
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
8767
9733
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -9014,7 +9980,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
9014
9980
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
9015
9981
  .draft-box .draft-row .hint.err { color: var(--red); }
9016
9982
  .draft-box .draft-row .hint.ok { color: var(--green); }
9017
- `,go=`
9983
+ `,Ao=`
9018
9984
  'use strict';
9019
9985
  const state = {
9020
9986
  boards: [], current: null, items: {},
@@ -10073,9 +11039,9 @@ function appendEvents(events) {
10073
11039
  }
10074
11040
 
10075
11041
  loadBoards().catch(e => toast('Init failed: ' + e.message));
10076
- `;function Sa(t={}){let a=`<h1>Plain-English glossary</h1>
11042
+ `;function Pa(t={}){let a=`<h1>Plain-English glossary</h1>
10077
11043
  <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>
10078
- ${ka.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${L(n.alias)}</span>`:"";return`<article class="term"><h3>${L(n.term)}${r}</h3><p>${L(n.definition)}</p></article>`}).join("")}`;return C({title:`${se.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ho})}var ho=`
11044
+ ${Sa.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${D(n.alias)}</span>`:"";return`<article class="term"><h3>${D(n.term)}${r}</h3><p>${D(n.definition)}</p></article>`}).join("")}`;return M({title:`${le.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Mo})}var Mo=`
10079
11045
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
10080
11046
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
10081
11047
  .lead {
@@ -10105,7 +11071,7 @@ article.term .alias {
10105
11071
  }
10106
11072
  article.term p {
10107
11073
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
10108
- }`;function Ta(t={}){let e=`<div class="ax-wf__root">
11074
+ }`;function Oa(t={}){let e=`<div class="ax-wf__root">
10109
11075
  <aside class="ax-wf__list">
10110
11076
  <header>
10111
11077
  <h2>Workflows</h2>
@@ -10161,7 +11127,7 @@ article.term p {
10161
11127
  </aside>
10162
11128
  </div>
10163
11129
 
10164
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return C({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:fo,scripts:`<script>${xo}</script>`})}var fo=`
11130
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Io,scripts:`<script>${$o}</script>`})}var Io=`
10165
11131
  .ax-wf__root {
10166
11132
  display: grid;
10167
11133
  grid-template-columns: 340px 1fr;
@@ -10530,7 +11496,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
10530
11496
  font-size: 12px; z-index: 50;
10531
11497
  }
10532
11498
  .hint { color: var(--ax-muted); font-size: 11px; }
10533
- `,xo=`
11499
+ `,$o=`
10534
11500
  (() => {
10535
11501
  const $ = (sel) => document.querySelector(sel)
10536
11502
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -11481,7 +12447,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
11481
12447
  setInterval(refresh, 15000)
11482
12448
  })
11483
12449
  })();
11484
- `;function Ca(t={}){let e=`<div class="ax-proc__root">
12450
+ `;function Ha(t={}){let e=`<div class="ax-proc__root">
11485
12451
  <header class="ax-proc__header">
11486
12452
  <h1>Procedures</h1>
11487
12453
  <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>
@@ -11525,7 +12491,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
11525
12491
  <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>
11526
12492
  <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>
11527
12493
  </section>
11528
- </div>`;return C({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:vo,scripts:`<script>${bo}</script>`})}var vo=`
12494
+ </div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:jo,scripts:`<script>${Lo}</script>`})}var jo=`
11529
12495
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
11530
12496
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
11531
12497
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -11551,7 +12517,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
11551
12517
  .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); }
11552
12518
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
11553
12519
  .ax-proc__link:hover { text-decoration: underline; }
11554
- `,bo=`
12520
+ `,Lo=`
11555
12521
  (function(){
11556
12522
  function $(sel){ return document.querySelector(sel) }
11557
12523
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -11651,24 +12617,24 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
11651
12617
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
11652
12618
  else bootAll()
11653
12619
  })();
11654
- `;function Aa(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
11655
- data-task-id="${L(t.taskId)}"
11656
- data-agent-id="${L(t.agentId)}"
11657
- data-node-url="${L(t.nodeUrl)}"
12620
+ `;function Na(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
12621
+ data-task-id="${D(t.taskId)}"
12622
+ data-agent-id="${D(t.agentId)}"
12623
+ data-node-url="${D(t.nodeUrl)}"
11658
12624
  data-archived="${t.archived?"1":""}"
11659
- data-ask="${L(t.ask||"")}"
11660
- data-ask-at="${L(t.askAt||"")}">
12625
+ data-ask="${D(t.ask||"")}"
12626
+ data-ask-at="${D(t.askAt||"")}">
11661
12627
 
11662
12628
  <header class="ax-task-page__head">
11663
12629
  <nav class="ax-crumbs" aria-label="Breadcrumb">
11664
12630
  <a href="/live">Live</a>
11665
12631
  <span class="ax-crumbs__sep">/</span>
11666
- <a href="/agents/${L(t.agentId)}/history?node=${encodeURIComponent(t.nodeUrl)}&name=${encodeURIComponent(e)}"><span class="ax-mention">@${L(t.agentId)}</span></a>
12632
+ <a href="/agents/${D(t.agentId)}/history?node=${encodeURIComponent(t.nodeUrl)}&name=${encodeURIComponent(e)}"><span class="ax-mention">@${D(t.agentId)}</span></a>
11667
12633
  <span class="ax-crumbs__sep">/</span>
11668
12634
  <span class="ax-crumbs__here">Task</span>
11669
12635
  </nav>
11670
12636
  <div class="ax-task-page__meta">
11671
- ${t.channel?`<span class="ax-badge ax-badge--mono ax-badge--ghost">${L(t.channel)}</span>`:""}
12637
+ ${t.channel?`<span class="ax-badge ax-badge--mono ax-badge--ghost">${D(t.channel)}</span>`:""}
11672
12638
  <span class="ax-badge ax-badge--mono" id="task-status">connecting\u2026</span>
11673
12639
  <span class="ax-mono ax-muted" id="task-elapsed"></span>
11674
12640
  </div>
@@ -11694,7 +12660,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
11694
12660
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
11695
12661
  </div>
11696
12662
  </footer>
11697
- </div>`;return C({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:yo,scripts:`<script>${wo}</script>`})}var yo=`
12663
+ </div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ro,scripts:`<script>${Do}</script>`})}var Ro=`
11698
12664
  /* The shell gives <main> no padding, so page content butted straight against
11699
12665
  the sticky topbar. Breathe. */
11700
12666
  .ax-task-page {
@@ -11836,7 +12802,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
11836
12802
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
11837
12803
  }
11838
12804
 
11839
- `,wo=`
12805
+ `,Do=`
11840
12806
  (function () {
11841
12807
  var root = document.querySelector('.ax-task-page');
11842
12808
  if (!root) return;
@@ -12192,15 +13158,15 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
12192
13158
  if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') { e.preventDefault(); sendBtn.click(); }
12193
13159
  });
12194
13160
  })();
12195
- `;function Ia(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
12196
- data-agent-id="${L(t.agentId)}"
12197
- data-agent-name="${L(e)}"
12198
- data-node-url="${L(t.nodeUrl)}">
13161
+ `;function Ba(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
13162
+ data-agent-id="${D(t.agentId)}"
13163
+ data-agent-name="${D(e)}"
13164
+ data-node-url="${D(t.nodeUrl)}">
12199
13165
  <header class="ax-history__head">
12200
13166
  <nav class="ax-crumbs" aria-label="Breadcrumb">
12201
13167
  <a href="/live">Live</a>
12202
13168
  <span class="ax-crumbs__sep">/</span>
12203
- <span class="ax-mention">@${L(t.agentId)}</span>
13169
+ <span class="ax-mention">@${D(t.agentId)}</span>
12204
13170
  <span class="ax-crumbs__sep">/</span>
12205
13171
  <span class="ax-crumbs__here">History</span>
12206
13172
  </nav>
@@ -12221,7 +13187,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
12221
13187
  <div class="ax-history__list" id="hist-list">
12222
13188
  <div class="ax-history__empty">loading\u2026</div>
12223
13189
  </div>
12224
- </div>`;return C({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ko,scripts:`<script>${_o}</script>`})}var ko=`
13190
+ </div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Po,scripts:`<script>${Oo}</script>`})}var Po=`
12225
13191
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
12226
13192
  flush against the sticky topbar. */
12227
13193
  .ax-history {
@@ -12273,7 +13239,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
12273
13239
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
12274
13240
  }
12275
13241
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
12276
- `,_o=`
13242
+ `,Oo=`
12277
13243
  (function () {
12278
13244
  var root = document.querySelector('.ax-history');
12279
13245
  if (!root) return;
@@ -12373,25 +13339,25 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
12373
13339
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
12374
13340
  });
12375
13341
  })();
12376
- `;function ja(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"])?E(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,l=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return ae(t,e,i=>$a(e,a,i,{mode:"create",convertFromYaml:l}))}}if(n==="/api/workflows/drafts"||n.startsWith("/api/workflows/drafts?")||n.startsWith("/api/workflows/drafts/"))return Eo(t,e,a,n);if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:To(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return E(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return E(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?ae(t,e,l=>{let i=l,d=a.dispatcher.emitSignal({name:s,scope:i?.scope,workflowId:i?.workflowId,payload:i?.payload});return E(e,200,{ok:!0,emission:d})}):E(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),l=o[2];if(l==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?E(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?ae(t,e,i=>{try{let d=a.layouts.save(s,i);return E(e,200,{layout:d})}catch(d){return E(e,400,{error:"invalid layout",message:d.message})}}):!0}if(l==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?ae(t,e,i=>{let d=fe.safeParse(i);if(!d.success)return E(e,200,{ok:!1,issues:d.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let c=xe(d.data).map(u=>({path:"",message:u}));return E(e,200,{ok:c.length===0,issues:c,workflow:d.data})}):!0;if(!l){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let i=a.store.get(s);return i?E(e,200,{workflow:i}):E(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=new URL(n,"http://_").searchParams,d=i.get("convertFromYaml")==="true"||i.get("convertFromYaml")==="1";return ae(t,e,c=>$a(e,a,c,{mode:"update",id:s,convertFromYaml:d}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=a.store.delete(s);return a.layouts.delete(s),E(e,i?200:404,i?{ok:!0}:{error:"workflow not found"})}}}return E(e,404,{error:"unknown workflows endpoint",path:n})}function Eo(t,e,a,n){let r=t.method||"GET",o=n.replace(/^\/api\/workflows\/drafts/,""),s=a.store.baseDir;if(o===""||o.startsWith("?")){if(r!=="GET")return E(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:read"]))return!0;let c=ot(process.cwd(),{workflowDir:s}).map(u=>({id:u.id,path:u.path,workflow:u.workflow,issues:ve(u.workflow)}));return E(e,200,{drafts:c})}let l=o.match(/^\/([^\/?]+)(\/validate|\/promote|\/reject)?$/);if(!l)return E(e,404,{error:"unknown drafts endpoint"});let i=decodeURIComponent(l[1]),d=l[2];if(!d&&r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let c=je(i,process.cwd(),{workflowDir:s});return c?E(e,200,{draft:c,issues:ve(c.workflow)}):E(e,404,{error:"draft not found"})}if(!d&&r==="PUT")return a.requireScope(t,e,["dashboard:write"])?ae(t,e,c=>{try{let u=c?.workflow??c;if(!u||typeof u!="object")return E(e,400,{error:"missing workflow body"});if(u.id&&u.id!==i)return E(e,400,{error:`draft id mismatch: body=${u.id}, url=${i}`});let g=fe.safeParse({...u,id:i});if(!g.success)return E(e,400,{error:"draft schema invalid",issues:g.error.issues.map(T=>`${T.path.join(".")||"<root>"}: ${T.message}`)});let f=xe(g.data),k=rt(g.data,{format:"yaml",workflowDir:s,force:!0});return E(e,200,{ok:!0,id:i,path:k,issues:f,workflow:g.data})}catch(u){return E(e,500,{error:u?.message||String(u)})}}):!0;if(d==="/validate"){if(r!=="POST")return E(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:read"]))return!0;let c=je(i,process.cwd(),{workflowDir:s});if(!c)return E(e,404,{error:"draft not found"});let u=ve(c.workflow);return E(e,200,{ok:u.length===0,issues:u,draft:c})}if(d==="/promote")return r!=="POST"?E(e,405,{error:"method not allowed"}):a.requireScope(t,e,["dashboard:write"])?ae(t,e,c=>{try{let u=!!c?.replace,g=c?.format==="json"?"json":"yaml",f=st(i,{replace:u,format:g,workflowDir:s});return a.layouts.sync(f.workflow.id,f.workflow.nodes.map(k=>k.id)),E(e,200,{ok:!0,...f})}catch(u){return E(e,400,{error:u?.message||String(u)})}}):!0;if(d==="/reject"){if(r!=="POST")return E(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;try{let c=it(i,process.cwd(),{workflowDir:s});return E(e,200,{ok:!0,id:i,archived:c})}catch(c){return E(e,400,{error:c?.message||String(c)})}}return E(e,405,{error:"method not allowed"})}var So=["mesh"];function $a(t,e,a,n){let r=fe.safeParse(a);if(!r.success)return E(t,400,{error:"invalid workflow",issues:r.error.issues.map(i=>({path:i.path.join("."),message:i.message}))});let o=r.data,s=xe(o);if(s.length>0)return E(t,400,{error:"lint errors",issues:s.map(i=>({path:"",message:i}))});if(n.mode==="update"&&o.id!==n.id)return E(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return E(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let i=a,d=e.store.get(n.id);if(d)for(let c of So)!(c in i)&&c in d&&(o[c]=d[c])}let l;try{l=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(i){let d=i?.message||String(i),c=i?.yamlPath,u=!!c||/yaml round-trip failed/.test(d);return E(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",...c?{path:c}:{}})}return e.layouts.sync(l.id,l.nodes.map(i=>i.id)),E(t,200,{workflow:l})}function To(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let i=Math.max(1,Math.min(500,Number(r.get("limit")||50))),d=r.get("workflowId")||void 0,c=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:d,limit:i});if(!c)return E(e,200,{runs:u});let g=u.map(f=>({id:f.id,workflowId:f.workflowId,workflowVersion:f.workflowVersion,homeNode:f.homeNode,status:f.status,pending:f.pending,entityRef:f.entityRef,history:(f.history||[]).slice(-5),parentRunId:f.parentRunId,parentNodeId:f.parentNodeId,rootRunId:f.rootRunId,depth:f.depth,createdAt:f.createdAt,updatedAt:f.updatedAt}));return E(e,200,{runs:g})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return E(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=decodeURIComponent(s[1]);return ae(t,e,d=>{let c=d?.status;return c!=="paused"&&c!=="running"&&c!=="canceled"?E(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(i,c)?E(e,200,{ok:!0,runId:i,status:c}):E(e,404,{error:"run not found"})})}let l=o.match(/^\/([^\/?]+)(\/stream)?$/);if(l){let i=decodeURIComponent(l[1]);if(l[2])return Co(t,e,a,i);let d=a.runs.get(i);return d?E(e,200,{run:d}):E(e,404,{error:"run not found"})}return E(e,404,{error:"unknown runs endpoint"})}function Co(t,e,a,n){let r=a.runs.get(n);if(!r)return E(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)}
13342
+ `;function qa(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"])?T(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 re(t,e,l=>za(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n==="/api/workflows/drafts"||n.startsWith("/api/workflows/drafts?")||n.startsWith("/api/workflows/drafts/"))return Ho(t,e,a,n);if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Bo(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return T(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return T(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?re(t,e,i=>{let l=i,d=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return T(e,200,{ok:!0,emission:d})}):T(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"])?T(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?re(t,e,l=>{try{let d=a.layouts.save(s,l);return T(e,200,{layout:d})}catch(d){return T(e,400,{error:"invalid layout",message:d.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?re(t,e,l=>{let d=ve.safeParse(l);if(!d.success)return T(e,200,{ok:!1,issues:d.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=be(d.data).map(u=>({path:"",message:u}));return T(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?T(e,200,{workflow:l}):T(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 re(t,e,p=>za(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),T(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return T(e,404,{error:"unknown workflows endpoint",path:n})}function Ho(t,e,a,n){let r=t.method||"GET",o=n.replace(/^\/api\/workflows\/drafts/,""),s=a.store.baseDir;if(o===""||o.startsWith("?")){if(r!=="GET")return T(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:read"]))return!0;let p=ct(process.cwd(),{workflowDir:s}).map(u=>({id:u.id,path:u.path,workflow:u.workflow,issues:ye(u.workflow)}));return T(e,200,{drafts:p})}let i=o.match(/^\/([^\/?]+)(\/validate|\/promote|\/reject)?$/);if(!i)return T(e,404,{error:"unknown drafts endpoint"});let l=decodeURIComponent(i[1]),d=i[2];if(!d&&r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let p=Pe(l,process.cwd(),{workflowDir:s});return p?T(e,200,{draft:p,issues:ye(p.workflow)}):T(e,404,{error:"draft not found"})}if(!d&&r==="PUT")return a.requireScope(t,e,["dashboard:write"])?re(t,e,p=>{try{let u=p?.workflow??p;if(!u||typeof u!="object")return T(e,400,{error:"missing workflow body"});if(u.id&&u.id!==l)return T(e,400,{error:`draft id mismatch: body=${u.id}, url=${l}`});let f=ve.safeParse({...u,id:l});if(!f.success)return T(e,400,{error:"draft schema invalid",issues:f.error.issues.map(A=>`${A.path.join(".")||"<root>"}: ${A.message}`)});let v=be(f.data),k=dt(f.data,{format:"yaml",workflowDir:s,force:!0});return T(e,200,{ok:!0,id:l,path:k,issues:v,workflow:f.data})}catch(u){return T(e,500,{error:u?.message||String(u)})}}):!0;if(d==="/validate"){if(r!=="POST")return T(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:read"]))return!0;let p=Pe(l,process.cwd(),{workflowDir:s});if(!p)return T(e,404,{error:"draft not found"});let u=ye(p.workflow);return T(e,200,{ok:u.length===0,issues:u,draft:p})}if(d==="/promote")return r!=="POST"?T(e,405,{error:"method not allowed"}):a.requireScope(t,e,["dashboard:write"])?re(t,e,p=>{try{let u=!!p?.replace,f=p?.format==="json"?"json":"yaml",v=pt(l,{replace:u,format:f,workflowDir:s});return a.layouts.sync(v.workflow.id,v.workflow.nodes.map(k=>k.id)),T(e,200,{ok:!0,...v})}catch(u){return T(e,400,{error:u?.message||String(u)})}}):!0;if(d==="/reject"){if(r!=="POST")return T(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;try{let p=ut(l,process.cwd(),{workflowDir:s});return T(e,200,{ok:!0,id:l,archived:p})}catch(p){return T(e,400,{error:p?.message||String(p)})}}return T(e,405,{error:"method not allowed"})}var No=["mesh"];function za(t,e,a,n){let r=ve.safeParse(a);if(!r.success)return T(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=be(o);if(s.length>0)return T(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return T(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return T(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 No)!(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 T(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)),T(t,200,{workflow:i})}function Bo(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 T(e,200,{runs:u});let f=u.map(v=>({id:v.id,workflowId:v.workflowId,workflowVersion:v.workflowVersion,homeNode:v.homeNode,status:v.status,pending:v.pending,entityRef:v.entityRef,history:(v.history||[]).slice(-5),parentRunId:v.parentRunId,parentNodeId:v.parentNodeId,rootRunId:v.rootRunId,depth:v.depth,createdAt:v.createdAt,updatedAt:v.updatedAt}));return T(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return T(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return re(t,e,d=>{let p=d?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?T(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?T(e,200,{ok:!0,runId:l,status:p}):T(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return zo(t,e,a,l);let d=a.runs.get(l);return d?T(e,200,{run:d}):T(e,404,{error:"run not found"})}return T(e,404,{error:"unknown runs endpoint"})}function zo(t,e,a,n){let r=a.runs.get(n);if(!r)return T(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)}
12377
13343
 
12378
- `);let o=!1,s=()=>{o=!0,i?.(),clearInterval(c);try{e.end()}catch{}};t.on("close",s);let l=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
13344
+ `);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)}
12379
13345
 
12380
- `)}catch{s()}},i=a.runEvents?.subscribe(n,l),d=r.updatedAt,c=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==d&&(d=u.updatedAt,l(u))},2e3);return!0}function ae(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){E(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{E(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{E(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>E(e,400,{error:"body read failed",message:r.message})),!0}function E(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}function ll(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let f of a)try{s.set(f.id,No(f,t))}catch(k){console.error(` Board "${f.id}" failed to initialize: ${k.message}`)}let l=t.node?.id||"local",i=t.workflows?.dir?he(process.cwd(),t.workflows.dir):void 0,d=new Ze(i?{baseDir:i}:void 0),c=new et(i?{baseDir:i,nodeId:l}:{nodeId:l}),u=new tt(i?{baseDir:i}:void 0);ca(t),lt({business:t.business?.enabled===!0}),Ao(async(f,k)=>{try{await Po(f,k,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:c,workflowLayouts:u})}catch(T){w(k,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let f=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
12381
- Live dashboard: http://${f}:${n}
13346
+ `)}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 re(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){T(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{T(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{T(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>T(e,400,{error:"body read failed",message:r.message})),!0}function T(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}function Rl(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let v of a)try{s.set(v.id,Zo(v,t))}catch(k){console.error(` Board "${v.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?xe(process.cwd(),t.workflows.dir):void 0,d=new rt(l?{baseDir:l}:void 0),p=new ot(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new st(l?{baseDir:l}:void 0);ma(t),mt({business:t.business?.enabled===!0}),qo(async(v,k)=>{try{await Jo(v,k,{boards:a,sources:s,token:o,config:t,workflowStore:d,workflowRuns:p,workflowLayouts:u})}catch(A){y(k,500,{error:A.message||"internal error"})}}).listen(n,r,()=>{let v=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
13347
+ Live dashboard: http://${v}:${n}
12382
13348
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
12383
- Kanban dashboard: http://${f}:${n}
12384
- `),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Ro=new Set(["/","/live","/mesh","/boards","/glossary","/workflows","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki","/admin/activity-graph"]);async function Po(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"),o==="OPTIONS"){e.writeHead(204),e.end();return}if(o==="GET"&&Ro.has(r)&&Et("page",r),o==="GET"&&r==="/"){let p=yt();if(!p.configExists||p.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(We({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ea({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(We({peers:H(a.config)}));return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_a({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Sa({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ta({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ca({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(bt({}));return}let s=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(s){let p=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!p){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(Aa({taskId:decodeURIComponent(s[1]),agentId:p,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:H(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(Ia({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){wt(t,e);return}if(o==="POST"&&r==="/api/setup"){await kt(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await _t(t,e);return}if(o==="GET"&&r==="/admin"){$t(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Ot(t,e,H(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}Wt(t,e,H(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let p=String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(p==="fleet"){if(r==="/api/admin/activity-graph"){await es(t,e,a);return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let h=x.slice(0,v),y=x.slice(v+2),_=a.config.node?.id||a.config.node?.name||"local";if(h===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(y)}`;else{let $=(a.config.dashboard?.daemons||[]).find(I=>(I.name||I.url)===h);if($){let I=Xe($.url.replace(/\/+$/,""),a.config);if(I){await Ma(t,e,I,`/api/admin/activity-graph/dispatch/${encodeURIComponent(y)}`);return}}w(e,404,{error:`unknown node "${h}" in fleet dispatch id`});return}}}}else if(p&&p!=="primary"){let m=Xe(p,a.config);if(!m){w(e,404,{error:`unknown peer: ${p}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,h=>h.startsWith("?")?"?":"");await Ma(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Gt(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await ts(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:p}=await import("./doctor-DHLBEKA4.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await p({running:x});w(e,200,v)}catch(p){w(e,500,{error:p?.message||String(p)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xt({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Vt(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Yt({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qt({peers:H(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 zo(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){na(t,e,H(a.config));return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await pa(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ua(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ga(t,e,r))return;let i=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(i){xa(t,e,i[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let p=t.headers.authorization||"",m=p.startsWith("Bearer ")?p.slice(7):"";if(m!==a.token){let x=new Y,v=m?x.verify(m):null;if(!v||!pe(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await jt(t,e);return}if(r.startsWith("/api/admin/graph/")){await Ht(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await va(t,e,r);return}if(r.startsWith("/api/admin/")){await Mt(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(Tt);return}if(o==="GET"&&r.startsWith("/assets/")){let p=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(p)){w(e,400,{error:"invalid asset name"});return}let m=Qo("web/"+p);try{let x=await Zo(m),v=p.endsWith(".map")?"application/json; charset=utf-8":p.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8";e.writeHead(200,{"Content-Type":v,"Cache-Control":"public, max-age=60"}),e.end(x)}catch{w(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let p=await Ve(a.config);w(e,200,p)}catch(p){w(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let p=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await Ve(a.config,{date:p,timezone:m});w(e,200,x)}catch(p){w(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/live/stream"){Uo(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let p=new URL(t.url||"/","http://localhost"),m=p.searchParams.get("node"),x=p.searchParams.get("agent"),v=p.searchParams.get("task");if(!m||!x||!v){w(e,400,{error:"node, agent, task query params required"});return}await Fo(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let p=new URL(t.url||"/","http://localhost"),m=p.searchParams.get("node"),x=p.searchParams.get("agent"),v=p.searchParams.get("task"),h=p.searchParams.get("limit")||"50";if(!m||!x){w(e,400,{error:"node and agent query params required"});return}await Ko(e,a,m,x,v,h);return}if(o==="POST"&&r==="/api/task/action"){let p=new URL(t.url||"/","http://localhost"),m=p.searchParams.get("node"),x=p.searchParams.get("task"),v=p.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){w(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Jo(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/agents"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:p});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();w(e,200,x)}catch(p){w(e,502,{error:p.message||"agents fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let p=await ne(t);try{let m=await Xo(a.config,p);w(e,200,m)}catch(m){w(e,502,{error:m.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let p=d[1];if(!Wo(t,e,[`agent:${p}`]))return;await Go(t,e,a.config,p);return}if(r.startsWith("/api/")&&a.token){let p=t.headers.authorization||"",m=p.startsWith("Bearer ")?p.slice(7):"";if(m!==a.token){let x=new Y,v=m?x.verify(m):null;if(!v||!pe(v,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){w(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(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","Access-Control-Allow-Origin":"*"});let x=[{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}))],v={flag:!1},h=[];t.on("close",()=>{v.flag=!0;for(let _ of h)try{_.abort()}catch{}});let y=setInterval(()=>{if(!v.flag)try{e.write(`: ping
13349
+ Kanban dashboard: http://${v}:${n}
13350
+ `),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Ko=new Set(["/","/live","/mesh","/boards","/glossary","/workflows","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki","/admin/activity-graph"]);async function Jo(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"),o==="OPTIONS"){e.writeHead(204),e.end();return}if(o==="GET"&&Ko.has(r)&&Ct("page",r),o==="GET"&&r==="/"){let c=_t();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(Ve({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ve({peers:H(a.config)}));return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pa({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Oa({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ha({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kt({}));return}let s=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(s){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(Na({taskId:decodeURIComponent(s[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:H(a.config)}));return}let i=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(i){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ba({agentId:decodeURIComponent(i[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Et(t,e);return}if(o==="POST"&&r==="/api/setup"){await St(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Tt(t,e);return}if(o==="GET"&&r==="/admin"){Lt(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Bt(t,e,H(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}Kt(t,e,H(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let c=String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(c==="fleet"){if(r==="/api/admin/activity-graph"){await hs(t,e,a);return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let g=decodeURIComponent(m[1]),x=g.indexOf("::");if(x>0){let h=g.slice(0,x),b=g.slice(x+2),_=a.config.node?.id||a.config.node?.name||"local";if(h===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let j=(a.config.dashboard?.daemons||[]).find($=>($.name||$.url)===h);if(j){let $=tt(j.url.replace(/\/+$/,""),a.config);if($){await Ua(t,e,$,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${h}" in fleet dispatch id`});return}}}}else if(c&&c!=="primary"){let m=tt(c,a.config);if(!m){y(e,404,{error:`unknown peer: ${c}`});return}let g=(n.search||"").replace(/[?&]peer=[^&]*/g,h=>h.startsWith("?")?"?":"");await Ua(t,e,m,r+(g==="?"?"":g));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Jt(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await gs(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:c}=await import("./doctor-3Q36ZFE6.js"),g=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",x=await c({running:g});y(e,200,x)}catch(c){y(e,500,{error:c?.message||String(c)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Zt({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Qt(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ea({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ta({peers:H(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 ts(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){sa(t,e,H(a.config));return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await ha(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ga(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await xa(t,e,r))return;let l=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(l){ya(t,e,l[1],H(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 g=new Z,x=m?g.verify(m):null;if(!x||!me(x,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Rt(t,e);return}if(r.startsWith("/api/admin/graph/")){await zt(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await wa(t,e,r);return}if(r.startsWith("/api/admin/")){await Dt(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(Mt);return}if(o==="GET"&&r.startsWith("/assets/")){let c=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(c)){y(e,400,{error:"invalid asset name"});return}let m=us("web/"+c);try{let g=await ms(m),x=c.endsWith(".map")?"application/json; charset=utf-8":c.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8";e.writeHead(200,{"Content-Type":x,"Cache-Control":"public, max-age=60"}),e.end(g)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let c=await et(a.config);y(e,200,c)}catch(c){y(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let c=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",g=await et(a.config,{date:c,timezone:m});y(e,200,g)}catch(c){y(e,502,{error:c.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let c=(m,g,x,h)=>{let b=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(b)?Math.max(x,Math.min(h,b)):g};try{let m=await Le(a.config);y(e,200,await ja(m,{days:c("days",30,0,180),tzOffsetMinutes:c("tzOffset",0,-840,840),limit:c("limit",60,1,200)}))}catch(m){y(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let c=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(c)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(g,x,h,b)=>{let _=parseInt(n.searchParams.get(g)||"",10);return Number.isFinite(_)?Math.max(h,Math.min(b,_)):x};try{let g=await Le(a.config);y(e,200,await Ra(g,{day:c,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(g){y(e,502,{error:g.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let c=n.searchParams.get("node");if(!c){y(e,400,{error:"node query param required"});return}let m=n.searchParams,g;if(r==="/api/mesh/thread"){let[x,h,b]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!h||!b){y(e,400,{error:"agent, channel, chat required"});return}g=`/analytics/thread?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(h)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[x,h]=[m.get("kind"),m.get("key")];if(!x||!h){y(e,400,{error:"kind and key required"});return}g=`/analytics/job?kind=${encodeURIComponent(x)}&key=${encodeURIComponent(h)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[x,h,b]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!x||!h||!b){y(e,400,{error:"agent, channel, chat required"});return}g=`/analytics/conversation?agent=${encodeURIComponent(x)}&channel=${encodeURIComponent(h)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let x=m.get("task");if(!x){y(e,400,{error:"task required"});return}g=`/analytics/run/${encodeURIComponent(x)}`}try{await La(e,await Le(a.config),c,g)}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&r==="/api/live/stream"){ns(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"),g=c.searchParams.get("agent"),x=c.searchParams.get("task");if(!m||!g||!x){y(e,400,{error:"node, agent, task query params required"});return}await rs(t,e,a,m,g,x);return}if(o==="GET"&&r==="/api/task/history"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),g=c.searchParams.get("agent"),x=c.searchParams.get("task"),h=c.searchParams.get("limit")||"50";if(!m||!g){y(e,400,{error:"node and agent query params required"});return}await is(e,a,m,g,x,h);return}if(o==="POST"&&r==="/api/task/action"){let c=new URL(t.url||"/","http://localhost"),m=c.searchParams.get("node"),g=c.searchParams.get("task"),x=c.searchParams.get("kind");if(!m||!g||x!=="cancel"&&x!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await ls(t,e,a,m,g,x);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 g=await m.json();y(e,200,g)}catch(c){y(e,502,{error:c.message||"agents fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let c=await oe(t);try{let m=await cs(a.config,c);y(e,200,m)}catch(m){y(e,502,{error:m.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let c=d[1];if(!os(t,e,[`agent:${c}`]))return;await ss(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 g=new Z,x=m?g.verify(m):null;if(!x||!me(x,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="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","Access-Control-Allow-Origin":"*"});let g=[{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},h=[];t.on("close",()=>{x.flag=!0;for(let _ of h)try{_.abort()}catch{}});let b=setInterval(()=>{if(!x.flag)try{e.write(`: ping
12385
13351
 
12386
- `)}catch{}},15e3);t.on("close",()=>clearInterval(y));for(let _ of x)(async()=>{let $={Accept:"text/event-stream"};_.token&&($.Authorization=`Bearer ${_.token}`);let I=new AbortController;h.push(I);try{let b=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:$,signal:I.signal});if(!b.ok||!b.body)return;let A=b.body.getReader(),j=new TextDecoder,D="";for(;!v.flag;){let{done:O,value:X}=await A.read();if(O)break;D+=j.decode(X,{stream:!0});let M;for(;(M=D.indexOf(`
13352
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let _ of g)(async()=>{let j={Accept:"text/event-stream"};_.token&&(j.Authorization=`Bearer ${_.token}`);let $=new AbortController;h.push($);try{let w=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:j,signal:$.signal});if(!w.ok||!w.body)return;let I=w.body.getReader(),L=new TextDecoder,P="";for(;!x.flag;){let{done:O,value:Q}=await I.read();if(O)break;P+=L.decode(Q,{stream:!0});let R;for(;(R=P.indexOf(`
12387
13353
 
12388
- `))>=0;){let J=D.slice(0,M);if(D=D.slice(M+2),v.flag)break;try{e.write(J+`
13354
+ `))>=0;){let K=P.slice(0,R);if(P=P.slice(R+2),x.flag)break;try{e.write(K+`
12389
13355
 
12390
- `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let p=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(p.searchParams.get("limit")||50))),x=p.searchParams.get("workflowId")||void 0,v=p.searchParams.get("summary")==="1"||p.searchParams.get("summary")==="true",h=a.workflowRuns.list({limit:m,workflowId:x}),y=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(j=>({url:j.url,token:j.token}))],$=await Promise.all(_.map(async j=>{let D={};j.token&&(D.Authorization=`Bearer ${j.token}`);try{let O=new AbortController,X=setTimeout(()=>O.abort(),5e3);try{let M=await fetch(`${j.url.replace(/\/+$/,"")}/api/workflows/runs${y}`,{headers:D,signal:O.signal});if(!M.ok)return[];let J=await M.json();return Array.isArray(J.runs)?J.runs:[]}finally{clearTimeout(X)}}catch{return[]}})),I=new Map;for(let j of h)I.set(j.id,j);for(let j of $)for(let D of j)I.set(D.id,D);let b=Array.from(I.values()).sort((j,D)=>j.updatedAt<D.updatedAt?1:-1).slice(0,m),A=v?b.map(j=>Ho(j)):b;w(e,200,{runs:A})}catch(p){w(e,502,{error:"runs fetch failed",message:p.message||String(p)})}return}let u=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(u){let p=decodeURIComponent(u[1]),m=a.workflowRuns.get(p);if(m){w(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let h={};v.token&&(h.Authorization=`Bearer ${v.token}`);let y=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(p)}`,{headers:h});if(y.ok){w(e,200,await y.json());return}}catch{}w(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${m}/api/actions/builtin`,{headers:p}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));w(e,x.status,v)}catch(p){w(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}let g=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(g){try{let p=await ne(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(g[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(p??{})}),h=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,h)}catch(p){w(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}let f=o==="POST"&&r.match(/^\/api\/workflows\/drafts\/([^/]+)\/replay$/);if(f){try{let p=await ne(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/drafts/${encodeURIComponent(f[1])}/replay`,{method:"POST",headers:m,body:JSON.stringify(p??{})}),h=await v.json().catch(()=>({error:`HTTP ${v.status}`}));w(e,v.status,h)}catch(p){w(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(r.startsWith("/api/workflows")&&ja(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let h=Me(m);if(!h)return!0;let y=new Y().verify(h);if(!y)return w(x,401,{error:"invalid or revoked token"}),!1;for(let _ of v)if(!pe(y,_))return w(x,403,{error:`token missing scope: ${_}`,scopes:y.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){w(e,200,a.boards.map(p=>({id:p.id,name:p.name,source:p.source,primaryToolLabel:p.primaryToolLabel,labels:p.labels,columns:p.columns,timeRangeDays:p.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let p=a.sources.get(k[1]);if(!p){w(e,404,{error:"unknown board"});return}try{let m=typeof p.listMembers=="function"?await p.listMembers():[];w(e,200,m)}catch(m){w(e,502,{error:m.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(T&&o==="GET"){let p=a.sources.get(T[1]);if(!p){w(e,404,{error:"unknown board"});return}try{let m=typeof p.listMilestones=="function"?await p.listMilestones():[];w(e,200,m)}catch(m){w(e,502,{error:m.message})}return}let R=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),P=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(R&&o==="PATCH"){let[,p,m]=R,x=decodeURIComponent(m),v=a.boards.find(I=>I.id===p);if(!v){w(e,404,{error:`unknown board: ${p}`});return}let h=a.sources.get(p);if(!h){w(e,503,{error:`board "${p}" source unavailable`});return}let y=await ne(t),_=v.columns.find(I=>I.id===y.to),$=v.columns.find(I=>I.id===y.from);if(!_){w(e,400,{error:`unknown 'to' column: ${y.to}`});return}try{await Oo(h,x,$,_),Ge({actor:Ke(t),action:"move",boardId:p,itemId:x,payload:{from:y.from,to:y.to}}),w(e,200,{ok:!0})}catch(I){w(e,502,{error:I.message||"transition failed"})}return}if(P){let[,p,m]=P,x=m?decodeURIComponent(m):void 0,v=a.boards.find(y=>y.id===p);if(!v){w(e,404,{error:`unknown board: ${p}`});return}let h=a.sources.get(p);if(!h){w(e,503,{error:`board "${p}" source unavailable`});return}if(o==="GET"&&!x){let{columns:y,totals:_}=await Do(v,h,n.searchParams);w(e,200,{columns:y,totals:_});return}if(o==="GET"&&x){try{let y=typeof h.getItem=="function"?await h.getItem(x):null;if(!y){w(e,404,{error:"not found"});return}w(e,200,y)}catch(y){w(e,502,{error:y.message})}return}if(o==="PATCH"&&x){let y=await ne(t);try{let _=typeof h.updateItem=="function"?await h.updateItem(x,y):null;if(!_){w(e,501,{error:"update unsupported"});return}Ge({actor:Ke(t),action:"update",boardId:p,itemId:x,payload:y}),w(e,200,_)}catch(_){w(e,502,{error:_.message})}return}if(o==="POST"&&!x){let y=await ne(t);if(!y.title){w(e,400,{error:"title required"});return}if(!h.capabilities.create||!h.create){w(e,400,{error:`source ${h.type} does not support create`});return}try{let _=await h.create({title:y.title,description:y.description,labels:y.labels,assigneeUsernames:y.assigneeUsernames,milestoneTitle:y.milestoneTitle,projectHint:y.projectHint});Ge({actor:Ke(t),action:"create",boardId:p,itemId:_.id,payload:{title:y.title}}),w(e,201,_)}catch(_){w(e,502,{error:_.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let p=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",activity:"/admin/activity-graph",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[p];if(x){e.writeHead(302,{Location:x}),e.end();return}}w(e,404,{error:"not found",path:r})}async function Do(t,e,a){if(!e.capabilities.listAll||!e.listAll){let p={};for(let m of t.columns)p[m.id]=[];return{columns:p,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,l=a.get("assignee")||void 0,i=parseInt(a.get("days")||String(t.timeRangeDays),10),d=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),c=t.columns.some(p=>p.kind!=="closed"),u=t.columns.some(p=>p.kind==="closed"),g=c?await e.listAll({sinceDays:i,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],f=u?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let p of t.columns)k[p.id]=[];let T=t.columns.find(p=>p.kind==="closed");for(let p of f)T&&k[T.id].push({...p,stage:T.id});let R=t.columns.filter(p=>p.kind!=="closed");for(let p of g){let m=at(p,R);if(!m)continue;let x=k[m];x&&x.push({...p,stage:m})}if(l)for(let p of Object.keys(k))k[p]=k[p].filter(m=>m.assignee===l);for(let p of Object.keys(k))k[p].sort((m,x)=>{let v=(m.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let P=Object.fromEntries(Object.entries(k).map(([p,m])=>[p,m.length]));return{columns:k,totals:P}}async function Oo(t,e,a,n){let r=nt(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 Ho(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 No(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 ct(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ge(t){try{let e=he(process.cwd(),".agentx");La(e)||$o(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
12391
- `;Io(he(e,"board-audit.jsonl"),a)}catch{}}function Ke(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function Bo(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)}`:"",[l,i,d,c,u]=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)]);if(!i||!i.ok)return o.error=i?`HTTP ${i.status}`:"unreachable",o;let g=await i.json();if(o.agents=g.map(f=>({id:f.id,name:f.name,tier:f.tier,model:f.model,skillCount:Number.isFinite(f.skillCount)?f.skillCount:void 0,active:f.active||0,total:f.total||0,errors:f.errors||0,lastActive:f.lastActive,lastSummary:f.lastSummary,hourlyTasks:Array.isArray(f.hourlyTasks)?f.hourlyTasks:void 0,runningTasks:Array.isArray(f.runningTasks)?f.runningTasks:[]})),l&&l.ok){let f=await l.json();o.uptimeSec=f.uptime,o.name=f.node?.name||f.node?.id||t,o.id=f.node?.id||t,f.usage&&(o.usage=f.usage)}if(c&&c.ok){let f=await c.json();o.crons=f.map(k=>({id:k.id,enabled:k.enabled===!0,schedule:String(k.schedule||""),timezone:k.timezone,agent:String(k.agent||""),nextRun:k.nextRun,retryPending:k.retryPending===!0,consecutiveErrors:Number(k.consecutiveErrors)||0}))}if(u&&u.ok){let f=await u.json();o.cronRuns=Array.isArray(f.runs)?f.runs:[]}o.reachable=!0,o._peers=Array.isArray(d&&await qo(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Ae=null;function zo(t){if(Ae)return Ae;let e=he(process.cwd(),".agentx/wiki");return Ae=St({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Ae}var Je=new WeakMap;async function qo(t){if(Je.has(t))return Je.get(t);try{let e=t.ok?await t.json():null;return Je.set(t,e),e}catch{return null}}async function Ie(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 Ve(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=a.token,o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let d=i.url.replace(/\/+$/,"");o.has(d)||o.set(d,{name:i.name,url:d,token:i.token})}let s=new AbortController,l=setTimeout(()=>s.abort(),3e3);try{let i=await Ie(n,r,s.signal);for(let c of i)o.has(c.url)||o.set(c.url,c);let d=await Promise.all([...o.values()].map(c=>Bo(c.url,c.token,s.signal,e)));return{ts:new Date().toISOString(),nodes:d}}finally{clearTimeout(l)}}function Uo(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,i)=>{n||e.write(`event: ${l}
12392
- data: ${JSON.stringify(i)}
13356
+ `)}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))),g=c.searchParams.get("workflowId")||void 0,x=c.searchParams.get("summary")==="1"||c.searchParams.get("summary")==="true",h=a.workflowRuns.list({limit:m,workflowId:g}),b=`?limit=${m}${g?`&workflowId=${encodeURIComponent(g)}`:""}${x?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],j=await Promise.all(_.map(async L=>{let P={};L.token&&(P.Authorization=`Bearer ${L.token}`);try{let O=new AbortController,Q=setTimeout(()=>O.abort(),5e3);try{let R=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:P,signal:O.signal});if(!R.ok)return[];let K=await R.json();return Array.isArray(K.runs)?K.runs:[]}finally{clearTimeout(Q)}}catch{return[]}})),$=new Map;for(let L of h)$.set(L.id,L);for(let L of j)for(let P of L)$.set(P.id,P);let w=Array.from($.values()).sort((L,P)=>L.updatedAt<P.updatedAt?1:-1).slice(0,m),I=x?w.map(L=>Qo(L)):w;y(e,200,{runs:I})}catch(c){y(e,502,{error:"runs fetch failed",message:c.message||String(c)})}return}let u=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(u){let c=decodeURIComponent(u[1]),m=a.workflowRuns.get(c);if(m){y(e,200,{run:m});return}let g=[{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 g)try{let h={};x.token&&(h.Authorization=`Bearer ${x.token}`);let b=await fetch(`${x.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(c)}`,{headers:h});if(b.ok){y(e,200,await b.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let c={};a.config.dashboard.token&&(c.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${m}/api/actions/builtin`,{headers:c}),x=await g.json().catch(()=>({error:`HTTP ${g.status}`}));y(e,g.status,x)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let f=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(f){try{let c=await oe(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${g}/workflows/${encodeURIComponent(f[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),h=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,h)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}let v=o==="POST"&&r.match(/^\/api\/workflows\/drafts\/([^/]+)\/replay$/);if(v){try{let c=await oe(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${g}/api/workflows/drafts/${encodeURIComponent(v[1])}/replay`,{method:"POST",headers:m,body:JSON.stringify(c??{})}),h=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,h)}catch(c){y(e,502,{error:"daemon unreachable",message:c.message||String(c)})}return}if(r.startsWith("/api/workflows")&&qa(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,g,x)=>{if(a.token)return!0;let h=Oe(m);if(!h)return!0;let b=new Z().verify(h);if(!b)return y(g,401,{error:"invalid or revoked token"}),!1;for(let _ of x)if(!me(b,_))return y(g,403,{error:`token missing scope: ${_}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(c=>({id:c.id,name:c.name,source:c.source,primaryToolLabel:c.primaryToolLabel,labels:c.labels,columns:c.columns,timeRangeDays:c.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let c=a.sources.get(k[1]);if(!c){y(e,404,{error:"unknown board"});return}try{let m=typeof c.listMembers=="function"?await c.listMembers():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let A=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(A&&o==="GET"){let c=a.sources.get(A[1]);if(!c){y(e,404,{error:"unknown board"});return}try{let m=typeof c.listMilestones=="function"?await c.listMilestones():[];y(e,200,m)}catch(m){y(e,502,{error:m.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,c,m]=E,g=decodeURIComponent(m),x=a.boards.find($=>$.id===c);if(!x){y(e,404,{error:`unknown board: ${c}`});return}let h=a.sources.get(c);if(!h){y(e,503,{error:`board "${c}" source unavailable`});return}let b=await oe(t),_=x.columns.find($=>$.id===b.to),j=x.columns.find($=>$.id===b.from);if(!_){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await Yo(h,g,j,_),Ye({actor:Qe(t),action:"move",boardId:c,itemId:g,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch($){y(e,502,{error:$.message||"transition failed"})}return}if(S){let[,c,m]=S,g=m?decodeURIComponent(m):void 0,x=a.boards.find(b=>b.id===c);if(!x){y(e,404,{error:`unknown board: ${c}`});return}let h=a.sources.get(c);if(!h){y(e,503,{error:`board "${c}" source unavailable`});return}if(o==="GET"&&!g){let{columns:b,totals:_}=await Vo(x,h,n.searchParams);y(e,200,{columns:b,totals:_});return}if(o==="GET"&&g){try{let b=typeof h.getItem=="function"?await h.getItem(g):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&g){let b=await oe(t);try{let _=typeof h.updateItem=="function"?await h.updateItem(g,b):null;if(!_){y(e,501,{error:"update unsupported"});return}Ye({actor:Qe(t),action:"update",boardId:c,itemId:g,payload:b}),y(e,200,_)}catch(_){y(e,502,{error:_.message})}return}if(o==="POST"&&!g){let b=await oe(t);if(!b.title){y(e,400,{error:"title required"});return}if(!h.capabilities.create||!h.create){y(e,400,{error:`source ${h.type} does not support create`});return}try{let _=await h.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});Ye({actor:Qe(t),action:"create",boardId:c,itemId:_.id,payload:{title:b.title}}),y(e,201,_)}catch(_){y(e,502,{error:_.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let c=r.replace(/^\/+|\/+$/g,""),g={health:"/admin/health",activity:"/admin/activity-graph",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[c];if(g){e.writeHead(302,{Location:g}),e.end();return}}y(e,404,{error:"not found",path:r})}async function Vo(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"}):[],v=u?await e.listAll({sinceDays:d,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let c of t.columns)k[c.id]=[];let A=t.columns.find(c=>c.kind==="closed");for(let c of v)A&&k[A.id].push({...c,stage:A.id});let E=t.columns.filter(c=>c.kind!=="closed");for(let c of f){let m=it(c,E);if(!m)continue;let g=k[m];g&&g.push({...c,stage:m})}if(i)for(let c of Object.keys(k))k[c]=k[c].filter(m=>m.assignee===i);for(let c of Object.keys(k))k[c].sort((m,g)=>{let x=(m.priority??99)-(g.priority??99);return x!==0?x:(g.updatedAt||"").localeCompare(m.updatedAt||"")});let S=Object.fromEntries(Object.entries(k).map(([c,m])=>[c,m.length]));return{columns:k,totals:S}}async function Yo(t,e,a,n){let r=lt(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 Qo(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 Zo(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 gt(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ye(t){try{let e=xe(process.cwd(),".agentx");Fa(e)||Fo(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
13357
+ `;Uo(xe(e,"board-audit.jsonl"),a)}catch{}}function Qe(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function es(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]=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)]);if(!l||!l.ok)return o.error=l?`HTTP ${l.status}`:"unreachable",o;let f=await l.json();if(o.agents=f.map(v=>({id:v.id,name:v.name,tier:v.tier,model:v.model,skillCount:Number.isFinite(v.skillCount)?v.skillCount:void 0,active:v.active||0,total:v.total||0,errors:v.errors||0,lastActive:v.lastActive,lastSummary:v.lastSummary,hourlyTasks:Array.isArray(v.hourlyTasks)?v.hourlyTasks:void 0,runningTasks:Array.isArray(v.runningTasks)?v.runningTasks:[]})),i&&i.ok){let v=await i.json();o.uptimeSec=v.uptime,o.name=v.node?.name||v.node?.id||t,o.id=v.node?.id||t,v.usage&&(o.usage=v.usage)}if(p&&p.ok){let v=await p.json();o.crons=v.map(k=>({id:k.id,enabled:k.enabled===!0,schedule:String(k.schedule||""),timezone:k.timezone,agent:String(k.agent||""),model:k.model,nextRun:k.nextRun,retryPending:k.retryPending===!0,consecutiveErrors:Number(k.consecutiveErrors)||0}))}if(u&&u.ok){let v=await u.json();o.cronRuns=Array.isArray(v.runs)?v.runs:[]}o.reachable=!0,o._peers=Array.isArray(d&&await as(d))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var je=null;function ts(t){if(je)return je;let e=xe(process.cwd(),".agentx/wiki");return je=At({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),je}var Ze=new WeakMap;async function as(t){if(Ze.has(t))return Ze.get(t);try{let e=t.ok?await t.json():null;return Ze.set(t,e),e}catch{return null}}async function Re(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 Le(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=new Map;r.set(n,{name:"primary",url:n,token:a.token});for(let s of a.daemons){let i=s.url.replace(/\/+$/,"");r.has(i)||r.set(i,{name:s.name,url:i,token:s.token})}let o=await Re(n,a.token,e);for(let s of o)r.has(s.url)||r.set(s.url,s);return[...r.values()]}async function et(t,e){let a=new AbortController,n=setTimeout(()=>a.abort(),3e3);try{let r=await Le(t,a.signal),o=await Promise.all(r.map(s=>es(s.url,s.token,a.signal,e)));return{ts:new Date().toISOString(),nodes:o}}finally{clearTimeout(n)}}function ns(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=(i,l)=>{n||e.write(`event: ${i}
13358
+ data: ${JSON.stringify(l)}
12393
13359
 
12394
- `)},o=async()=>{try{let l=await Ve(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}};o();let s=setInterval(o,2e3);t.on("close",()=>{n=!0,clearInterval(s),e.end()})}async function Fo(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),l=new Set;l.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)l.add(k.url.replace(/\/+$/,""));try{let k=await Ie(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of k)l.add(T.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let i=s===a.config.dashboard.daemonUrl.replace(/\/+$/,"")?a.config.dashboard.token:a.config.dashboard.daemons.find(k=>k.url.replace(/\/+$/,"")===s)?.token,d={Accept:"text/event-stream"};i&&(d.Authorization=`Bearer ${i}`);let c=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:d,signal:c.signal})}catch(k){w(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){w(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","Access-Control-Allow-Origin":"*","X-Accel-Buffering":"no"});let g=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:T}=await g.read();if(T)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{c.abort();try{e.end()}catch{}})}function Wo(t,e,a){let n=Me(t);if(!n)return w(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Y().verify(n);if(!r)return w(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!pe(r,o))return w(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Go(t,e,a,n){let r=a.agents?.[n];if(!r){w(e,404,{error:"unknown agent"});return}if(r.access!=="public"){w(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ne(t)}catch{w(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){w(e,400,{error:"required: { message: string, context?: {...} }"});return}let l=a.dashboard.daemonUrl.replace(/\/+$/,""),i={"Content-Type":"application/json"};a.dashboard.token&&(i.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${l}/task`,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),c=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(c)}catch(d){w(e,502,{error:d.message||"upstream call failed"})}}async function Ko(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),l=new Set;l.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)l.add(u.url.replace(/\/+$/,""));try{let u=await Ie(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let g of u)l.add(g.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){w(t,403,{error:"node not in dashboard allowlist",target:s});return}let i=s===e.config.dashboard.daemonUrl.replace(/\/+$/,"")?e.config.dashboard.token:e.config.dashboard.daemons.find(u=>u.url.replace(/\/+$/,"")===s)?.token,d={Accept:"application/json"};i&&(d.Authorization=`Bearer ${i}`);let c=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${c}`,{headers:d}),g=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),t.end(g)}catch(u){w(t,502,{error:u.message||"upstream fetch failed"})}}async function Jo(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),l=new Set;l.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of a.config.dashboard.daemons)l.add(u.url.replace(/\/+$/,""));try{let u=await Ie(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let g of u)l.add(g.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let i=s===a.config.dashboard.daemonUrl.replace(/\/+$/,"")?a.config.dashboard.token:a.config.dashboard.daemons.find(u=>u.url.replace(/\/+$/,"")===s)?.token,d={"Content-Type":"application/json",Accept:"application/json"};i&&(d.Authorization=`Bearer ${i}`);let c="{}";try{let u=await ne(t);c=u?JSON.stringify(u):"{}"}catch{}try{let u=await fetch(`${s}/api/tasks/${encodeURIComponent(r)}/${o}`,{method:"POST",headers:d,body:c}),g=await u.text();e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(g)}catch(u){w(e,502,{error:u.message||"upstream fetch failed"})}}var Vo=`
13360
+ `)},o=async()=>{try{let i=await et(a);r("snapshot",i)}catch(i){r("error",{message:i.message})}};o();let s=setInterval(o,2e3);t.on("close",()=>{n=!0,clearInterval(s),e.end()})}async function rs(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await Re(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let A of k)i.add(A.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=s===a.config.dashboard.daemonUrl.replace(/\/+$/,"")?a.config.dashboard.token:a.config.dashboard.daemons.find(k=>k.url.replace(/\/+$/,"")===s)?.token,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(k){y(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Access-Control-Allow-Origin":"*","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:A}=await f.read();if(A)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function os(t,e,a){let n=Oe(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new Z().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!me(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function ss(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await oe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let d=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await d.text();e.writeHead(d.status,{"Content-Type":d.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(p)}catch(d){y(e,502,{error:d.message||"upstream call failed"})}}async function is(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 Re(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=s===e.config.dashboard.daemonUrl.replace(/\/+$/,"")?e.config.dashboard.token:e.config.dashboard.daemons.find(u=>u.url.replace(/\/+$/,"")===s)?.token,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","Access-Control-Allow-Origin":"*"}),t.end(f)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function ls(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of a.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await Re(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=s===a.config.dashboard.daemonUrl.replace(/\/+$/,"")?a.config.dashboard.token:a.config.dashboard.daemons.find(u=>u.url.replace(/\/+$/,"")===s)?.token,d={"Content-Type":"application/json",Accept:"application/json"};l&&(d.Authorization=`Bearer ${l}`);let p="{}";try{let u=await oe(t);p=u?JSON.stringify(u):"{}"}catch{}try{let u=await fetch(`${s}/api/tasks/${encodeURIComponent(r)}/${o}`,{method:"POST",headers:d,body:p}),f=await u.text();e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(f)}catch(u){y(e,502,{error:u.message||"upstream fetch failed"})}}var ds=`
12395
13361
  You are helping draft a new GitLab issue. Follow these conventions strictly.
12396
13362
 
12397
13363
  Title pattern:
@@ -12423,16 +13389,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
12423
13389
  Shape:
12424
13390
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
12425
13391
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
12426
- `;async function Xo(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):
13392
+ `;async function cs(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):
12427
13393
  - ${r.knownLabels.slice(0,60).join(`
12428
13394
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
12429
- `),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",l={"Content-Type":"application/json"};t.dashboard.token&&(l.Authorization=`Bearer ${t.dashboard.token}`);let i=await fetch(s,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:Vo}})});if(!i.ok)throw new Error(`daemon /task HTTP ${i.status}: ${await i.text().catch(()=>"")}`);let d=await i.json();if(d.error)throw new Error(String(d.error));let c=(d.content||"").toString(),u=Yo(c);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+c.slice(0,400));let g=Array.isArray(u.labels)?u.labels.filter(f=>typeof f=="string"):[];return r.primaryLabel&&!g.includes(r.primaryLabel)&&g.unshift(r.primaryLabel),r.columnLabel&&!g.includes(r.columnLabel)&&g.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:g,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:c}}function Yo(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 Qo(t){let e=Lo(Mo(import.meta.url));return he(e,t)}async function Zo(t){return jo(t)}function w(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ne(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 Ra(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(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:Ra(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 es(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6,o=a.config.node?.id||a.config.node?.name||"local",s=[],l=la(r);l&&s.push({nodeId:o,snap:l});let i=(a.config.dashboard?.daemons||[]).filter(d=>d.url);await Promise.all(i.map(async d=>{let c=Xe(d.url.replace(/\/+$/,""),a.config);if(c)try{let u=new AbortController,g=setTimeout(()=>u.abort(),8e3);try{let f=await fetch(`${c.url}/api/admin/activity-graph?hours=${r}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...c.token?{Authorization:`Bearer ${c.token}`}:{}},signal:u.signal});if(!f.ok)return;let k=await f.json();s.push({nodeId:d.name||d.url,snap:k})}finally{clearTimeout(g)}}catch{}})),w(e,200,da(s))}async function ts(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||"",g=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),f=g.find(k=>La(k));if(!f){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:g}));return}r="tail",o=["-F","-n","200",f]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
13395
+ `),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:ds}})});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=ps(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(v=>typeof v=="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 ps(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 us(t){let e=Xo(Go(import.meta.url));return xe(e,t)}async function ms(t){return Wo(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function oe(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 Wa(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(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:Wa(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 hs(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6,o=a.config.node?.id||a.config.node?.name||"local",s=[],i=pa(r);i&&s.push({nodeId:o,snap:i});let l=(a.config.dashboard?.daemons||[]).filter(d=>d.url);await Promise.all(l.map(async d=>{let p=tt(d.url.replace(/\/+$/,""),a.config);if(p)try{let u=new AbortController,f=setTimeout(()=>u.abort(),8e3);try{let v=await fetch(`${p.url}/api/admin/activity-graph?hours=${r}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...p.token?{Authorization:`Bearer ${p.token}`}:{}},signal:u.signal});if(!v.ok)return;let k=await v.json();s.push({nodeId:d.name||d.url,snap:k})}finally{clearTimeout(f)}}catch{}})),y(e,200,ua(s))}async function gs(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),v=f.find(k=>Fa(k));if(!v){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",v]}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}
12430
13396
 
12431
- `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),l="",i=u=>{l+=u.toString("utf8");let g;for(;(g=l.indexOf(`
12432
- `))>=0;){let f=l.slice(0,g).replace(/\r$/,"");l=l.slice(g+1);try{e.write(`event: line
12433
- data: ${f.replace(/\n/g," ")}
13397
+ `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
13398
+ `))>=0;){let v=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
13399
+ data: ${v.replace(/\n/g," ")}
12434
13400
 
12435
- `)}catch{}}};s.stdout?.on("data",i),s.stderr?.on("data",i);let d=setInterval(()=>{try{e.write(`: hb
13401
+ `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let d=setInterval(()=>{try{e.write(`: hb
12436
13402
 
12437
- `)}catch{}},15e3),c=()=>{clearInterval(d);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",c),s.on("exit",c),s.on("error",c)}async function Ma(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),l=o!=="GET"&&o!=="HEAD"?await new Promise((u,g)=>{let f=[];t.on("data",k=>f.push(k)),t.on("end",()=>u(Buffer.concat(f))),t.on("error",g)}):void 0,i={},d=t.headers["content-type"];d&&(i["Content-Type"]=Array.isArray(d)?d[0]:d);let c=t.headers["x-requested-with"];c&&(i["X-Requested-With"]=Array.isArray(c)?c[0]:c),a.token&&(i.Authorization=`Bearer ${a.token}`),i["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:i,body:l&&l.length>0?l:void 0}),g=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store","Access-Control-Allow-Origin":"*"}),e.end(g)}catch(u){w(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Xe(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Ra(n),token:n.dashboardToken||n.token}:null}export{ll as startBoardDashboard};
12438
- //# sourceMappingURL=board-dashboard-CQ5F4GPD.js.map
13403
+ `)}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 Ua(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 v=[];t.on("data",k=>v.push(k)),t.on("end",()=>u(Buffer.concat(v))),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","Access-Control-Allow-Origin":"*"}),e.end(f)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function tt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Wa(n),token:n.dashboardToken||n.token}:null}export{Rl as startBoardDashboard};
13404
+ //# sourceMappingURL=board-dashboard-M3372FLO.js.map