agentix-cli 0.26.0 → 0.27.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.
- package/dist/{App-BPNHIGUX.js → App-U52IPUK2.js} +2 -2
- package/dist/{ChatApp-6XSSZB4U.js → ChatApp-XP4OMHPL.js} +2 -2
- package/dist/agent-V2CA4TXD.js +2 -0
- package/dist/article-fields-L4D2BOGY.js +2 -0
- package/dist/article-quality-44ONVGLN.js +3 -0
- package/dist/article-quality-44ONVGLN.js.map +1 -0
- package/dist/{audit-JU3HWISB.js → audit-4245CX6P.js} +2 -2
- package/dist/backfill-MTD2B62I.js +6 -0
- package/dist/backfill-MTD2B62I.js.map +1 -0
- package/dist/{board-dashboard-M3372FLO.js → board-dashboard-TTMAYRLG.js} +1407 -447
- package/dist/board-dashboard-TTMAYRLG.js.map +1 -0
- package/dist/{builtin-FRKAQMFS.js → builtin-B67DMJ3M.js} +2 -2
- package/dist/calibration-ILS5OI44.js +2 -0
- package/dist/chunk-2T5W3ETS.js +5 -0
- package/dist/{chunk-K2CAPYES.js.map → chunk-2T5W3ETS.js.map} +1 -1
- package/dist/chunk-3SCPRYJB.js +5 -0
- package/dist/chunk-3SCPRYJB.js.map +1 -0
- package/dist/chunk-4BR7D2OU.js +36 -0
- package/dist/chunk-4BR7D2OU.js.map +1 -0
- package/dist/{chunk-P4VWIVKN.js → chunk-52ZPELD2.js} +403 -29
- package/dist/chunk-52ZPELD2.js.map +1 -0
- package/dist/{chunk-5U35WAZF.js → chunk-77OV7346.js} +6 -6
- package/dist/chunk-77OV7346.js.map +1 -0
- package/dist/chunk-AJ5RMU7X.js +2 -0
- package/dist/chunk-AJ5RMU7X.js.map +1 -0
- package/dist/chunk-AJONZWLT.js +2 -0
- package/dist/chunk-AJONZWLT.js.map +1 -0
- package/dist/chunk-AX2PWSRT.js +114 -0
- package/dist/chunk-AX2PWSRT.js.map +1 -0
- package/dist/chunk-BH3GTCZ6.js +2 -0
- package/dist/chunk-BH3GTCZ6.js.map +1 -0
- package/dist/chunk-BPIRO4YD.js +126 -0
- package/dist/chunk-BPIRO4YD.js.map +1 -0
- package/dist/chunk-CJQQIRPD.js +13 -0
- package/dist/chunk-CJQQIRPD.js.map +1 -0
- package/dist/chunk-DCDQZR7I.js +24 -0
- package/dist/chunk-DCDQZR7I.js.map +1 -0
- package/dist/chunk-EVWEG3VD.js +3 -0
- package/dist/chunk-EVWEG3VD.js.map +1 -0
- package/dist/chunk-F4HZTZHW.js +2 -0
- package/dist/chunk-F4HZTZHW.js.map +1 -0
- package/dist/chunk-F6CNF7V3.js +25 -0
- package/dist/chunk-F6CNF7V3.js.map +1 -0
- package/dist/chunk-FIEJDZVC.js +121 -0
- package/dist/chunk-FIEJDZVC.js.map +1 -0
- package/dist/chunk-FIOB3MEX.js +2 -0
- package/dist/{chunk-H5D7ATXS.js → chunk-FKBGJYWQ.js} +5 -5
- package/dist/chunk-FKBGJYWQ.js.map +1 -0
- package/dist/chunk-GDWJUGB5.js +9 -0
- package/dist/chunk-GDWJUGB5.js.map +1 -0
- package/dist/{chunk-BVGJSPW4.js → chunk-IB3F7VBE.js} +7 -7
- package/dist/{chunk-BVGJSPW4.js.map → chunk-IB3F7VBE.js.map} +1 -1
- package/dist/chunk-IBUSGCLQ.js +109 -0
- package/dist/chunk-IBUSGCLQ.js.map +1 -0
- package/dist/{chunk-LDHPMJ7M.js → chunk-IWMW5432.js} +3 -3
- package/dist/chunk-IWMW5432.js.map +1 -0
- package/dist/chunk-K33GIBSE.js +2 -0
- package/dist/chunk-K33GIBSE.js.map +1 -0
- package/dist/chunk-L2IZPR6P.js +45 -0
- package/dist/chunk-L2IZPR6P.js.map +1 -0
- package/dist/chunk-L2WSPY6S.js +2 -0
- package/dist/chunk-L2WSPY6S.js.map +1 -0
- package/dist/chunk-LCIREYTD.js +54 -0
- package/dist/chunk-LCIREYTD.js.map +1 -0
- package/dist/chunk-LNRB5MCU.js +530 -0
- package/dist/chunk-LNRB5MCU.js.map +1 -0
- package/dist/chunk-OPHIXXGI.js +157 -0
- package/dist/chunk-OPHIXXGI.js.map +1 -0
- package/dist/{chunk-JTJIPNXY.js → chunk-PNWNVOEZ.js} +1 -1
- package/dist/chunk-PNWNVOEZ.js.map +1 -0
- package/dist/{chunk-V3U4OF7L.js → chunk-UFAGYX73.js} +45 -47
- package/dist/chunk-UFAGYX73.js.map +1 -0
- package/dist/{chunk-DJEZ2HVU.js → chunk-VDMYBPYB.js} +1 -1
- package/dist/chunk-VDMYBPYB.js.map +1 -0
- package/dist/chunk-VTE7L6LO.js +5 -0
- package/dist/{chunk-O6YPEOQF.js.map → chunk-VTE7L6LO.js.map} +1 -1
- package/dist/chunk-W5C2GDNC.js +32 -0
- package/dist/{chunk-JP5IEXR7.js.map → chunk-W5C2GDNC.js.map} +1 -1
- package/dist/chunk-WPMX3VGI.js +3 -0
- package/dist/chunk-WPMX3VGI.js.map +1 -0
- package/dist/chunk-WZ72HX5C.js +1182 -0
- package/dist/chunk-WZ72HX5C.js.map +1 -0
- package/dist/chunk-ZTEU5JVQ.js +2 -0
- package/dist/chunk-ZTEU5JVQ.js.map +1 -0
- package/dist/{chunk-2WVX3LEC.js → chunk-ZVP6GB4G.js} +1 -1
- package/dist/chunk-ZVP6GB4G.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-PX25MD47.js +2 -0
- package/dist/{compaction-NWEMOSHA.js → compaction-FD4R23HZ.js} +4 -4
- package/dist/config-HL5F36V4.js +2 -0
- package/dist/config-mutator-HBX53OMJ.js +2 -0
- package/dist/{conflict-detector-D7VIYPDI.js → conflict-detector-ZPOT3M2C.js} +2 -2
- package/dist/conflict-detector-ZPOT3M2C.js.map +1 -0
- package/dist/context-planner-AQHJMVY2.js +17 -0
- package/dist/context-planner-AQHJMVY2.js.map +1 -0
- package/dist/debug-3MEUO2P2.js +2 -0
- package/dist/{discover-XJXQXXIO.js → discover-D4VVRNAI.js} +2 -2
- package/dist/discover-D4VVRNAI.js.map +1 -0
- package/dist/doctor-PBAH6XL3.js +2 -0
- package/dist/editor-chat-OB7IQOB5.js +137 -0
- package/dist/editor-chat-OB7IQOB5.js.map +1 -0
- package/dist/entry-triage-LK34TSQD.js +2 -0
- package/dist/entry-triage-LK34TSQD.js.map +1 -0
- package/dist/facts-YVEJOM7O.js +22 -0
- package/dist/facts-YVEJOM7O.js.map +1 -0
- package/dist/heal-FVLBHYP7.js +2 -0
- package/dist/index.d.ts +1016 -65
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/{ingest-whatsapp-LZE62INA.js → ingest-whatsapp-NS4OWDOU.js} +2 -2
- package/dist/loader-4ZGTK7LD.js +2 -0
- package/dist/loader-BOKE5M5S.js +2 -0
- package/dist/memory-extract-F5ZHWY5E.js +2 -0
- package/dist/{migrate-v2-QO7SLKIM.js → migrate-v2-V4WN2VVM.js} +2 -2
- package/dist/ntfy-X7EPB3TG.js +4 -0
- package/dist/ntfy-X7EPB3TG.js.map +1 -0
- package/dist/processes-WU23U2OJ.js +2 -0
- package/dist/program-YGXVCV2Y.js +2 -0
- package/dist/{projects-api-KRME2YKZ.js → projects-api-QE6L65SK.js} +2 -2
- package/dist/{projects-mutate-3NHVG437.js → projects-mutate-MY7JTLSZ.js} +2 -2
- package/dist/providers-KO2DODIO.js +2 -0
- package/dist/query-ZKTFJMNE.js +2 -0
- package/dist/questions-4B4KSPXG.js +3 -0
- package/dist/questions-4B4KSPXG.js.map +1 -0
- package/dist/recipes-7S4MC5OJ.js +2 -0
- package/dist/registry-PSZDPFZK.js +2 -0
- package/dist/review-candidates-AEUXRQQC.js +4 -0
- package/dist/review-candidates-AEUXRQQC.js.map +1 -0
- package/dist/review-store-B4YE3EFK.js +4 -0
- package/dist/review-store-B4YE3EFK.js.map +1 -0
- package/dist/{rotation-memo-B3EXXSEH.js → rotation-memo-7T75BLEX.js} +2 -2
- package/dist/routing-4PV66BK6.js +2 -0
- package/dist/routing-4PV66BK6.js.map +1 -0
- package/dist/runner-YRBVNYTY.js +2 -0
- package/dist/scheduler-GZZAN6ZG.js +2 -0
- package/dist/seat-VZ7AVO27.js +2 -0
- package/dist/select-F5I5PO2O.js +2 -0
- package/dist/select-F5I5PO2O.js.map +1 -0
- package/dist/store-MCOA6N4F.js +2 -0
- package/dist/{subagent-WV7QKQ3L.js → subagent-2SJHSSJS.js} +2 -2
- package/dist/{surface-usage-PRL6Z4U3.js → surface-usage-NS74AXSE.js} +2 -2
- package/dist/timers-PCB4ZIBD.js +2 -0
- package/dist/triage-backtest-JNO7RKX7.js +2 -0
- package/dist/triage-backtest-JNO7RKX7.js.map +1 -0
- package/dist/types-H5ENIUIT.js +2 -0
- package/dist/types-OIFU3KSQ.js +2 -0
- package/dist/web/workflow-editor.global.js +1542 -0
- package/dist/web/workflow-editor.global.js.map +1 -0
- package/dist/{whatsapp-state-XMTCSRXU.js → whatsapp-state-6D6FHHD2.js} +2 -2
- package/dist/wiki-N5SMP3DT.js +2 -0
- package/dist/wiki-N5SMP3DT.js.map +1 -0
- package/dist/workflows/templates/branching.yaml +1 -1
- package/dist/{workspace-setup-TBQAHYHJ.js → workspace-setup-B3F3TUDE.js} +2 -2
- package/dist/workspace-setup-B3F3TUDE.js.map +1 -0
- package/package.json +1 -1
- package/dist/agent-5QMITZT6.js +0 -2
- package/dist/architect-SEPWMWS4.js +0 -2
- package/dist/board-dashboard-M3372FLO.js.map +0 -1
- package/dist/chunk-2WVX3LEC.js.map +0 -1
- package/dist/chunk-3WQFCIB6.js +0 -24
- package/dist/chunk-3WQFCIB6.js.map +0 -1
- package/dist/chunk-4YCH6IZV.js +0 -2
- package/dist/chunk-53NRX2NA.js +0 -2
- package/dist/chunk-53NRX2NA.js.map +0 -1
- package/dist/chunk-5U35WAZF.js.map +0 -1
- package/dist/chunk-BFXONUUN.js +0 -108
- package/dist/chunk-BFXONUUN.js.map +0 -1
- package/dist/chunk-BFZUG66X.js +0 -45
- package/dist/chunk-BFZUG66X.js.map +0 -1
- package/dist/chunk-BTHHSY7D.js +0 -13
- package/dist/chunk-BTHHSY7D.js.map +0 -1
- package/dist/chunk-D46VZ7K7.js +0 -116
- package/dist/chunk-D46VZ7K7.js.map +0 -1
- package/dist/chunk-DJEZ2HVU.js.map +0 -1
- package/dist/chunk-E5CXCI33.js +0 -155
- package/dist/chunk-E5CXCI33.js.map +0 -1
- package/dist/chunk-FDWOECJY.js +0 -54
- package/dist/chunk-FDWOECJY.js.map +0 -1
- package/dist/chunk-H5D7ATXS.js.map +0 -1
- package/dist/chunk-HR4JSRZS.js +0 -3
- package/dist/chunk-HR4JSRZS.js.map +0 -1
- package/dist/chunk-ISEBLHWX.js +0 -118
- package/dist/chunk-ISEBLHWX.js.map +0 -1
- package/dist/chunk-JP5IEXR7.js +0 -32
- package/dist/chunk-JTJIPNXY.js.map +0 -1
- package/dist/chunk-K2CAPYES.js +0 -5
- package/dist/chunk-LDHPMJ7M.js.map +0 -1
- package/dist/chunk-METYYZKQ.js +0 -1115
- package/dist/chunk-METYYZKQ.js.map +0 -1
- package/dist/chunk-MTAPOCGA.js +0 -47
- package/dist/chunk-MTAPOCGA.js.map +0 -1
- package/dist/chunk-O6YPEOQF.js +0 -5
- package/dist/chunk-P4VWIVKN.js.map +0 -1
- package/dist/chunk-SR3X25TN.js +0 -3
- package/dist/chunk-SR3X25TN.js.map +0 -1
- package/dist/chunk-UHE5FCPB.js +0 -431
- package/dist/chunk-UHE5FCPB.js.map +0 -1
- package/dist/chunk-V3U4OF7L.js.map +0 -1
- package/dist/chunk-VJUTQAPJ.js +0 -2
- package/dist/chunk-VJUTQAPJ.js.map +0 -1
- package/dist/chunk-VT5XYFDD.js +0 -126
- package/dist/chunk-VT5XYFDD.js.map +0 -1
- package/dist/client-HGKAC6VP.js +0 -2
- package/dist/config-A4RWEJHV.js +0 -2
- package/dist/config-mutator-MNSFUN7D.js +0 -2
- package/dist/conflict-detector-D7VIYPDI.js.map +0 -1
- package/dist/context-planner-45GEWKGL.js +0 -17
- package/dist/context-planner-45GEWKGL.js.map +0 -1
- package/dist/debug-N3B5NVJU.js +0 -2
- package/dist/discover-XJXQXXIO.js.map +0 -1
- package/dist/doctor-3Q36ZFE6.js +0 -2
- package/dist/heal-HZ3EQD52.js +0 -2
- package/dist/loader-5CA3O5GM.js +0 -2
- package/dist/loader-6IHUCPVO.js +0 -2
- package/dist/memory-extract-AENFVVO5.js +0 -2
- package/dist/processes-UIC4XXA6.js +0 -2
- package/dist/program-SAUNRCCD.js +0 -2
- package/dist/providers-L27BJ5A6.js +0 -2
- package/dist/query-HZYYRCLU.js +0 -2
- package/dist/recipes-EPLE2SNT.js +0 -2
- package/dist/registry-HK3WQ7BS.js +0 -2
- package/dist/runner-BFYDWPUO.js +0 -2
- package/dist/scheduler-6T2SU5ST.js +0 -2
- package/dist/store-I3HEWVLQ.js +0 -2
- package/dist/timers-5LPZN55J.js +0 -2
- package/dist/types-VECTMYTO.js +0 -2
- package/dist/types-Y6ZCZ52Z.js +0 -2
- package/dist/wiki-M6YNRFC4.js +0 -2
- /package/dist/{App-BPNHIGUX.js.map → App-U52IPUK2.js.map} +0 -0
- /package/dist/{ChatApp-6XSSZB4U.js.map → ChatApp-XP4OMHPL.js.map} +0 -0
- /package/dist/{agent-5QMITZT6.js.map → agent-V2CA4TXD.js.map} +0 -0
- /package/dist/{architect-SEPWMWS4.js.map → article-fields-L4D2BOGY.js.map} +0 -0
- /package/dist/{audit-JU3HWISB.js.map → audit-4245CX6P.js.map} +0 -0
- /package/dist/{builtin-FRKAQMFS.js.map → builtin-B67DMJ3M.js.map} +0 -0
- /package/dist/{chunk-4YCH6IZV.js.map → calibration-ILS5OI44.js.map} +0 -0
- /package/dist/{client-HGKAC6VP.js.map → chunk-FIOB3MEX.js.map} +0 -0
- /package/dist/{config-A4RWEJHV.js.map → client-PX25MD47.js.map} +0 -0
- /package/dist/{compaction-NWEMOSHA.js.map → compaction-FD4R23HZ.js.map} +0 -0
- /package/dist/{config-mutator-MNSFUN7D.js.map → config-HL5F36V4.js.map} +0 -0
- /package/dist/{debug-N3B5NVJU.js.map → config-mutator-HBX53OMJ.js.map} +0 -0
- /package/dist/{doctor-3Q36ZFE6.js.map → debug-3MEUO2P2.js.map} +0 -0
- /package/dist/{heal-HZ3EQD52.js.map → doctor-PBAH6XL3.js.map} +0 -0
- /package/dist/{loader-5CA3O5GM.js.map → heal-FVLBHYP7.js.map} +0 -0
- /package/dist/{ingest-whatsapp-LZE62INA.js.map → ingest-whatsapp-NS4OWDOU.js.map} +0 -0
- /package/dist/{loader-6IHUCPVO.js.map → loader-4ZGTK7LD.js.map} +0 -0
- /package/dist/{memory-extract-AENFVVO5.js.map → loader-BOKE5M5S.js.map} +0 -0
- /package/dist/{processes-UIC4XXA6.js.map → memory-extract-F5ZHWY5E.js.map} +0 -0
- /package/dist/{migrate-v2-QO7SLKIM.js.map → migrate-v2-V4WN2VVM.js.map} +0 -0
- /package/dist/{program-SAUNRCCD.js.map → processes-WU23U2OJ.js.map} +0 -0
- /package/dist/{providers-L27BJ5A6.js.map → program-YGXVCV2Y.js.map} +0 -0
- /package/dist/{projects-api-KRME2YKZ.js.map → projects-api-QE6L65SK.js.map} +0 -0
- /package/dist/{projects-mutate-3NHVG437.js.map → projects-mutate-MY7JTLSZ.js.map} +0 -0
- /package/dist/{query-HZYYRCLU.js.map → providers-KO2DODIO.js.map} +0 -0
- /package/dist/{recipes-EPLE2SNT.js.map → query-ZKTFJMNE.js.map} +0 -0
- /package/dist/{registry-HK3WQ7BS.js.map → recipes-7S4MC5OJ.js.map} +0 -0
- /package/dist/{runner-BFYDWPUO.js.map → registry-PSZDPFZK.js.map} +0 -0
- /package/dist/{rotation-memo-B3EXXSEH.js.map → rotation-memo-7T75BLEX.js.map} +0 -0
- /package/dist/{scheduler-6T2SU5ST.js.map → runner-YRBVNYTY.js.map} +0 -0
- /package/dist/{store-I3HEWVLQ.js.map → scheduler-GZZAN6ZG.js.map} +0 -0
- /package/dist/{surface-usage-PRL6Z4U3.js.map → seat-VZ7AVO27.js.map} +0 -0
- /package/dist/{timers-5LPZN55J.js.map → store-MCOA6N4F.js.map} +0 -0
- /package/dist/{subagent-WV7QKQ3L.js.map → subagent-2SJHSSJS.js.map} +0 -0
- /package/dist/{types-VECTMYTO.js.map → surface-usage-NS74AXSE.js.map} +0 -0
- /package/dist/{types-Y6ZCZ52Z.js.map → timers-PCB4ZIBD.js.map} +0 -0
- /package/dist/{wiki-M6YNRFC4.js.map → types-H5ENIUIT.js.map} +0 -0
- /package/dist/{workspace-setup-TBQAHYHJ.js.map → types-OIFU3KSQ.js.map} +0 -0
- /package/dist/{whatsapp-state-XMTCSRXU.js.map → whatsapp-state-6D6FHHD2.js.map} +0 -0
|
@@ -1,7 +1,1019 @@
|
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import{a as Lt}from"./chunk-FKBGJYWQ.js";import{a as T,b as Rt,c as Pt,d as Dt,e as Ot,f as ee,g as ve,h as Fe,i as Nt}from"./chunk-UFAGYX73.js";import{a as Ht}from"./chunk-UCQ2N3KO.js";import{a as me,c as C,d as P,i as Ae,j as Me,k as X,l as N,m as Ie,n as It,o as $t,p as jt}from"./chunk-52ZPELD2.js";import{a as kt,c as qe,d as Ue,e as _t,m as Tt,o as ue,p as _e,q as Ee,r as Se,s as Te,t as Ct,u as At,v as Mt,w as Ce}from"./chunk-F6CNF7V3.js";import{g as yt,h as wt}from"./chunk-DCDQZR7I.js";import{a as Et,b as St}from"./chunk-IWMW5432.js";import{a as ft,b as Be,c as ze,g as xt,h as vt,i as bt}from"./chunk-GDWJUGB5.js";import"./chunk-M4AMWP3H.js";import"./chunk-4BR7D2OU.js";import"./chunk-AFRHKA7B.js";import"./chunk-FIEJDZVC.js";import"./chunk-2T5W3ETS.js";import{b as gt}from"./chunk-IBUSGCLQ.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-EVWEG3VD.js";import"./chunk-AX2PWSRT.js";import"./chunk-AJONZWLT.js";import"./chunk-F4HZTZHW.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import{a as mt,b as ht,c as cn,g as G,j as Ne}from"./chunk-CJQQIRPD.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";function We(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function Bt(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:We(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var K={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},le=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",$e=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+le(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function zt(t={}){return C({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
|
|
2
|
+
|
|
3
|
+
<div class="bf-head">
|
|
4
|
+
<div>
|
|
5
|
+
<span class="bf-kicker">Your attention, protected</span>
|
|
6
|
+
<h1>What needs you.</h1>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="bf-sync">
|
|
9
|
+
<span class="bf-sync__t" id="synced">Gathering…</span>
|
|
10
|
+
<a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${le(K.pulse,13)} Activity</a>
|
|
11
|
+
<button class="ax-btn" id="refresh" title="Refresh now">${le(K.refresh)} Refresh</button>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<p id="coverage" class="bf-sr" role="status">Gathering session reviews across your mesh…</p>
|
|
16
|
+
<div class="bf-strip" id="strip"></div>
|
|
17
|
+
<div id="coverage-note"></div>
|
|
18
|
+
<div id="principals"></div>
|
|
19
|
+
|
|
20
|
+
<p id="notice" role="status" aria-live="polite"></p>
|
|
21
|
+
|
|
22
|
+
<div class="bf-grid">
|
|
23
|
+
<section class="bf-col">
|
|
24
|
+
${$e(K.alert,"Only you","you-count",'<span class="bf-why">needs your authority, your relationship, or something the system cannot know</span><button class="ax-btn ax-btn--sm" id="clear-actions" title="Mark every open action done on every node">Clear all</button>')}
|
|
25
|
+
<div id="you" class="bf-col"></div>
|
|
26
|
+
|
|
27
|
+
${$e(K.plug,"Agents can handle","agents-count",'<span class="bf-why">no human needed — not yet automatic</span>')}
|
|
28
|
+
<div id="agents" class="bf-col"></div>
|
|
29
|
+
<button class="ax-btn ax-btn--sm" id="more-actions" hidden></button>
|
|
30
|
+
|
|
31
|
+
<div id="handled"></div>
|
|
32
|
+
</section>
|
|
33
|
+
<aside class="bf-col">
|
|
34
|
+
${$e(K.pulse,"In motion","run-count")}
|
|
35
|
+
<div id="running" class="bf-col"></div>
|
|
36
|
+
</aside>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
${$e(K.file,"Session briefings","brief-count")}
|
|
40
|
+
<div class="bf-toolbar">
|
|
41
|
+
<div class="bf-search">${le(K.search)}
|
|
42
|
+
<input id="search" type="search" placeholder="Search sessions…" aria-label="Search sessions">
|
|
43
|
+
</div>
|
|
44
|
+
<div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
|
|
45
|
+
</div>
|
|
46
|
+
<div id="reviews" class="bf-col"></div>
|
|
47
|
+
|
|
48
|
+
<section class="ax-panel bf-connect">
|
|
49
|
+
<div class="bf-connect__head">${le(K.plug,17)}<h2>Connect a CLI session</h2>
|
|
50
|
+
<span class="bf-connect__note">Daemon-owned processes only</span></div>
|
|
51
|
+
<div class="bf-discover">
|
|
52
|
+
<div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
|
|
53
|
+
<button class="ax-btn" id="discover">${le(K.search)} Discover CLIs</button>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="bf-cli" id="discovered"></div>
|
|
56
|
+
<details class="bf-manual">
|
|
57
|
+
<summary>${le(K.chev,12)} Register manually</summary>
|
|
58
|
+
<div class="bf-forms">
|
|
59
|
+
<form id="register" class="bf-form">
|
|
60
|
+
<div class="ax-sec-label"><h3>Register a session</h3></div>
|
|
61
|
+
<div class="bf-form__row">
|
|
62
|
+
<div class="ax-field"><label for="r-id">Session ID</label>
|
|
63
|
+
<input id="r-id" name="id" required maxlength="200"></div>
|
|
64
|
+
<div class="ax-field"><label for="r-rt">Runtime</label>
|
|
65
|
+
<select id="r-rt" name="runtime"><option>claude</option><option>codex</option>
|
|
66
|
+
<option>gemini</option><option>opencode</option><option>other</option></select></div>
|
|
67
|
+
</div>
|
|
68
|
+
<div class="ax-field"><label for="r-lb">Label</label>
|
|
69
|
+
<input id="r-lb" name="label" required maxlength="200"></div>
|
|
70
|
+
<button class="ax-btn ax-btn--primary">Register session</button>
|
|
71
|
+
</form>
|
|
72
|
+
<form id="ended" class="bf-form">
|
|
73
|
+
<div class="ax-sec-label"><h3>Submit an ended run</h3></div>
|
|
74
|
+
<div class="bf-form__row">
|
|
75
|
+
<div class="ax-field"><label for="registered">Registered session</label>
|
|
76
|
+
<select id="registered" name="sessionId" required></select></div>
|
|
77
|
+
<div class="ax-field"><label for="e-run">Run ID</label>
|
|
78
|
+
<input id="e-run" name="runId" required maxlength="200" placeholder="unique per turn"></div>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="ax-field"><label for="e-tr">Run transcript</label>
|
|
81
|
+
<textarea id="e-tr" name="transcript" required maxlength="100000" rows="3"
|
|
82
|
+
placeholder="Last 90 KB is submitted"></textarea></div>
|
|
83
|
+
<button class="ax-btn ax-btn--primary">Review ended run</button>
|
|
84
|
+
</form>
|
|
85
|
+
</div>
|
|
86
|
+
</details>
|
|
87
|
+
</section>
|
|
88
|
+
</div>`,css:pn,scripts:`<script>${me({decayOf:We,rankByDecay:Bt})}const ICON = ${JSON.stringify(K)};${un}</script>`})}var pn=`
|
|
89
|
+
.bf{max-width:1240px;margin:0 auto;padding:22px 24px 48px}
|
|
90
|
+
.bf-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
91
|
+
.bf :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
|
|
92
|
+
|
|
93
|
+
/* Page head */
|
|
94
|
+
.bf-head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:16px}
|
|
95
|
+
.bf-kicker{display:inline-block;font-size:10px;letter-spacing:0.1em;color:var(--ax-muted);
|
|
96
|
+
text-transform:uppercase;margin-bottom:6px;font-family:var(--ax-mono)}
|
|
97
|
+
.bf h1{font-size:22px;font-weight:600;letter-spacing:-0.015em;margin:0}
|
|
98
|
+
.bf-sync{display:flex;align-items:center;gap:12px;flex-shrink:0}
|
|
99
|
+
.bf-sync__t{font-size:11px;color:var(--ax-muted);font-family:var(--ax-mono);text-align:right;line-height:1.5}
|
|
100
|
+
.bf .ax-btn{display:inline-flex;align-items:center;gap:7px}
|
|
101
|
+
.bf .ax-btn--sm{padding:5px 12px;font-size:var(--ax-fs-sm);border-radius:var(--ax-radius-sm)}
|
|
102
|
+
|
|
103
|
+
/* Coverage counters */
|
|
104
|
+
.bf-strip{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:16px}
|
|
105
|
+
.bf-si--warn .ax-stat-inline__icon{background:color-mix(in oklch,var(--ax-warn) 14%,var(--ax-surface-2));color:var(--ax-warn)}
|
|
106
|
+
.bf-si--warn .ax-stat-inline__v{color:var(--ax-warn)}
|
|
107
|
+
.bf-si--err .ax-stat-inline__icon{background:color-mix(in oklch,var(--ax-err) 14%,var(--ax-surface-2));color:var(--ax-err)}
|
|
108
|
+
.bf-si--err .ax-stat-inline__v{color:var(--ax-err)}
|
|
109
|
+
#coverage-note:not(:empty){margin-bottom:16px}
|
|
110
|
+
.bf-callout--err{border-color:color-mix(in oklch,var(--ax-err) 30%,var(--ax-border));
|
|
111
|
+
background:color-mix(in oklch,var(--ax-err) 5%,var(--ax-bg-elev))}
|
|
112
|
+
.bf-callout--err .ax-callout__icon{background:color-mix(in oklch,var(--ax-err) 18%,transparent);color:var(--ax-err)}
|
|
113
|
+
|
|
114
|
+
#notice{margin:0 0 14px;font-size:12.5px;color:var(--ax-text-2)}
|
|
115
|
+
#notice:not(:empty){padding:9px 13px;border-radius:var(--ax-radius-sm);background:var(--ax-surface-2);
|
|
116
|
+
border:var(--ax-border-w) solid var(--ax-border)}
|
|
117
|
+
|
|
118
|
+
/* Cost of delay \u2014 replaces the old minutes estimate */
|
|
119
|
+
.bf-cost{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;
|
|
120
|
+
color:var(--ax-text-2)}
|
|
121
|
+
.bf-cost--rise{color:var(--ax-err)}
|
|
122
|
+
.bf-cost--rise.is-over{padding:2px 9px;border-radius:var(--ax-radius-pill);
|
|
123
|
+
background:color-mix(in oklch,var(--ax-err) 9%,var(--ax-surface));
|
|
124
|
+
border:1px solid color-mix(in oklch,var(--ax-err) 32%,var(--ax-border))}
|
|
125
|
+
.bf-act.is-snoozed{opacity:0.62}
|
|
126
|
+
.bf-why{font-size:12px;color:var(--ax-text-2);font-weight:400;margin-left:2px}
|
|
127
|
+
.ax-sec-label h3 .bf-why{margin-left:8px}
|
|
128
|
+
/* The hint wraps under the heading on a narrow column instead of running
|
|
129
|
+
beneath the button that used to sit on top of it. */
|
|
130
|
+
.bf .ax-sec-label{flex-wrap:wrap;gap:8px 12px;align-items:baseline}
|
|
131
|
+
.bf .ax-sec-label h3{flex-wrap:wrap;row-gap:2px;min-width:0}
|
|
132
|
+
.bf .ax-sec-label h3 .bf-why{flex:1 1 260px;min-width:0;white-space:normal}
|
|
133
|
+
#clear-actions{flex:none;margin-left:auto}
|
|
134
|
+
|
|
135
|
+
/* Handled \u2014 a count, not a list: it shows the backlog moving, nothing to decide */
|
|
136
|
+
.bf-done{display:flex;align-items:center;gap:10px;margin-top:14px;padding:11px 15px;
|
|
137
|
+
border-radius:var(--ax-radius-lg);border:var(--ax-border-w) solid var(--ax-border);
|
|
138
|
+
background:var(--ax-surface-2);font-size:12.5px;color:var(--ax-text-2)}
|
|
139
|
+
.bf-done b{font-family:var(--ax-mono);font-size:15px;color:var(--ax-text);font-weight:600}
|
|
140
|
+
.bf-done svg{color:var(--ax-ok);flex:none}
|
|
141
|
+
.bf-done span{margin-left:auto}
|
|
142
|
+
|
|
143
|
+
/* Principals */
|
|
144
|
+
.bf-pr{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:14px}
|
|
145
|
+
.bf-pr__c{min-width:0}
|
|
146
|
+
.bf-pr__n,.bf-pr__k,.bf-pr__o{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
147
|
+
.bf-pr__c{display:flex;flex-direction:column;gap:4px;text-align:left;font:inherit;cursor:pointer;
|
|
148
|
+
background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
149
|
+
border-radius:var(--ax-radius-lg);box-shadow:var(--ax-shadow);padding:11px 14px;color:var(--ax-text)}
|
|
150
|
+
.bf-pr__c:hover{background:var(--ax-surface-2)}
|
|
151
|
+
.bf-pr__c.is-on{border-color:var(--ax-accent);box-shadow:var(--ax-shadow-accent)}
|
|
152
|
+
.bf-pr__c--client{border-left:4px solid var(--ax-accent)}
|
|
153
|
+
.bf-pr__n{font-size:13.5px;font-weight:600;letter-spacing:-0.005em}
|
|
154
|
+
.bf-pr__k{font-size:10.5px;color:var(--ax-text-2);font-family:var(--ax-mono)}
|
|
155
|
+
.bf-pr__s{display:flex;align-items:baseline;gap:8px;font-size:11.5px;color:var(--ax-text-2);margin-top:3px}
|
|
156
|
+
.bf-pr__s b{font-family:var(--ax-mono);font-size:17px;font-weight:600;color:var(--ax-text-2)}
|
|
157
|
+
.bf-pr__s b.bf-pr__you{color:var(--ax-err)}
|
|
158
|
+
.bf-pr__s i{font-style:normal}
|
|
159
|
+
.bf-pr__o{font-size:10.5px;color:var(--ax-text-2)}
|
|
160
|
+
|
|
161
|
+
/* Triage columns */
|
|
162
|
+
.bf-grid{display:grid;grid-template-columns:minmax(0,2fr) minmax(300px,1fr);gap:22px;
|
|
163
|
+
align-items:flex-start;margin-bottom:24px}
|
|
164
|
+
.bf-col{display:flex;flex-direction:column;gap:10px;min-width:0}
|
|
165
|
+
.bf .ax-sec-label h3{display:flex;align-items:center;gap:8px}
|
|
166
|
+
.ax-sec-label__n{font-family:var(--ax-mono);font-size:11px;padding:1px 7px;border-radius:var(--ax-radius);
|
|
167
|
+
background:var(--ax-surface-3);color:var(--ax-text-2);letter-spacing:0}
|
|
168
|
+
.ax-sec-label__n:empty{display:none}
|
|
169
|
+
|
|
170
|
+
/* --- Identity: who, and where ------------------------------------------
|
|
171
|
+
Every card leads with the agent avatar and a row of place tags, so the
|
|
172
|
+
question "who did this, and where" is answered before any prose. */
|
|
173
|
+
.bf-id{display:flex;align-items:center;gap:11px;min-width:0}
|
|
174
|
+
.bf-id .ax-avatar{width:32px;height:32px;font-size:12px;text-transform:uppercase}
|
|
175
|
+
.bf-who{flex:1;min-width:0}
|
|
176
|
+
.bf-who__n{font-size:13.5px;font-weight:600;letter-spacing:-0.005em;display:flex;align-items:center;
|
|
177
|
+
gap:7px;flex-wrap:wrap}
|
|
178
|
+
.bf-where{display:flex;align-items:center;gap:5px;flex-wrap:wrap;margin-top:3px}
|
|
179
|
+
.bf-tag{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-family:var(--ax-mono);
|
|
180
|
+
color:var(--ax-muted);background:var(--ax-surface-2);border:1px solid var(--ax-border);
|
|
181
|
+
border-radius:var(--ax-radius-pill);padding:1px 8px;line-height:16px;max-width:100%;
|
|
182
|
+
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
183
|
+
button.bf-tag{cursor:pointer;font-weight:600}
|
|
184
|
+
button.bf-tag:hover{border-color:var(--ax-accent);color:var(--ax-accent)}
|
|
185
|
+
button.bf-tag.is-on{background:color-mix(in oklch,var(--ax-accent) 14%,transparent);
|
|
186
|
+
border-color:color-mix(in oklch,var(--ax-accent) 35%,transparent);color:var(--ax-accent)}
|
|
187
|
+
.bf-tag svg{flex-shrink:0}
|
|
188
|
+
.bf-time{font-size:10.5px;color:var(--ax-muted);font-family:var(--ax-mono);white-space:nowrap;
|
|
189
|
+
align-self:flex-start;padding-top:2px}
|
|
190
|
+
|
|
191
|
+
/* --- Quick links: always visible, never buried in a disclosure --------- */
|
|
192
|
+
.bf-links{display:flex;gap:6px;flex-wrap:wrap}
|
|
193
|
+
.bf-lnk{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;
|
|
194
|
+
padding:4px 10px;border-radius:var(--ax-radius-sm);border:var(--ax-border-w) solid var(--ax-border);
|
|
195
|
+
background:var(--ax-surface-2);color:var(--ax-text-2);text-decoration:none;max-width:320px;
|
|
196
|
+
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
197
|
+
.bf-lnk:hover{border-color:var(--ax-accent);color:var(--ax-accent);text-decoration:none}
|
|
198
|
+
.bf-lnk svg{flex-shrink:0;opacity:0.75}
|
|
199
|
+
.bf-lnk--go{color:var(--ax-accent);border-color:color-mix(in oklch,var(--ax-accent) 32%,var(--ax-border));
|
|
200
|
+
background:color-mix(in oklch,var(--ax-accent) 8%,transparent)}
|
|
201
|
+
|
|
202
|
+
/* Action card */
|
|
203
|
+
.bf-act{background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
204
|
+
border-radius:var(--ax-radius-lg);padding:14px 16px;box-shadow:var(--ax-shadow);
|
|
205
|
+
display:flex;flex-direction:column;gap:10px}
|
|
206
|
+
.bf-act--now{border-color:color-mix(in oklch,var(--ax-warn) 34%,var(--ax-border))}
|
|
207
|
+
.bf-act__cost{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--ax-text-2);
|
|
208
|
+
font-family:var(--ax-mono)}
|
|
209
|
+
.bf-act__cost svg{color:var(--ax-muted)}
|
|
210
|
+
/* One job, re-derived by N session reviews. Marking it done clears all N. */
|
|
211
|
+
.bf-dupe{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;
|
|
212
|
+
padding:2px 9px;border-radius:var(--ax-radius-pill);color:var(--ax-red);
|
|
213
|
+
background:color-mix(in oklch,var(--ax-err) 8%,var(--ax-surface));
|
|
214
|
+
border:1px solid color-mix(in oklch,var(--ax-err) 30%,var(--ax-border))}
|
|
215
|
+
.bf-eff{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--ax-muted)}
|
|
216
|
+
.bf-eff i{width:4px;height:10px;border-radius:1px;background:var(--ax-border-2);display:block}
|
|
217
|
+
.bf-eff--low i:nth-child(1),.bf-eff--medium i:nth-child(-n+2),.bf-eff--high i{background:var(--ax-text-2)}
|
|
218
|
+
.bf-act__text{font-size:var(--ax-fs);line-height:1.55;color:var(--ax-text);overflow-wrap:anywhere;margin:0}
|
|
219
|
+
.bf-act__foot{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
220
|
+
.bf-why{margin-top:2px}
|
|
221
|
+
.bf-why summary{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--ax-muted);
|
|
222
|
+
cursor:pointer;list-style:none;font-weight:600}
|
|
223
|
+
.bf-why summary::-webkit-details-marker{display:none}
|
|
224
|
+
.bf-why[open] summary svg{transform:rotate(180deg)}
|
|
225
|
+
.bf-ev{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--ax-text-2);
|
|
226
|
+
border-left:2px solid var(--ax-border-2);padding-left:12px;overflow-wrap:anywhere}
|
|
227
|
+
|
|
228
|
+
/* Deferred band */
|
|
229
|
+
.bf-defer{background:var(--ax-surface-2);border:var(--ax-border-w) solid var(--ax-border);
|
|
230
|
+
border-radius:var(--ax-radius-lg);padding:12px 16px;display:flex;align-items:center;gap:10px;
|
|
231
|
+
flex-wrap:wrap;cursor:pointer}
|
|
232
|
+
.bf-defer:hover{border-color:var(--ax-border-2)}
|
|
233
|
+
.bf-defer__t{font-size:var(--ax-fs-sm);font-weight:600;color:var(--ax-text-2)}
|
|
234
|
+
.bf-defer__n{margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
235
|
+
.bf-defer svg{color:var(--ax-muted);transition:transform 140ms ease}
|
|
236
|
+
#later{margin-top:10px}
|
|
237
|
+
#more-actions{align-self:flex-start;margin-top:10px}
|
|
238
|
+
|
|
239
|
+
/* In motion */
|
|
240
|
+
.bf-run{background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
241
|
+
border-radius:var(--ax-radius-sm);padding:11px 13px;display:flex;flex-direction:column;gap:8px}
|
|
242
|
+
.bf-run__dot{width:7px;height:7px;border-radius:50%;background:var(--ax-accent);flex-shrink:0;
|
|
243
|
+
box-shadow:0 0 0 3px color-mix(in oklch,var(--ax-accent) 18%,transparent)}
|
|
244
|
+
.bf-run__msg{font-size:12.5px;line-height:1.5;color:var(--ax-text-2);margin:0;overflow:hidden;
|
|
245
|
+
display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
|
|
246
|
+
|
|
247
|
+
/* Briefings toolbar + filters */
|
|
248
|
+
.bf-toolbar{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}
|
|
249
|
+
.bf-search{position:relative;flex:0 1 300px}
|
|
250
|
+
.bf-search svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--ax-muted);
|
|
251
|
+
pointer-events:none}
|
|
252
|
+
.bf-search input{width:100%;background:var(--ax-surface);color:var(--ax-text);
|
|
253
|
+
border:var(--ax-border-w) solid var(--ax-border-2);border-radius:var(--ax-radius);
|
|
254
|
+
padding:8px 14px 8px 34px;font:inherit;font-size:var(--ax-fs-sm)}
|
|
255
|
+
.bf-filters{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
|
|
256
|
+
.bf-filter{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;
|
|
257
|
+
padding:5px 11px;border-radius:var(--ax-radius-pill);border:var(--ax-border-w) solid var(--ax-border);
|
|
258
|
+
background:var(--ax-surface);color:var(--ax-text-2);cursor:pointer;font-family:inherit}
|
|
259
|
+
.bf-filter:hover{border-color:var(--ax-border-2);color:var(--ax-text)}
|
|
260
|
+
.bf-filter.is-on{background:color-mix(in oklch,var(--ax-accent) 14%,var(--ax-surface));
|
|
261
|
+
border-color:color-mix(in oklch,var(--ax-accent) 40%,var(--ax-border));color:var(--ax-accent)}
|
|
262
|
+
.bf-filter__n{font-family:var(--ax-mono);font-size:10px;opacity:0.8}
|
|
263
|
+
.bf-filter--clear{color:var(--ax-muted);border-style:dashed}
|
|
264
|
+
|
|
265
|
+
/* Briefing card */
|
|
266
|
+
.bf-brief{background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
267
|
+
border-radius:var(--ax-radius-lg);padding:14px 16px;box-shadow:var(--ax-shadow);
|
|
268
|
+
display:flex;flex-direction:column;gap:10px}
|
|
269
|
+
.bf-brief--failed{border-color:color-mix(in oklch,var(--ax-err) 30%,var(--ax-border))}
|
|
270
|
+
.bf-brief__top{display:flex;align-items:flex-start;gap:10px}
|
|
271
|
+
.bf-brief__sum{font-size:13px;line-height:1.6;color:var(--ax-text);margin:0;overflow-wrap:anywhere}
|
|
272
|
+
.bf-brief__fail{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
|
|
273
|
+
.bf-brief__fail .bf-brief__sum{flex:1;min-width:220px;color:var(--ax-text-2)}
|
|
274
|
+
|
|
275
|
+
/* Finding chips */
|
|
276
|
+
.bf-finds{display:flex;gap:6px;flex-wrap:wrap}
|
|
277
|
+
.bf-find{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:3px 9px;
|
|
278
|
+
border-radius:var(--ax-radius-pill);border:var(--ax-border-w) solid var(--ax-border);
|
|
279
|
+
background:var(--ax-surface-2);color:var(--ax-muted)}
|
|
280
|
+
.bf-find--warn{color:var(--ax-warn);background:color-mix(in oklch,var(--ax-warn) 12%,transparent);
|
|
281
|
+
border-color:color-mix(in oklch,var(--ax-warn) 32%,transparent)}
|
|
282
|
+
.bf-find--info{color:var(--ax-info);background:color-mix(in oklch,var(--ax-info) 12%,transparent);
|
|
283
|
+
border-color:color-mix(in oklch,var(--ax-info) 32%,transparent)}
|
|
284
|
+
.bf-find--zero{display:none}
|
|
285
|
+
.bf-brief details>summary{cursor:pointer;font-size:11.5px;color:var(--ax-muted);font-weight:600;
|
|
286
|
+
list-style:none;display:inline-flex;align-items:center;gap:5px}
|
|
287
|
+
.bf-brief details>summary::-webkit-details-marker{display:none}
|
|
288
|
+
.bf-brief details[open]>summary svg{transform:rotate(180deg)}
|
|
289
|
+
.bf-detail{border-top:1px dashed var(--ax-border);margin-top:10px;padding-top:12px;
|
|
290
|
+
display:flex;flex-direction:column;gap:13px}
|
|
291
|
+
.bf-fgroup h4{margin:0 0 7px;font-size:10.5px;font-family:var(--ax-mono);text-transform:uppercase;
|
|
292
|
+
letter-spacing:0.06em;color:var(--ax-muted);font-weight:600;display:flex;align-items:center;gap:6px}
|
|
293
|
+
.bf-fgroup--warn h4{color:var(--ax-warn)}
|
|
294
|
+
.bf-fgroup--info h4{color:var(--ax-info)}
|
|
295
|
+
.bf-item{display:flex;flex-direction:column;gap:4px;padding-bottom:9px}
|
|
296
|
+
.bf-item>p{font-size:12.5px;line-height:1.55;color:var(--ax-text);margin:0;overflow-wrap:anywhere}
|
|
297
|
+
|
|
298
|
+
/* Inline trace panel \u2014 a readable summary in place, not a JSON tab */
|
|
299
|
+
.bf-trace{border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-sm);
|
|
300
|
+
background:var(--ax-surface-2);padding:8px 12px}
|
|
301
|
+
.bf-trace>summary{cursor:pointer;font-size:11.5px;color:var(--ax-text-2);font-weight:600;
|
|
302
|
+
list-style:none;display:inline-flex;align-items:center;gap:6px}
|
|
303
|
+
.bf-trace>summary::-webkit-details-marker{display:none}
|
|
304
|
+
.bf-trace>summary:hover{color:var(--ax-accent)}
|
|
305
|
+
.bf-trace[open]>summary{margin-bottom:10px}
|
|
306
|
+
.bf-trace__body{font-size:12px;display:flex;flex-direction:column;gap:10px;align-items:flex-start}
|
|
307
|
+
.bf-kv{display:grid;grid-template-columns:auto 1fr;gap:5px 14px;margin:0;width:100%}
|
|
308
|
+
.bf-kv dt{font-family:var(--ax-mono);font-size:10.5px;text-transform:uppercase;letter-spacing:0.06em;
|
|
309
|
+
color:var(--ax-muted);align-self:center}
|
|
310
|
+
.bf-kv dd{margin:0;font-size:12.5px;color:var(--ax-text);overflow-wrap:anywhere}
|
|
311
|
+
|
|
312
|
+
.bf-tool{display:inline-flex;align-items:center;gap:4px;font-family:var(--ax-mono);font-size:11px;
|
|
313
|
+
background:var(--ax-surface-3);border-radius:var(--ax-radius-sm);padding:1px 7px;margin-right:4px}
|
|
314
|
+
|
|
315
|
+
/* Connect a CLI session */
|
|
316
|
+
.bf-connect{margin-top:24px}
|
|
317
|
+
.bf-connect__head{display:flex;align-items:center;gap:11px;margin-bottom:14px}
|
|
318
|
+
.bf-connect h2{margin:0;font-size:16px;font-weight:600;letter-spacing:-0.01em}
|
|
319
|
+
.bf-connect__note{margin-left:auto;font-size:10.5px;color:var(--ax-muted);font-family:var(--ax-mono)}
|
|
320
|
+
.bf-discover{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;margin-bottom:14px}
|
|
321
|
+
.bf-discover .ax-field{min-width:220px;flex:0 1 300px}
|
|
322
|
+
.bf-cli{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:10px}
|
|
323
|
+
.bf-cli:not(:empty){margin-bottom:14px}
|
|
324
|
+
.bf-cli-card{background:var(--ax-surface-2);border:var(--ax-border-w) solid var(--ax-border);
|
|
325
|
+
border-radius:var(--ax-radius-sm);padding:12px 13px;display:flex;flex-direction:column;gap:9px}
|
|
326
|
+
.bf-cli-card__top{display:flex;align-items:center;gap:10px;min-width:0}
|
|
327
|
+
.bf-cli-card__n{font-size:13px;font-weight:600}
|
|
328
|
+
.bf-cli-card__m{font-size:10.5px;color:var(--ax-muted);font-family:var(--ax-mono);margin-top:2px;
|
|
329
|
+
overflow-wrap:anywhere}
|
|
330
|
+
.bf-cli-card .ax-btn{justify-content:center}
|
|
331
|
+
.bf-manual>summary{cursor:pointer;font-size:12px;color:var(--ax-muted);font-weight:600;list-style:none;
|
|
332
|
+
display:inline-flex;align-items:center;gap:6px}
|
|
333
|
+
.bf-manual>summary::-webkit-details-marker{display:none}
|
|
334
|
+
.bf-manual[open]>summary svg{transform:rotate(180deg)}
|
|
335
|
+
.bf-forms{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:14px}
|
|
336
|
+
.bf-form{display:flex;flex-direction:column;gap:12px}
|
|
337
|
+
.bf-form .ax-sec-label{margin:0}
|
|
338
|
+
.bf-form__row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
|
|
339
|
+
.bf-form .ax-btn{align-self:flex-start}
|
|
340
|
+
|
|
341
|
+
/* Empty + loading */
|
|
342
|
+
.bf-empty{text-align:center;padding:30px 22px;background:var(--ax-surface);
|
|
343
|
+
border:var(--ax-border-w) dashed var(--ax-border-2);border-radius:var(--ax-radius-lg);
|
|
344
|
+
color:var(--ax-muted);display:flex;flex-direction:column;align-items:center;gap:7px}
|
|
345
|
+
.bf-empty svg{color:var(--ax-border-2)}
|
|
346
|
+
.bf-empty h4{margin:0;color:var(--ax-text);font-size:14px;font-weight:600}
|
|
347
|
+
.bf-empty p{font-size:12.5px;line-height:1.55;max-width:380px;margin:0}
|
|
348
|
+
.bf-skel{background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
349
|
+
border-radius:var(--ax-radius-lg);padding:14px 16px;display:flex;flex-direction:column;gap:10px}
|
|
350
|
+
.bf-bar{display:block;height:10px;border-radius:var(--ax-radius-pill);background:var(--ax-surface-3);
|
|
351
|
+
animation:bf-pulse 1.4s ease-in-out infinite}
|
|
352
|
+
@keyframes bf-pulse{0%,100%{opacity:1}50%{opacity:0.45}}
|
|
353
|
+
@media (prefers-reduced-motion:reduce){.bf-bar{animation:none}}
|
|
354
|
+
|
|
355
|
+
@media(max-width:980px){
|
|
356
|
+
.bf-grid{grid-template-columns:1fr}
|
|
357
|
+
.bf-forms{grid-template-columns:1fr}
|
|
358
|
+
.bf-strip{grid-template-columns:1fr 1fr}
|
|
359
|
+
}
|
|
360
|
+
@media(max-width:600px){
|
|
361
|
+
.bf{padding:16px 14px 36px}
|
|
362
|
+
.bf-head{flex-direction:column;gap:14px;align-items:stretch}
|
|
363
|
+
.bf-sync{justify-content:space-between}
|
|
364
|
+
}`,un=String.raw`
|
|
365
|
+
(function(){
|
|
366
|
+
const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
367
|
+
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
368
|
+
let nodes=[], actions=[], busy=false, expandedActions=false;
|
|
369
|
+
let filter={kind:'all',agent:null,node:null};
|
|
370
|
+
async function api(op,node,body){const r=await fetch('/api/monitor/'+op+'?node='+encodeURIComponent(node),{method:body?'POST':'GET',headers:{'Content-Type':'application/json'},...(body?{body:JSON.stringify(body)}:{})});const data=await r.json();if(!r.ok)throw Error(data.error||'Request failed');return data;}
|
|
371
|
+
function message(s){$('notice').textContent=s;}
|
|
372
|
+
let clientFilter='';
|
|
373
|
+
const PAGE=25;
|
|
374
|
+
let shown={you:PAGE,agents:PAGE};
|
|
375
|
+
|
|
376
|
+
/* --- Who and where ------------------------------------------------------
|
|
377
|
+
session_id is "<agent>:<channel>:<target>" for trace-sourced reviews, e.g.
|
|
378
|
+
"umbrella-coding:gitlab:umbrella-lab/umbrella-v1:issue:94". Native CLI session
|
|
379
|
+
ids carry no place, so the tags simply fall away. */
|
|
380
|
+
const CHANNEL_ICON={gitlab:'branch',github:'branch',telegram:'send',whatsapp:'msg',discord:'msg',slack:'hash',api:'code',cron:'clock',mesh:'route'};
|
|
381
|
+
function place(sessionId){
|
|
382
|
+
const parts=String(sessionId||'').split(':');
|
|
383
|
+
if(parts.length<3)return null;
|
|
384
|
+
const channel=parts[1];
|
|
385
|
+
let target=parts.slice(2).join(':')
|
|
386
|
+
.replace(/:issue:/,' #').replace(/:mr:/,' !').replace(/:pr:/,' #').replace(/:/g,' · ');
|
|
387
|
+
return {channel:channel,target:target};
|
|
388
|
+
}
|
|
389
|
+
function initials(name){const w=String(name||'?').split(/[-_\s.]+/).filter(Boolean);return ((w[0]||'?')[0]+(w[1]?w[1][0]:(w[0]||'?')[1]||'')).slice(0,2);}
|
|
390
|
+
const AV=['blue','teal','amber','coral'];
|
|
391
|
+
function avatarClass(name){let h=0;for(const c of String(name||'')) h=(h*31+c.charCodeAt(0))>>>0;return AV[h%AV.length];}
|
|
392
|
+
function tag(icon,text,attrs){return '<'+(attrs?'button type="button" '+attrs:'span')+' class="bf-tag">'+(icon?ic(icon,11):'')+esc(text)+'</'+(attrs?'button':'span')+'>';}
|
|
393
|
+
function idBlock(agent,nodeName,nodeUrl,sessionId,model,when,whenExact){
|
|
394
|
+
const p=place(sessionId);
|
|
395
|
+
const on=(k,v)=>filter[k]===v?' is-on':'';
|
|
396
|
+
return '<div class="bf-id"><div class="ax-avatar ax-avatar--'+avatarClass(agent)+'">'+esc(initials(agent))+'</div>'
|
|
397
|
+
+'<div class="bf-who"><div class="bf-who__n">'
|
|
398
|
+
+'<button type="button" class="bf-tag'+on('agent',agent)+'" data-fagent="'+esc(agent)+'" style="font-size:13.5px;font-family:inherit;background:none;border:none;padding:0;color:inherit">'+esc(agent)+'</button>'
|
|
399
|
+
+(model?'<span class="ax-badge ax-badge--mono">'+esc(model)+'</span>':'')+'</div>'
|
|
400
|
+
+'<div class="bf-where">'
|
|
401
|
+
+'<button type="button" class="bf-tag'+on('node',nodeName)+'" data-fnode="'+esc(nodeName)+'" title="Filter by node">'+ic('server',11)+esc(nodeName)+'</button>'
|
|
402
|
+
+(p?tag(CHANNEL_ICON[p.channel]||'hash',p.channel):'')
|
|
403
|
+
+(p&&p.target?tag('',p.target):'')
|
|
404
|
+
+'</div></div>'
|
|
405
|
+
+(when?'<span class="bf-time" title="'+esc(whenExact||'')+'">'+esc(when)+'</span>':'')+'</div>';
|
|
406
|
+
}
|
|
407
|
+
function lnk(href,icon,text,go){return '<a class="bf-lnk'+(go?' bf-lnk--go':'')+'" href="'+esc(href)+'" target="_blank" rel="noopener noreferrer" title="'+esc(text)+'">'+ic(icon,12)+esc(text)+'</a>';}
|
|
408
|
+
/* Human-friendly time. Relative on the face, exact on hover. */
|
|
409
|
+
function relTime(ms){
|
|
410
|
+
if(!ms)return '';
|
|
411
|
+
const d=Math.round((Date.now()-ms)/1000);
|
|
412
|
+
if(d<45)return 'just now';
|
|
413
|
+
if(d<90)return 'a minute ago';
|
|
414
|
+
const m=Math.round(d/60);
|
|
415
|
+
if(m<60)return m+' min ago';
|
|
416
|
+
const h=Math.round(m/60);
|
|
417
|
+
if(h<24)return h===1?'an hour ago':h+' hours ago';
|
|
418
|
+
const day=Math.round(h/24);
|
|
419
|
+
if(day===1)return 'yesterday';
|
|
420
|
+
if(day<7)return day+' days ago';
|
|
421
|
+
return new Date(ms).toLocaleDateString([], {month:'short',day:'numeric'});
|
|
422
|
+
}
|
|
423
|
+
function absTime(ms){return ms?new Date(ms).toLocaleString():'';}
|
|
424
|
+
function fmtDur(ms){
|
|
425
|
+
if(ms==null)return '';
|
|
426
|
+
if(ms<1000)return ms+' ms';
|
|
427
|
+
const s=Math.round(ms/1000);
|
|
428
|
+
if(s<60)return s+' s';
|
|
429
|
+
const m=Math.floor(s/60),r=s%60;
|
|
430
|
+
if(m<60)return m+'m'+(r?' '+r+'s':'');
|
|
431
|
+
const h=Math.floor(m/60);
|
|
432
|
+
return h+'h'+(m%60?' '+(m%60)+'m':'');
|
|
433
|
+
}
|
|
434
|
+
function tracePanel(nodeUrl,taskId){
|
|
435
|
+
return '<details class="bf-trace" data-node="'+esc(nodeUrl)+'" data-task="'+esc(taskId)+'">'
|
|
436
|
+
+'<summary>'+ic('trace',12)+'Trace</summary>'
|
|
437
|
+
+'<div class="bf-trace__body"><span class="ax-muted">Loading…</span></div></details>';
|
|
438
|
+
}
|
|
439
|
+
function renderTrace(el,d){
|
|
440
|
+
if(!d||d.found===false)return '<span class="ax-muted">No trace stored for this run.</span>';
|
|
441
|
+
const kv=[];
|
|
442
|
+
const add=(k,v)=>{if(v!==''&&v!=null)kv.push('<dt>'+k+'</dt><dd>'+v+'</dd>');};
|
|
443
|
+
add('Status','<span class="ax-pill ax-pill--'+(d.status==='ok'?'ok':d.status==='error'?'err':'off')+'"><span class="ax-pill__dot"></span>'+esc(d.status||'unknown')+'</span>');
|
|
444
|
+
add('Agent',esc(d.agent||''));
|
|
445
|
+
if(d.channel)add('Where',esc(d.channel)+(d.chatId?' · '+esc(String(d.chatId).replace(/:issue:/,' #').replace(/:mr:/,' !')):''));
|
|
446
|
+
add('Started',d.startedAt?'<span title="'+esc(absTime(d.startedAt))+'">'+esc(relTime(d.startedAt))+'</span>':'');
|
|
447
|
+
add('Took',d.durationMs!=null?esc(fmtDur(d.durationMs)):'');
|
|
448
|
+
if(d.model)add('Model',esc(d.model));
|
|
449
|
+
if(d.cause)add('Cause',esc(d.cause));
|
|
450
|
+
// Counters are derived from steps; pruned traces report zeros that mean
|
|
451
|
+
// "unknown", not "none". Say so rather than showing a wall of 0s.
|
|
452
|
+
if(d.stepsPruned)kv.push('<dt>Detail</dt><dd class="ax-muted">Step detail was pruned — tool, token and I/O counters are no longer available.</dd>');
|
|
453
|
+
else{
|
|
454
|
+
add('Steps',String((d.steps||[]).length));
|
|
455
|
+
if(d.tools&&d.tools.length)add('Tools',d.tools.map(t=>{
|
|
456
|
+
const name=esc(typeof t==='string'?t:(t.tool||t.name||'tool'));
|
|
457
|
+
const used=(t&&t.used>1)?' ×'+t.used:'';
|
|
458
|
+
const failed=(t&&t.failed)?' <span class="ax-pill ax-pill--err" style="padding:0 5px">'+t.failed+' failed</span>':'';
|
|
459
|
+
return '<span class="bf-tool">'+name+used+failed+'</span>';
|
|
460
|
+
}).join(' '));
|
|
461
|
+
if(d.outputTokens)add('Output tokens',String(d.outputTokens));
|
|
462
|
+
const io=[d.reads?d.reads+' read':'',d.writes?d.writes+' write':'',d.sends?d.sends+' send':''].filter(Boolean).join(' · ');
|
|
463
|
+
if(io)add('I/O',io);
|
|
464
|
+
}
|
|
465
|
+
return '<dl class="bf-kv">'+kv.join('')+'</dl>'
|
|
466
|
+
+'<a class="bf-lnk" href="/api/mesh/run?node='+encodeURIComponent(el.dataset.node)+'&task='+encodeURIComponent(el.dataset.task)+'" target="_blank" rel="noopener noreferrer">'+ic('ext',12)+'Raw JSON</a>';
|
|
467
|
+
}
|
|
468
|
+
/* The human task page, not the raw JSON endpoint. archived=1 reads the stored
|
|
469
|
+
record; a live task streams instead. Falls back to the JSON API only when no
|
|
470
|
+
agent can be resolved, because /tasks refuses a request without one. */
|
|
471
|
+
function taskHref(nodeUrl,taskId,agentId,archived){
|
|
472
|
+
return agentId
|
|
473
|
+
?'/tasks/'+encodeURIComponent(taskId)+'?agent='+encodeURIComponent(agentId)+'&node='+encodeURIComponent(nodeUrl)+(archived?'&archived=1':'')
|
|
474
|
+
:'/api/mesh/run?node='+encodeURIComponent(nodeUrl)+'&task='+encodeURIComponent(taskId);
|
|
475
|
+
}
|
|
476
|
+
/* A related task usually has its own review (or is still running); either one
|
|
477
|
+
tells us which agent owns it. */
|
|
478
|
+
function ownerOf(n,taskId){
|
|
479
|
+
const run=(n.data.running||[]).find(t=>t.taskId===taskId);
|
|
480
|
+
if(run)return run.agentId;
|
|
481
|
+
const rev=(n.data.reviews||[]).find(r=>r.id===taskId);
|
|
482
|
+
return rev?rev.agent:'';
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* --- Loading skeleton --------------------------------------------------- */
|
|
486
|
+
function skeleton(){
|
|
487
|
+
const bar=w=>'<i class="bf-bar" style="width:'+w+'"></i>';
|
|
488
|
+
const card='<div class="bf-skel">'+bar('40%')+bar('100%')+bar('64%')+'</div>';
|
|
489
|
+
$('strip').innerHTML=('<div class="ax-stat-inline"><div class="ax-stat-inline__icon"></div>'
|
|
490
|
+
+'<div class="bf-skel" style="flex:1;gap:6px">'+bar('46px')+bar('76px')+'</div></div>').repeat(4);
|
|
491
|
+
$('you').innerHTML=card+card;$('agents').innerHTML=card;$('reviews').innerHTML=card;$('running').innerHTML=card;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/* --- Coverage ----------------------------------------------------------- */
|
|
495
|
+
function si(icon,value,label,kind){return '<div class="ax-stat-inline'+(kind?' bf-si--'+kind:'')+'"><div class="ax-stat-inline__icon">'+ic(icon,14)+'</div><div style="min-width:0"><div class="ax-stat-inline__v">'+esc(value)+'</div><div class="ax-stat-inline__l">'+esc(label)+'</div></div></div>';}
|
|
496
|
+
function renderCoverage(){
|
|
497
|
+
const ok=nodes.filter(n=>n.ok), failed=nodes.filter(n=>!n.ok);
|
|
498
|
+
const reviews=ok.reduce((a,n)=>a+(n.data.reviews||[]).length,0);
|
|
499
|
+
const queue=ok.flatMap(n=>n.data.counts||[]);
|
|
500
|
+
const waiting=queue.filter(c=>c.status==='pending'||c.status==='reviewing').reduce((a,c)=>a+c.count,0);
|
|
501
|
+
const failures=queue.filter(c=>c.status==='failed').reduce((a,c)=>a+c.count,0);
|
|
502
|
+
$('strip').innerHTML=si('server',ok.length+' / '+nodes.length,'Nodes reporting',failed.length?'warn':'')
|
|
503
|
+
+si('inbox',String(waiting),'Awaiting review')
|
|
504
|
+
+si('cross',String(failures),failures===1?'Review failed':'Reviews failed',failures?'err':'')
|
|
505
|
+
+si('file',String(reviews),'Recent briefings');
|
|
506
|
+
$('coverage').textContent=reviews+' recent reviews, '+waiting+' awaiting review'+(failures?', '+failures+' review failures':'')+', '+ok.length+' of '+nodes.length+' nodes reporting'+(failed.length?'. Unavailable: '+failed.map(n=>n.name+' ('+n.error+')').join(', '):'');
|
|
507
|
+
$('coverage-note').innerHTML=failed.length
|
|
508
|
+
?'<div class="ax-callout'+(ok.length?'':' bf-callout--err')+'"><span class="ax-callout__icon">!</span><div><b>'
|
|
509
|
+
+esc(failed.map(n=>n.name).join(', '))+'</b> not reporting — '
|
|
510
|
+
+failed.map(n=>'<code>'+esc(n.error)+'</code>').join(' ')+'</div></div>':'';
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/* --- Actions ------------------------------------------------------------ */
|
|
514
|
+
function card(a,i,clocks){
|
|
515
|
+
/* The cost of waiting, not an estimate of the work. A client with a stated
|
|
516
|
+
clock accrues against it; everything else is flat and says so. */
|
|
517
|
+
const d=decayOf(a,clocks||{});
|
|
518
|
+
const age=a.updatedAt?relTime(a.updatedAt).replace(' ago',''):'';
|
|
519
|
+
const cost=d.rising
|
|
520
|
+
?'<span class="bf-cost bf-cost--rise'+(d.overdue?' is-over':'')+'">'+ic('pulse',12)+esc(age)+(d.overdue?' · past the clock':' · rising')+'</span>'
|
|
521
|
+
:'<span class="bf-cost">'+ic('clock',12)+esc(age)+' · flat</span>';
|
|
522
|
+
const pill=a.needsHuman
|
|
523
|
+
?'<span class="ax-pill ax-pill--warn"><span class="ax-pill__dot"></span>Needs you</span>'
|
|
524
|
+
:'<span class="ax-pill ax-pill--info"><span class="ax-pill__dot"></span>Agent</span>';
|
|
525
|
+
const done='<button class="ax-btn ax-btn--sm ax-btn--primary" data-action="done" data-index="'+i+'">'+ic('check',13)+' Done</button>';
|
|
526
|
+
const foot=a.snoozed
|
|
527
|
+
?done+'<button class="ax-btn ax-btn--sm ax-btn--ghost" data-action="open" data-index="'+i+'">Bring back</button>'
|
|
528
|
+
:done+'<button class="ax-btn ax-btn--sm ax-btn--ghost" data-action="later" data-index="'+i+'">Snooze</button>';
|
|
529
|
+
const src=a.sources[0];
|
|
530
|
+
const links=(src && !String(src.reviewId).startsWith('external:'))?tracePanel(src.node,src.reviewId):'';
|
|
531
|
+
return '<article class="bf-act'+(d.overdue&&a.needsHuman?' bf-act--now':'')+(a.snoozed?' is-snoozed':'')+'">'
|
|
532
|
+
+idBlock(a.agent,a.nodes.join(' / '),src?src.node:'',a.sessionId,'',relTime(a.updatedAt),absTime(a.updatedAt))
|
|
533
|
+
+'<p class="bf-act__text">'+esc(a.text)+'</p>'
|
|
534
|
+
+'<div class="bf-links">'+pill
|
|
535
|
+
+(a.sources.length>1?'<span class="bf-dupe" title="Re-derived by this many session reviews">'+ic('loop',12)+'seen '+a.sources.length+'×</span>':'')
|
|
536
|
+
+cost
|
|
537
|
+
+(a.snoozed?'<span class="ax-pill ax-pill--off">snoozed</span>':'')+'</div>'
|
|
538
|
+
+links
|
|
539
|
+
+'<div class="bf-act__foot">'+foot+'</div>'
|
|
540
|
+
+(a.evidence?'<details class="bf-why"><summary>'+ic('chev',12)+'Evidence</summary><p class="bf-ev">'+esc(a.evidence)+'</p></details>':'')
|
|
541
|
+
+'</article>';
|
|
542
|
+
}
|
|
543
|
+
/* --- Principals ---------------------------------------------------------- */
|
|
544
|
+
/* Who the work is for. Clients are derived from business.projects and
|
|
545
|
+
business.contactMap, so this fills itself in; it is only empty when no
|
|
546
|
+
project or contact has ever been configured. Clicking one filters the
|
|
547
|
+
action list — the fastest way to answer "what does this client need". */
|
|
548
|
+
const KIND_LABEL={client:'client',own:'own product',internal:'internal'};
|
|
549
|
+
function renderPrincipals(){
|
|
550
|
+
const policy={};
|
|
551
|
+
for(const n of nodes.filter(n=>n.ok))for(const c of n.data.clients||[])policy[c.id]=c;
|
|
552
|
+
const by={};
|
|
553
|
+
for(const a of actions){
|
|
554
|
+
const id=a.clientId||'unmapped';
|
|
555
|
+
const g=by[id]||(by[id]={id:id,you:0,agents:0,oldest:0});
|
|
556
|
+
if(a.needsHuman)g.you++;else g.agents++;
|
|
557
|
+
if(a.updatedAt&&(!g.oldest||a.updatedAt<g.oldest))g.oldest=a.updatedAt;
|
|
558
|
+
}
|
|
559
|
+
const rows=Object.values(by).sort((x,y)=>y.you-x.you||y.agents-x.agents);
|
|
560
|
+
if(!rows.length){$('principals').innerHTML='';return;}
|
|
561
|
+
$('principals').innerHTML='<section class="bf-pr" aria-label="Who the work is for">'
|
|
562
|
+
+rows.map(g=>{
|
|
563
|
+
const p=policy[g.id]||{name:g.id,kind:'internal',declared:false};
|
|
564
|
+
const on=clientFilter===g.id;
|
|
565
|
+
return '<button class="bf-pr__c'+(on?' is-on':'')+(p.kind==='client'?' bf-pr__c--client':'')+'"'
|
|
566
|
+
+' data-client="'+esc(g.id)+'" aria-pressed="'+(on?'true':'false')+'">'
|
|
567
|
+
+'<span class="bf-pr__n">'+esc(p.name||g.id)+'</span>'
|
|
568
|
+
+'<span class="bf-pr__k">'+esc(KIND_LABEL[p.kind]||'internal')+(p.respondWithinMinutes?' · '+p.respondWithinMinutes+'m clock':'')+'</span>'
|
|
569
|
+
+'<span class="bf-pr__s"><b class="'+(g.you?'bf-pr__you':'')+'">'+g.you+'</b> on you'
|
|
570
|
+
+'<i>'+g.agents+' on agents</i></span>'
|
|
571
|
+
+(g.oldest?'<span class="bf-pr__o">oldest '+relTime(g.oldest)+'</span>':'')
|
|
572
|
+
+'</button>';
|
|
573
|
+
}).join('')+'</section>';
|
|
574
|
+
$('principals').querySelectorAll('[data-client]').forEach(b=>b.onclick=()=>{
|
|
575
|
+
clientFilter=clientFilter===b.dataset.client?'':b.dataset.client;shown={you:PAGE,agents:PAGE};renderPrincipals();renderActions();});
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function renderActions(){
|
|
579
|
+
const merged=new Map();
|
|
580
|
+
for(const n of nodes.filter(n=>n.ok))for(const entry of n.data.actions?.items||[]){
|
|
581
|
+
const a=entry.action,saved=entry.state;const key=entry.key||JSON.stringify([n.url,entry.sessionId,a.text.toLowerCase().replace(/\s+/g,' ').trim()]);const source={node:n.url,reviewId:entry.reviewId,index:entry.actionIndex};
|
|
582
|
+
if(merged.has(key)){const m=merged.get(key);m.sources.push(source);if(!m.nodes.includes(n.name))m.nodes.push(n.name);if(saved==='open')m.snoozed=false;if(entry.updatedAt>m.updatedAt){m.updatedAt=entry.updatedAt;m.text=a.text;m.evidence=a.evidence;}}
|
|
583
|
+
else merged.set(key,{...a,snoozed:saved==='later',sources:[source],nodes:[n.name],agent:entry.agent,sessionId:entry.sessionId,updatedAt:entry.updatedAt,clientId:entry.clientId});
|
|
584
|
+
}
|
|
585
|
+
const unloaded=nodes.filter(n=>n.ok).reduce((s,n)=>s+Math.max(0,(n.data.actions?.total||0)-(n.data.actions?.items.length||0)),0);
|
|
586
|
+
$('more-actions').hidden=!unloaded;$('more-actions').textContent='Load '+unloaded+' older';
|
|
587
|
+
actions=[...merged.values()];
|
|
588
|
+
/* Each client's stated respondWithin is what makes a wait cost something.
|
|
589
|
+
Work for a client with no clock is flat and can never outrank someone who
|
|
590
|
+
is actually waiting. */
|
|
591
|
+
const clocks={};
|
|
592
|
+
for(const n of nodes.filter(n=>n.ok))for(const c of n.data.clients||[])clocks[c.id]=c.respondWithinMinutes;
|
|
593
|
+
const list=clientFilter?actions.filter(a=>(a.clientId||'unmapped')===clientFilter):actions;
|
|
594
|
+
const order=rankByDecay(list,clocks)
|
|
595
|
+
.sort((x,y)=>(list[x].snoozed?1:0)-(list[y].snoozed?1:0));
|
|
596
|
+
const you=[],agents=[];
|
|
597
|
+
for(const i of order)(list[i].needsHuman?you:agents).push(list[i]);
|
|
598
|
+
const page=(items,key)=>items.slice(0,shown[key]).map(a=>card(a,actions.indexOf(a),clocks)).join('')
|
|
599
|
+
+(items.length>shown[key]
|
|
600
|
+
?'<button class="ax-btn ax-btn--sm bf-more" data-more="'+key+'">Show '+Math.min(PAGE,items.length-shown[key])+' more of '+(items.length-shown[key])+'</button>'
|
|
601
|
+
:'');
|
|
602
|
+
$('you').innerHTML=page(you,'you')||'<div class="bf-empty">'+ic('check',22)+'<h4>Nothing needs you</h4><p>Everything open can be finished without your authority.</p></div>';
|
|
603
|
+
$('you-count').textContent=you.length?String(you.length):'';
|
|
604
|
+
$('agents').innerHTML=page(agents,'agents')||'<div class="bf-empty">'+ic('check',22)+'<h4>Nothing queued for agents</h4><p>No open action was marked as needing no human.</p></div>';
|
|
605
|
+
$('agents-count').innerHTML=String(agents.length)+(unloaded?'<span class="ax-pill ax-pill--off">'+unloaded+' not loaded</span>':'');
|
|
606
|
+
const done=nodes.filter(n=>n.ok).reduce((t,n)=>t+(n.data.doneCount||0),0);
|
|
607
|
+
$('handled').innerHTML=done?'<div class="bf-done">'+ic('check',17)+'<b>'+done+'</b> handled<span>cleared by you or by an agent — no decision in here</span></div>':'';
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/* --- Session briefings + filters ---------------------------------------- */
|
|
611
|
+
const GROUPS=[['warnings','Warnings','alert','warn'],['decisions','Decisions on your behalf','gavel','info'],['friction','Avoidable round trips','loop',''],['context','Context maintenance','broom','']];
|
|
612
|
+
function chip(n,icon,kind,one,many){return '<span class="bf-find '+(n?'bf-find--'+kind:'bf-find--zero')+'">'+ic(icon,12)+(n?n+' '+(n===1?one:many):'no '+many)+'</span>';}
|
|
613
|
+
function rows(){return nodes.filter(n=>n.ok).flatMap(n=>(n.data.reviews||[]).map(r=>({n:n,r:r})));}
|
|
614
|
+
function passes(e,ignoreKind){
|
|
615
|
+
const r=e.r,v=r.result;
|
|
616
|
+
if(filter.agent&&r.agent!==filter.agent)return false;
|
|
617
|
+
if(filter.node&&e.n.name!==filter.node)return false;
|
|
618
|
+
if(!ignoreKind){
|
|
619
|
+
if(filter.kind==='failed'&&r.status!=='failed')return false;
|
|
620
|
+
if(filter.kind==='warn'&&!(v&&v.warnings.length))return false;
|
|
621
|
+
if(filter.kind==='needs'&&!(v&&v.actions.some(a=>a.needsHuman)))return false;
|
|
622
|
+
}
|
|
623
|
+
const q=$('search').value.toLowerCase();
|
|
624
|
+
return !q||JSON.stringify(r).toLowerCase().includes(q);
|
|
625
|
+
}
|
|
626
|
+
function renderFilters(){
|
|
627
|
+
const base=rows().filter(e=>passes(e,true));
|
|
628
|
+
const counts={all:base.length,
|
|
629
|
+
needs:base.filter(e=>e.r.result&&e.r.result.actions.some(a=>a.needsHuman)).length,
|
|
630
|
+
warn:base.filter(e=>e.r.result&&e.r.result.warnings.length).length,
|
|
631
|
+
failed:base.filter(e=>e.r.status==='failed').length};
|
|
632
|
+
const defs=[['all','file','All'],['needs','alert','Needs you'],['warn','alert','Warnings'],['failed','cross','Failed']];
|
|
633
|
+
let html=defs.map(([k,icon,label])=>'<button type="button" class="bf-filter'+(filter.kind===k?' is-on':'')+'" data-fkind="'+k+'">'+ic(icon,12)+esc(label)+'<span class="bf-filter__n">'+counts[k]+'</span></button>').join('');
|
|
634
|
+
if(filter.agent)html+='<button type="button" class="bf-filter is-on" data-fagent="'+esc(filter.agent)+'">'+ic('hash',12)+esc(filter.agent)+ic('x',11)+'</button>';
|
|
635
|
+
if(filter.node)html+='<button type="button" class="bf-filter is-on" data-fnode="'+esc(filter.node)+'">'+ic('server',12)+esc(filter.node)+ic('x',11)+'</button>';
|
|
636
|
+
if(filter.kind!=='all'||filter.agent||filter.node)html+='<button type="button" class="bf-filter bf-filter--clear" data-fclear="1">'+ic('x',12)+'Clear</button>';
|
|
637
|
+
$('filters').innerHTML=html;
|
|
638
|
+
}
|
|
639
|
+
function renderReviews(){
|
|
640
|
+
renderFilters();
|
|
641
|
+
const entries=rows().filter(e=>passes(e,false)).sort((a,b)=>b.r.updated_at-a.r.updated_at).map(e=>{
|
|
642
|
+
const n=e.n,r=e.r,v=r.result;
|
|
643
|
+
const head=idBlock(r.agent,n.name,n.url,r.session_id,r.model,relTime(r.updated_at),absTime(r.updated_at));
|
|
644
|
+
if(r.status==='failed')return '<article class="bf-brief bf-brief--failed">'+head
|
|
645
|
+
+'<div class="bf-brief__fail"><span class="ax-badge ax-badge--err">Review failed</span>'
|
|
646
|
+
+'<p class="bf-brief__sum">'+esc(r.error||'Review failed')+'</p>'
|
|
647
|
+
+'<button class="ax-btn ax-btn--sm" data-retry="'+esc(r.id)+'" data-node="'+esc(n.url)+'">Retry</button></div></article>';
|
|
648
|
+
let html='<article class="bf-brief">'+head+'<p class="bf-brief__sum">'+esc(v?v.summary:'Review '+r.status+'…')+'</p>';
|
|
649
|
+
// Quick access: every link the review produced, plus the trace it came from.
|
|
650
|
+
let links=v?v.links.filter(l=>/^https?:\/\//i.test(l.url)||/^\/(?!\/)/.test(l.url))
|
|
651
|
+
.map(l=>lnk(l.url.startsWith('/')?n.url+l.url:l.url,'ext',l.label)).join(''):'';
|
|
652
|
+
if(v)links+=v.relatedTaskIds.map(id=>lnk(taskHref(n.url,id,ownerOf(n,id),true),'route','Related '+String(id).slice(-6))).join('');
|
|
653
|
+
|
|
654
|
+
if(links)html+='<div class="bf-links">'+links+'</div>';
|
|
655
|
+
if(r.source==='trace')html+=tracePanel(n.url,r.id);
|
|
656
|
+
if(v){
|
|
657
|
+
html+='<div class="bf-finds">'+chip(v.warnings.length,'alert','warn','warning','warnings')
|
|
658
|
+
+chip(v.decisions.length,'gavel','info','decision','decisions')
|
|
659
|
+
+chip(v.friction.length,'loop','warn','round trip','round trips')
|
|
660
|
+
+chip(v.context.length,'broom','info','context note','context notes')+'</div>';
|
|
661
|
+
const detail=GROUPS.filter(g=>v[g[0]].length).map(g=>'<div class="bf-fgroup'+(g[3]?' bf-fgroup--'+g[3]:'')+'"><h4>'+ic(g[2],13)+esc(g[1])+'</h4>'
|
|
662
|
+
+v[g[0]].map(x=>'<div class="bf-item"><p>'+esc(x.text)+'</p><p class="bf-ev">'+esc(x.evidence)+'</p></div>').join('')+'</div>').join('');
|
|
663
|
+
if(detail)html+='<details><summary>'+ic('chev',12)+'Findings & evidence</summary><div class="bf-detail">'+detail+'</div></details>';
|
|
664
|
+
}
|
|
665
|
+
return html+'</article>';});
|
|
666
|
+
$('brief-count').textContent=entries.length?String(entries.length):'';
|
|
667
|
+
$('reviews').innerHTML=(entries.slice(0,4).join('')+(entries.length>4?'<details><summary class="bf-defer">'+ic('chevr',14)+'<span class="bf-defer__t">'+(entries.length-4)+' earlier</span></summary><div class="bf-col" style="margin-top:10px">'+entries.slice(4).join('')+'</div></details>':''))
|
|
668
|
+
||'<div class="bf-empty">'+ic('file',22)+'<h4>Nothing here</h4><p>'+(filter.kind!=='all'||filter.agent||filter.node||$('search').value?'No briefing matches the current filter.':'Runs that finish from now on are reviewed and land here.')+'</p></div>';
|
|
669
|
+
}
|
|
670
|
+
function registrations(){const n=nodes.find(n=>n.url===$('node').value);$('registered').innerHTML=(n?.data?.registrations||[]).map(r=>'<option value="'+esc(r.id)+'">'+esc(r.label)+' · '+esc(r.runtime)+'</option>').join('');}
|
|
671
|
+
function renderRunning(){
|
|
672
|
+
const list=nodes.filter(n=>n.ok).flatMap(n=>(n.data.running||[]).map(t=>'<div class="bf-run">'
|
|
673
|
+
+idBlock(t.agentId,n.name,n.url,t.sessionId||'','','')
|
|
674
|
+
+'<p class="bf-run__msg">'+esc(t.messagePreview||'Running task')+'</p>'
|
|
675
|
+
+tracePanel(n.url,t.taskId)+'</div>'));
|
|
676
|
+
$('run-count').textContent=list.length?String(list.length):'';
|
|
677
|
+
$('running').innerHTML=list.join('')||'<div class="bf-empty">'+ic('pulse',22)+'<h4>Nothing running</h4><p>No active AgentX runs reported.</p></div>';
|
|
678
|
+
}
|
|
679
|
+
async function refresh(){
|
|
680
|
+
if(busy)return;busy=true;$('refresh').disabled=true;$('refresh').setAttribute('aria-busy','true');
|
|
681
|
+
try{
|
|
682
|
+
const r=await fetch('/api/monitor');if(!r.ok)throw Error('Briefing unavailable: HTTP '+r.status);
|
|
683
|
+
const data=await r.json();nodes=data.nodes;expandedActions=false;
|
|
684
|
+
renderCoverage();
|
|
685
|
+
const selected=$('node').value;
|
|
686
|
+
$('node').innerHTML=nodes.map(n=>'<option value="'+esc(n.url)+'">'+esc(n.name)+(n.ok?'':' — unavailable')+'</option>').join('');
|
|
687
|
+
if(nodes.some(n=>n.url===selected))$('node').value=selected;
|
|
688
|
+
registrations();renderActions();renderPrincipals();renderReviews();renderRunning();
|
|
689
|
+
$('synced').textContent='Synced '+new Date().toLocaleTimeString();
|
|
690
|
+
message('');
|
|
691
|
+
}catch(e){$('synced').textContent='Refresh failed';message(e.message);}
|
|
692
|
+
finally{busy=false;$('refresh').disabled=false;$('refresh').removeAttribute('aria-busy');}
|
|
693
|
+
}
|
|
694
|
+
$('more-actions').onclick=async()=>{try{for(const n of nodes.filter(n=>n.ok&&n.data.actions.items.length<n.data.actions.total)){const r=await fetch('/api/monitor/actions?node='+encodeURIComponent(n.url)+'&offset='+n.data.actions.items.length);if(!r.ok)throw Error('Could not load older actions');const d=await r.json();n.data.actions.items.push(...d.items);n.data.actions.total=d.total;}expandedActions=true;renderActions();message('Older actions loaded. Auto-refresh paused until you press Refresh.');}catch(e){message(e.message);}};
|
|
695
|
+
document.addEventListener('click',e=>{const b=e.target.closest('[data-more]');if(!b)return;
|
|
696
|
+
shown[b.dataset.more]+=PAGE;renderActions();});
|
|
697
|
+
/* What this page is showing, for the ask-an-agent drawer. Kept small and
|
|
698
|
+
factual: the filter in force, what the buckets hold, and the handful of
|
|
699
|
+
items actually on screen — not the whole backlog. */
|
|
700
|
+
window.axPageContext=()=>{
|
|
701
|
+
const vis=actions.filter(a=>!clientFilter||(a.clientId||'unmapped')===clientFilter);
|
|
702
|
+
return {
|
|
703
|
+
page:'monitor',
|
|
704
|
+
client:clientFilter||'all',
|
|
705
|
+
onlyYou:vis.filter(a=>a.needsHuman).length,
|
|
706
|
+
forAgents:vis.filter(a=>!a.needsHuman).length,
|
|
707
|
+
topItems:vis.filter(a=>a.needsHuman).slice(0,8).map(a=>({
|
|
708
|
+
text:String(a.text||'').slice(0,140),client:a.clientId||'unmapped',agent:a.agent,
|
|
709
|
+
where:a.sessionId,seen:a.sources?a.sources.length:1})),
|
|
710
|
+
};};
|
|
711
|
+
|
|
712
|
+
$('clear-actions').onclick=async()=>{
|
|
713
|
+
const open=actions.length;
|
|
714
|
+
if(!open){message('Nothing open to clear.');return;}
|
|
715
|
+
if(!confirm('Mark all '+open+' open actions done on every node? The reviews and their findings stay; only the open flags move.'))return;
|
|
716
|
+
try{let n=0;
|
|
717
|
+
for(const nd of nodes.filter(n=>n.ok)){const r=await api('clear',nd.url,{});n+=r.cleared||0;}
|
|
718
|
+
message('Cleared '+n+'. New actions keep arriving as sessions end.');await refresh();
|
|
719
|
+
}catch(e){message(e.message);}};
|
|
720
|
+
$('search').oninput=renderReviews;$('refresh').onclick=refresh;$('node').onchange=registrations;
|
|
721
|
+
document.addEventListener('click',async e=>{
|
|
722
|
+
const tr=e.target.closest('.bf-trace>summary');
|
|
723
|
+
if(tr){
|
|
724
|
+
const el=tr.parentElement;
|
|
725
|
+
if(!el.dataset.loaded){
|
|
726
|
+
el.dataset.loaded='1';
|
|
727
|
+
const body=el.querySelector('.bf-trace__body');
|
|
728
|
+
fetch('/api/mesh/run?node='+encodeURIComponent(el.dataset.node)+'&task='+encodeURIComponent(el.dataset.task))
|
|
729
|
+
.then(r=>r.json()).then(d=>{body.innerHTML=renderTrace(el,d);})
|
|
730
|
+
.catch(err=>{body.innerHTML='<span class="ax-muted">Could not load the trace: '+esc(err.message)+'</span>';el.dataset.loaded='';});
|
|
731
|
+
}
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
const t=e.target.closest('[data-fkind],[data-fagent],[data-fnode],[data-fclear]');
|
|
735
|
+
if(t){
|
|
736
|
+
if(t.dataset.fclear)filter={kind:'all',agent:null,node:null};
|
|
737
|
+
else if(t.dataset.fkind)filter.kind=t.dataset.fkind;
|
|
738
|
+
else if(t.dataset.fagent)filter.agent=filter.agent===t.dataset.fagent?null:t.dataset.fagent;
|
|
739
|
+
else if(t.dataset.fnode)filter.node=filter.node===t.dataset.fnode?null:t.dataset.fnode;
|
|
740
|
+
renderReviews();
|
|
741
|
+
if(t.dataset.fagent||t.dataset.fnode)$('reviews').scrollIntoView({behavior:'smooth',block:'start'});
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
const b=e.target.closest('button');if(!b)return;
|
|
745
|
+
try{
|
|
746
|
+
if(b.dataset.action){b.disabled=true;const a=actions[Number(b.dataset.index)];await Promise.all(a.sources.map(s=>api('action',s.node,{reviewId:s.reviewId,index:s.index,state:b.dataset.action})));await refresh();}
|
|
747
|
+
if(b.dataset.retry){b.disabled=true;await api('retry',b.dataset.node,{id:b.dataset.retry});await refresh();}
|
|
748
|
+
}catch(err){message(err.message);}finally{b.disabled=false;}});
|
|
749
|
+
function cliCard(glyph,name,meta,badge,cta,onclick){
|
|
750
|
+
const el=document.createElement('div');el.className='bf-cli-card';
|
|
751
|
+
el.innerHTML='<div class="bf-cli-card__top"><div class="ax-avatar ax-avatar--'+avatarClass(name)+'" style="width:30px;height:30px;font-size:11px">'+esc(glyph)+'</div>'
|
|
752
|
+
+'<div style="min-width:0"><div class="bf-cli-card__n">'+esc(name)+'</div><div class="bf-cli-card__m">'+esc(meta)+'</div></div></div>'
|
|
753
|
+
+badge+'<button class="ax-btn ax-btn--sm ax-btn--primary">'+esc(cta)+'</button>';
|
|
754
|
+
el.querySelector('button').onclick=onclick;
|
|
755
|
+
return el;
|
|
756
|
+
}
|
|
757
|
+
const NATIVE='<span class="ax-pill ax-pill--ok"><span class="ax-pill__dot"></span>Reports turns natively</span>';
|
|
758
|
+
const PROC='<span class="ax-pill ax-pill--off">Process only</span>';
|
|
759
|
+
$('discover').onclick=async()=>{
|
|
760
|
+
try{
|
|
761
|
+
const node=$('node').value;const data=await api('discover',node);$('discovered').replaceChildren();
|
|
762
|
+
for(const s of data.sessions||[])
|
|
763
|
+
$('discovered').append(cliCard('cl','claude',s.label||s.id,NATIVE,'Monitor session',async()=>{
|
|
764
|
+
try{await api('register',node,{...s,label:s.label||s.id});message('Registered. Attach stop hooks will review future turns.');await refresh();}catch(e){message(e.message);}}));
|
|
765
|
+
for(const p of data.processes)
|
|
766
|
+
$('discovered').append(cliCard(p.runtime.slice(0,2),p.runtime,'PID '+p.pid+' · '+p.started,PROC,'Register',async()=>{
|
|
767
|
+
try{await api('register',node,{id:p.runtime+':'+p.pid+':'+p.started,label:p.runtime+' '+p.pid,runtime:p.runtime,pid:p.pid,started:p.started});message('Registered. Connect a stop hook or submit a transcript.');await refresh();}catch(e){message(e.message);}}));
|
|
768
|
+
if(!data.processes.length&&!(data.sessions||[]).length)
|
|
769
|
+
$('discovered').innerHTML='<div class="bf-empty" style="grid-column:1/-1">'+ic('plug',22)+'<h4>No CLI found</h4><p>Only processes owned by the daemon account are visible. Register others manually.</p></div>';
|
|
770
|
+
}catch(e){message(e.message);}};
|
|
771
|
+
for(const op of ['register','ended'])$(op).onsubmit=async e=>{e.preventDefault();try{const body=Object.fromEntries(new FormData(e.target));await api(op,$('node').value,body);message(op==='ended'?'Run queued for review.':'Session registered.');if(op==='ended')e.target.reset();await refresh();}catch(err){message(err.message);}};
|
|
772
|
+
skeleton();refresh();
|
|
773
|
+
setInterval(()=>{
|
|
774
|
+
if(document.hidden||expandedActions)return;
|
|
775
|
+
if(document.querySelector('form :focus'))return;
|
|
776
|
+
if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
|
|
777
|
+
refresh();
|
|
778
|
+
},15000);
|
|
779
|
+
})();`;function Ge(t,e=20*6e4,a=6){let n=[...t].sort((i,c)=>i.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let i of n){let c=i.startedAt+Math.max(i.durationMs||0,0),u=r[r.length-1];u&&i.startedAt-u.to<=e?(u.to=Math.max(u.to,c),u.runs++):r.push({from:i.startedAt,to:c,runs:1})}for(;r.length>a;){let i=0,c=1/0;for(let u=1;u<r.length;u++){let m=r[u].from-r[u-1].to;m<c&&(c=m,i=u)}r[i-1].to=r[i].to,r[i-1].runs+=r[i].runs,r.splice(i,1)}let o=r.reduce((i,c)=>i+c.runs,0)||1,s=r.map(i=>({from:i.from,to:Math.max(i.to,i.from+1),weight:i.runs/o,runs:i.runs})),l=r.slice(1).map((i,c)=>i.from-r[c].to);return{bands:s,gaps:l}}function Xe(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function qt(t,e=[],a){let{bands:n,gaps:r}=Ge(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let i of e){let c=o.get(i.runId);c?c.push(i):o.set(i.runId,[i])}let s=new Map;for(let i of t){let c=n.findIndex(M=>i.startedAt>=M.from&&i.startedAt<=M.to);if(c===-1)continue;let u=n[c],m=u.to-u.from||1,x=(i.startedAt-u.from)/m*100,b=Math.min(Math.max((i.durationMs||0)/m*100,1.2),100-x),_=s.get(i.laneKey)??{key:i.laneKey,label:i.laneLabel,sub:i.laneSub,tracks:1,runs:[]};_.runs.push({...i,band:c,track:0,left:x,width:b,marks:o.get(i.id)??[]}),s.set(i.laneKey,_)}let l=[...s.values()];for(let i of l)i.tracks=Math.max(...n.map((c,u)=>Xe(i.runs.filter(m=>m.band===u))),1);return l.sort((i,c)=>c.runs.length-i.runs.length||i.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:l,from:n[0].from,to:n[n.length-1].to}}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},Ke=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",mn=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["node","Node",se.mesh]];function Ut(t={}){return C({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
|
|
780
|
+
|
|
781
|
+
<div class="ac-head">
|
|
782
|
+
<div>
|
|
783
|
+
<div class="ac-kicker">Operations</div>
|
|
784
|
+
<h1>What ran, where, and what it decided</h1>
|
|
785
|
+
<p class="ac-sub">Every run on the mesh, from task traces. The axis breaks over silence — quiet stretches are labelled, not drawn.</p>
|
|
786
|
+
</div>
|
|
787
|
+
<div class="ac-tools">
|
|
788
|
+
<div class="ac-seg" id="hours" role="radiogroup" aria-label="Window">
|
|
789
|
+
${[["6","6h"],["24","24h"],["72","3d"],["168","7d"]].map(([e,a],n)=>`<button type="button" role="radio" data-value="${e}" aria-checked="${n===1}"${n===1?' class="is-on"':""}>${a}</button>`).join("")}
|
|
790
|
+
</div>
|
|
791
|
+
<button class="ax-btn ax-btn--sm" id="refresh">${Ke(se.refresh,13)} Refresh</button>
|
|
792
|
+
</div>
|
|
793
|
+
</div>
|
|
794
|
+
|
|
795
|
+
<div class="ac-bar">
|
|
796
|
+
<span class="ac-lbl">Lanes by</span>
|
|
797
|
+
<div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
|
|
798
|
+
${mn.map(([e,a,n],r)=>`<button type="button" role="radio" data-value="${e}" aria-checked="${r===0}"${r===0?' class="is-on"':""}>${Ke(n,13)}${a}</button>`).join("")}
|
|
799
|
+
</div>
|
|
800
|
+
<div class="ac-key">
|
|
801
|
+
<span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
|
|
802
|
+
<span class="ac-k"><i class="ac-d ac-d--warning"></i>warning</span>
|
|
803
|
+
<span class="ac-k"><i class="ac-d ac-d--recommendation"></i>friction</span>
|
|
804
|
+
<span class="ac-k"><i class="ac-d ac-d--later"></i>do later</span>
|
|
805
|
+
<span class="ac-k">${Ke(se.x,11)}canceled</span>
|
|
806
|
+
</div>
|
|
807
|
+
</div>
|
|
808
|
+
|
|
809
|
+
<p id="notice" role="status" aria-live="polite"></p>
|
|
810
|
+
<div id="tl" class="ac-tl"></div>
|
|
811
|
+
<div id="detail"></div>
|
|
812
|
+
|
|
813
|
+
</div>`,css:hn,scripts:`<script>${me({computeBands:Ge,packTracks:Xe,buildTimeline:qt})}const ICON = ${JSON.stringify(se)};${gn}</script>`})}var hn=`
|
|
814
|
+
.ac{max-width:1440px;margin:0 auto;padding:22px 24px 48px}
|
|
815
|
+
.ac :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
|
|
816
|
+
.ac-head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:14px}
|
|
817
|
+
.ac-kicker{font-family:var(--ax-mono);font-size:10px;letter-spacing:0.1em;text-transform:uppercase;
|
|
818
|
+
color:var(--ax-text-2);font-weight:600}
|
|
819
|
+
.ac h1{font-size:22px;font-weight:600;letter-spacing:-0.015em;margin:5px 0 0}
|
|
820
|
+
.ac-sub{font-size:13px;color:var(--ax-text-2);margin:5px 0 0;max-width:66ch;line-height:1.5}
|
|
821
|
+
.ac-tools{display:flex;align-items:center;gap:10px;flex:none;padding-top:6px}
|
|
822
|
+
.ac-bar{display:flex;align-items:center;gap:16px;flex-wrap:wrap;background:var(--ax-surface);
|
|
823
|
+
border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-lg);
|
|
824
|
+
padding:11px 16px;box-shadow:var(--ax-shadow);margin-bottom:14px}
|
|
825
|
+
.ac-lbl{font-family:var(--ax-mono);font-size:10px;letter-spacing:0.08em;text-transform:uppercase;
|
|
826
|
+
color:var(--ax-text-2);font-weight:600}
|
|
827
|
+
.ac-seg{display:flex;border:var(--ax-border-w) solid var(--ax-border-2);border-radius:var(--ax-radius);
|
|
828
|
+
overflow:hidden;background:var(--ax-bg)}
|
|
829
|
+
.ac-seg button{background:transparent;border:none;border-right:1px solid var(--ax-border);
|
|
830
|
+
color:var(--ax-text-2);font:inherit;font-size:12.5px;font-weight:600;padding:6px 13px;cursor:pointer;
|
|
831
|
+
white-space:nowrap;display:inline-flex;align-items:center;gap:6px}
|
|
832
|
+
.ac-seg button:last-child{border-right:none}
|
|
833
|
+
.ac-seg button:hover{color:var(--ax-text);background:var(--ax-surface-2)}
|
|
834
|
+
.ac-seg button.is-on{background:var(--ax-blue-t);color:var(--ax-blue-d)}
|
|
835
|
+
.ac-key{display:flex;align-items:center;gap:13px;margin-left:auto;flex-wrap:wrap}
|
|
836
|
+
.ac-k{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--ax-text-2)}
|
|
837
|
+
.ac-d{width:9px;height:9px;flex:none}
|
|
838
|
+
.ac-d--decision{background:var(--ax-blue-d);transform:rotate(45deg)}
|
|
839
|
+
.ac-d--warning{background:var(--ax-amber-ink);clip-path:polygon(50% 0,100% 100%,0 100%)}
|
|
840
|
+
.ac-d--recommendation{background:var(--ax-green-d);border-radius:50%}
|
|
841
|
+
.ac-d--later{border:2px solid var(--ax-text-2);border-radius:2px}
|
|
842
|
+
|
|
843
|
+
.ac-tl{background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
844
|
+
border-radius:var(--ax-radius-lg);box-shadow:var(--ax-shadow);overflow:hidden}
|
|
845
|
+
.ac-row{display:flex;align-items:stretch;border-bottom:1px solid var(--ax-border);position:relative}
|
|
846
|
+
.ac-row:last-child{border-bottom:none}
|
|
847
|
+
.ac-row--hd{background:var(--ax-surface-2);border-bottom:var(--ax-border-w) solid var(--ax-border)}
|
|
848
|
+
.ac-gut{width:186px;flex:none;display:flex;align-items:center;gap:9px;padding:8px 12px;
|
|
849
|
+
border-right:var(--ax-border-w) solid var(--ax-border);min-width:0}
|
|
850
|
+
.ac-gut b{font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
|
|
851
|
+
.ac-gut i{font-style:normal;font-family:var(--ax-mono);font-size:10px;color:var(--ax-text-2);
|
|
852
|
+
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
|
|
853
|
+
.ac-bands{flex:1;display:flex;min-width:0}
|
|
854
|
+
.ac-band{position:relative;min-width:0}
|
|
855
|
+
.ac-band--hd{display:flex;align-items:center;justify-content:center;font-family:var(--ax-mono);
|
|
856
|
+
font-size:10px;color:var(--ax-text-2);font-weight:600;padding:7px 0}
|
|
857
|
+
.ac-gap{width:44px;flex:none;
|
|
858
|
+
background-image:repeating-linear-gradient(45deg,var(--ax-surface-2) 0 3px,transparent 3px 7px)}
|
|
859
|
+
.ac-gap--hd{display:flex;align-items:center;justify-content:center;background-image:none;
|
|
860
|
+
border-left:1px dashed var(--ax-border-2);border-right:1px dashed var(--ax-border-2);
|
|
861
|
+
font-family:var(--ax-mono);font-size:9px;color:var(--ax-text-2);font-weight:600}
|
|
862
|
+
.ac-run{position:absolute;height:20px;border-radius:5px;background:var(--ax-blue);
|
|
863
|
+
border:1px solid var(--ax-blue-d);cursor:pointer;padding:0}
|
|
864
|
+
.ac-run:hover{filter:brightness(1.08)}
|
|
865
|
+
.ac-run.is-sel{outline:2px solid var(--ax-text);outline-offset:1px}
|
|
866
|
+
.ac-run--failed{background:var(--ax-red);border-color:var(--ax-red-ink)}
|
|
867
|
+
.ac-run--canceled{background:transparent;border:1.5px dashed var(--ax-red-ink);height:14px;margin-top:3px}
|
|
868
|
+
.ac-run--running{background:var(--ax-green);border-color:var(--ax-green-d)}
|
|
869
|
+
.ac-mk{position:absolute;top:1px;width:9px;height:9px;transform:translateX(-50%);pointer-events:none}
|
|
870
|
+
.ac-empty{padding:40px;text-align:center;color:var(--ax-text-2);font-size:13px}
|
|
871
|
+
|
|
872
|
+
.ac-det{margin-top:14px;background:var(--ax-surface);border:var(--ax-border-w) solid var(--ax-border);
|
|
873
|
+
border-radius:var(--ax-radius-lg);box-shadow:var(--ax-shadow);padding:15px 17px}
|
|
874
|
+
.ac-det__h{display:flex;align-items:center;gap:9px;margin-bottom:11px;flex-wrap:wrap}
|
|
875
|
+
.ac-det__t{font-size:14px;font-weight:600}
|
|
876
|
+
.ac-kv{display:grid;grid-template-columns:80px minmax(0,1fr);gap:5px 12px;font-size:12.5px}
|
|
877
|
+
.ac-kv dt{font-family:var(--ax-mono);font-size:10px;text-transform:uppercase;letter-spacing:0.05em;
|
|
878
|
+
color:var(--ax-text-2);font-weight:600;padding-top:2px}
|
|
879
|
+
.ac-kv dd{margin:0;color:var(--ax-text);min-width:0;overflow-wrap:anywhere}
|
|
880
|
+
.ac-find{display:flex;gap:8px;align-items:flex-start;padding:7px 0;border-top:1px solid var(--ax-border);
|
|
881
|
+
font-size:12.5px;line-height:1.45}
|
|
882
|
+
.ac-chip{display:inline-flex;align-items:center;gap:5px;border-radius:var(--ax-radius-pill);padding:2px 9px;
|
|
883
|
+
font-size:11.5px;font-weight:600;border:1px solid var(--ax-border-2);background:var(--ax-surface-2);
|
|
884
|
+
color:var(--ax-text-2)}
|
|
885
|
+
#notice{margin:0 0 12px;font-size:12.5px;color:var(--ax-text-2)}
|
|
886
|
+
#notice:not(:empty){padding:9px 13px;border-radius:var(--ax-radius-sm);background:var(--ax-surface-2);
|
|
887
|
+
border:var(--ax-border-w) solid var(--ax-border)}
|
|
888
|
+
@media (max-width:900px){.ac-gut{width:120px}.ac-key{display:none}}
|
|
889
|
+
`,gn=String.raw`
|
|
890
|
+
const $=id=>document.getElementById(id);
|
|
891
|
+
const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
892
|
+
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
893
|
+
let runs=[],marks=[],persp='agent',hours='24',selected=null,busy=false;
|
|
894
|
+
|
|
895
|
+
function fmtDur(ms){if(!ms)return '0s';if(ms<1000)return ms+'ms';const s=Math.round(ms/1000);
|
|
896
|
+
if(s<60)return s+'s';const m=Math.floor(s/60);return m+'m '+(s%60)+'s';}
|
|
897
|
+
function fmtGap(ms){const m=Math.round(ms/60000);if(m<60)return m+'m';const h=Math.floor(m/60);
|
|
898
|
+
return h+'h'+(m%60?' '+(m%60)+'m':'');}
|
|
899
|
+
function clock(ms){return new Date(ms).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});}
|
|
900
|
+
|
|
901
|
+
/* The lane a run hangs from. Only this changes between perspectives — the
|
|
902
|
+
runs themselves are already loaded, so switching never refetches. */
|
|
903
|
+
function lane(r){
|
|
904
|
+
if(persp==='agent')return {key:r.agentId+'|'+(r.channel||''),label:r.agentId,sub:r.channel||''};
|
|
905
|
+
if(persp==='client')return {key:r.clientId||'unmapped',label:r.clientId||'unmapped',sub:''};
|
|
906
|
+
if(persp==='project')return {key:r.project||('('+(r.channel||'none')+')'),label:r.project||('no project'),sub:r.channel||''};
|
|
907
|
+
if(persp==='channel')return {key:r.channel||'none',label:r.channel||'none',sub:''};
|
|
908
|
+
return {key:r.node||'this node',label:r.node||'this node',sub:''};
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function render(){
|
|
912
|
+
if(!runs.length){$('tl').innerHTML='<div class="ac-empty">Nothing ran in this window.</div>';$('detail').innerHTML='';return;}
|
|
913
|
+
const t=buildTimeline(runs.map(r=>{const l=lane(r);
|
|
914
|
+
return {id:r.id,laneKey:l.key,laneLabel:l.label,laneSub:l.sub,startedAt:r.startedAt,
|
|
915
|
+
durationMs:r.durationMs||0,status:r.status,label:r.preview||''};}),marks);
|
|
916
|
+
const cells=(inner)=>t.bands.map((b,i)=>
|
|
917
|
+
(i?'<div class="ac-gap'+inner.gapCls+'">'+(inner.gap?fmtGap(t.gaps[i-1]):'')+'</div>':'')
|
|
918
|
+
+'<div class="ac-band'+inner.cls+'" style="flex:'+b.weight.toFixed(4)+'">'+inner.body(b,i)+'</div>').join('');
|
|
919
|
+
|
|
920
|
+
let html='<div class="ac-row ac-row--hd"><div class="ac-gut"><i>'+t.lanes.length+' lanes · '+runs.length+' runs</i></div>'
|
|
921
|
+
+'<div class="ac-bands">'+cells({cls:' ac-band--hd',gapCls:' ac-gap--hd',gap:true,
|
|
922
|
+
body:b=>clock(b.from)+' – '+clock(b.to)})+'</div></div>';
|
|
923
|
+
|
|
924
|
+
for(const ln of t.lanes){
|
|
925
|
+
const h=10+ln.tracks*24;
|
|
926
|
+
html+='<div class="ac-row" style="height:'+h+'px"><div class="ac-gut"><span style="min-width:0"><b>'+esc(ln.label)+'</b>'
|
|
927
|
+
+(ln.sub?'<i>'+esc(ln.sub)+'</i>':'')+'</span></div><div class="ac-bands">'
|
|
928
|
+
+cells({cls:'',gapCls:'',gap:false,body:(b,bi)=>ln.runs.filter(r=>r.band===bi).map(r=>{
|
|
929
|
+
const top=5+r.track*24;
|
|
930
|
+
const cls=r.status==='failed'?' ac-run--failed':r.status==='canceled'?' ac-run--canceled'
|
|
931
|
+
:(r.status==='running'||r.status==='in-flight')?' ac-run--running':'';
|
|
932
|
+
const mk=r.marks.map(m=>'<span class="ac-mk ac-d ac-d--'+m.kind+'" style="left:'+r.left.toFixed(3)+'%;top:'+(top-11)+'px"></span>').join('');
|
|
933
|
+
return mk+'<button class="ac-run'+cls+(selected===r.id?' is-sel':'')+'" data-run="'+esc(r.id)+'"'
|
|
934
|
+
+' style="left:'+r.left.toFixed(3)+'%;width:'+r.width.toFixed(3)+'%;top:'+top+'px"'
|
|
935
|
+
+' title="'+esc(r.laneLabel+' · '+clock(r.startedAt)+' · '+fmtDur(r.durationMs))+'"></button>';
|
|
936
|
+
}).join('')})
|
|
937
|
+
+'</div></div>';
|
|
938
|
+
}
|
|
939
|
+
$('tl').innerHTML=html;
|
|
940
|
+
$('tl').querySelectorAll('[data-run]').forEach(b=>b.onclick=()=>{selected=b.dataset.run;render();detail();});
|
|
941
|
+
detail();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
const KIND={decision:'Decision taken for you',warning:'Warning',recommendation:'Avoidable round trip',later:'For later'};
|
|
945
|
+
function detail(){
|
|
946
|
+
const r=runs.find(x=>x.id===selected);
|
|
947
|
+
if(!r){$('detail').innerHTML='';return;}
|
|
948
|
+
const found=marks.filter(m=>m.runId===r.id);
|
|
949
|
+
$('detail').innerHTML='<div class="ac-det"><div class="ac-det__h">'
|
|
950
|
+
+'<span class="ac-det__t">'+esc(r.preview||'(no prompt recorded)')+'</span>'
|
|
951
|
+
+'<span class="ac-chip">'+esc(r.status)+'</span></div>'
|
|
952
|
+
+'<dl class="ac-kv">'
|
|
953
|
+
+'<dt>When</dt><dd>'+clock(r.startedAt)+' · took '+fmtDur(r.durationMs||0)+'</dd>'
|
|
954
|
+
+'<dt>Who</dt><dd>'+esc(r.agentId)+(r.node?' on '+esc(r.node):'')+'</dd>'
|
|
955
|
+
+'<dt>Where</dt><dd>'+esc(r.channel||'—')+(r.chatId?' · '+esc(r.chatId):'')+'</dd>'
|
|
956
|
+
+'<dt>For</dt><dd>'+esc(r.clientId||'unmapped')+'</dd></dl>'
|
|
957
|
+
+(found.length?found.map(m=>'<div class="ac-find"><i class="ac-d ac-d--'+m.kind+'" style="margin-top:4px"></i>'
|
|
958
|
+
+'<span><b>'+esc(KIND[m.kind]||m.kind)+'.</b> '+esc(m.text)+'</span></div>').join('')
|
|
959
|
+
:'<div class="ac-find" style="color:var(--ax-text-2)">No review findings for this run.</div>')
|
|
960
|
+
+'</div>';
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
async function load(){
|
|
964
|
+
if(busy)return;busy=true;$('refresh').disabled=true;
|
|
965
|
+
try{
|
|
966
|
+
const r=await fetch('/api/monitor');if(!r.ok)throw Error('HTTP '+r.status);
|
|
967
|
+
const nodes=(await r.json()).nodes.filter(n=>n.ok);
|
|
968
|
+
runs=[];marks=[];
|
|
969
|
+
for(const n of nodes){
|
|
970
|
+
try{
|
|
971
|
+
const a=await fetch('/api/monitor/activity?node='+encodeURIComponent(n.url)+'&hours='+hours);
|
|
972
|
+
if(!a.ok)continue;
|
|
973
|
+
const d=await a.json();
|
|
974
|
+
for(const run of d.runs||[])runs.push({...run,node:d.node||n.name});
|
|
975
|
+
for(const m of d.marks||[])marks.push(m);
|
|
976
|
+
}catch{}
|
|
977
|
+
}
|
|
978
|
+
$('notice').textContent='';
|
|
979
|
+
render();
|
|
980
|
+
}catch(e){$('notice').textContent=e.message;}
|
|
981
|
+
finally{busy=false;$('refresh').disabled=false;}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function paint(id,v){for(const b of $(id).children){const on=b.dataset.value===v;
|
|
985
|
+
b.classList.toggle('is-on',on);b.setAttribute('aria-checked',String(on));}}
|
|
986
|
+
$('persp').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b)return;
|
|
987
|
+
persp=b.dataset.value;paint('persp',persp);selected=null;render();});
|
|
988
|
+
$('hours').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b)return;
|
|
989
|
+
hours=b.dataset.value;paint('hours',hours);load();});
|
|
990
|
+
$('refresh').onclick=load;
|
|
991
|
+
load();
|
|
992
|
+
`;import{createHash as fn}from"crypto";import{readFileSync as xn,statSync as vn}from"fs";import{resolve as bn,dirname as yn}from"path";import{fileURLToPath as wn}from"url";var Ft=new Map;function je(t){let e=Ft.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=yn(wn(import.meta.url)),r=bn(n,"web",t),o=vn(r),s=o.size<8e6?fn("sha1").update(xn(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Ft.set(t,a),a}function Wt(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return C({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:kn,scripts:`<script src="${je("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var kn=`
|
|
993
|
+
/* Preload the fonts the redesign's CSS references. Placed in the shell so
|
|
994
|
+
* they start fetching while the React bundle is still parsing. */
|
|
995
|
+
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
|
|
996
|
+
|
|
997
|
+
html, body { height: 100%; }
|
|
998
|
+
body { margin: 0; overflow: hidden; }
|
|
999
|
+
/* The editor takes over the whole viewport except the dashboard topbar. The
|
|
1000
|
+
* topbar still renders via the shell so the Workflows tab highlights and
|
|
1001
|
+
* global nav works. */
|
|
1002
|
+
.ax-topbar { position: relative; z-index: 50; }
|
|
1003
|
+
#wfe-root { width: 100%; height: calc(100vh - 48px); }
|
|
1004
|
+
/* Tiny fallback while the bundle loads \u2014 prevents an empty flash. */
|
|
1005
|
+
#wfe-root:empty::before {
|
|
1006
|
+
content: "Loading editor\u2026";
|
|
1007
|
+
display: block;
|
|
1008
|
+
padding: 40px 24px;
|
|
1009
|
+
color: #94a3b8;
|
|
1010
|
+
font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1011
|
+
text-align: center;
|
|
1012
|
+
}
|
|
1013
|
+
`;cn();import{createServer as xs}from"http";import{appendFileSync as vs,existsSync as on,mkdirSync as bs}from"fs";import{readFile as ys}from"fs/promises";import{fileURLToPath as ws}from"url";import{dirname as ks,resolve as ke}from"path";var Gt='/*! 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 Le,readFileSync as Kt,writeFileSync as Jt,rmSync as hi,mkdirSync as An,copyFileSync as Mn,readdirSync as In}from"fs";import{resolve as he}from"path";Ne();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 Xt(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=Ae({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.`})+Me([{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+En()+It,css:Tn,scripts:`${e}<script>${$t}
|
|
1014
|
+
${jt}
|
|
1015
|
+
${_n}
|
|
1016
|
+
${Cn}</script>`})}var _n=`
|
|
5
1017
|
(function(){
|
|
6
1018
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
7
1019
|
async function refresh() {
|
|
@@ -62,8 +1074,8 @@ ${Qa}</script>`})}var Ka=`
|
|
|
62
1074
|
refresh();
|
|
63
1075
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
64
1076
|
document.addEventListener('ax-config-saved', refresh);
|
|
65
|
-
})();`;function
|
|
66
|
-
`:"";return
|
|
1077
|
+
})();`;function En(){let t=St().business?`<button data-tab="business">Business</button>
|
|
1078
|
+
`:"";return Sn.replace("__BUSINESS_TABS__",t)}var Sn=`
|
|
67
1079
|
<div id="peer-banner" class="peer-banner">
|
|
68
1080
|
<span class="label">Managing</span>
|
|
69
1081
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -206,7 +1218,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
206
1218
|
<div id="global-msg" class="msg"></div>
|
|
207
1219
|
|
|
208
1220
|
<section id="tab-agents" class="tab active">
|
|
209
|
-
${N({icon:
|
|
1221
|
+
${N({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
1222
|
${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
1223
|
<div id="agent-list" class="ax-stack"></div>
|
|
212
1224
|
<div class="add-form">
|
|
@@ -229,7 +1241,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
229
1241
|
</section>
|
|
230
1242
|
|
|
231
1243
|
<section id="tab-channels" class="tab">
|
|
232
|
-
${N({icon:
|
|
1244
|
+
${N({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
1245
|
${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
1246
|
|
|
235
1247
|
<details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
|
|
@@ -259,10 +1271,10 @@ ${Qa}</script>`})}var Ka=`
|
|
|
259
1271
|
</div>
|
|
260
1272
|
</details>
|
|
261
1273
|
|
|
262
|
-
<div id="ch-chatapps-label">${
|
|
1274
|
+
<div id="ch-chatapps-label">${Ie({label:"Chat apps"})}</div>
|
|
263
1275
|
<div class="ax-connectors" id="ch-chatapps"></div>
|
|
264
1276
|
|
|
265
|
-
<div id="ch-devtools-label">${
|
|
1277
|
+
<div id="ch-devtools-label">${Ie({label:"Developer tools",rightHtml:'<span class="ax-pill">Send events from GitHub, GitLab, Sentry, etc.</span>'})}</div>
|
|
266
1278
|
<div class="ax-connectors" id="ch-devtools"></div>
|
|
267
1279
|
|
|
268
1280
|
<!-- Active-channel configuration panes. One shows at a time; clicking
|
|
@@ -280,7 +1292,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
280
1292
|
</section>
|
|
281
1293
|
|
|
282
1294
|
<section id="tab-crons" class="tab">
|
|
283
|
-
${N({icon:
|
|
1295
|
+
${N({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
1296
|
${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
1297
|
<div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
|
|
286
1298
|
|
|
@@ -378,13 +1390,13 @@ ${Qa}</script>`})}var Ka=`
|
|
|
378
1390
|
</section>
|
|
379
1391
|
|
|
380
1392
|
<section id="tab-webhooks" class="tab">
|
|
381
|
-
${N({icon:
|
|
1393
|
+
${N({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
1394
|
${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
1395
|
<div id="webhook-list" class="ax-stack"></div>
|
|
384
1396
|
<div class="add-form">
|
|
385
1397
|
<h3>Add a webhook</h3>
|
|
386
1398
|
<div class="rowf">
|
|
387
|
-
<div><label>Webhook id<span class="hint">(lowercase)</span></label><input id="w-id" placeholder="
|
|
1399
|
+
<div><label>Webhook id<span class="hint">(lowercase)</span></label><input id="w-id" placeholder="globex-gitlab" /></div>
|
|
388
1400
|
<div><label>Source</label><select id="w-source"><option value="gitlab">GitLab \u2713</option><option value="github">GitHub \u2713</option><option value="sentry">Sentry \u2713</option><option value="stripe">Stripe \u2713</option><option value="vercel">Vercel \u2713</option><option value="odoo">Odoo \u2713</option><option value="hubspot">HubSpot \u2713</option><option value="discord">Discord</option><option value="slack">Slack</option><option value="custom">Custom</option></select></div>
|
|
389
1401
|
</div>
|
|
390
1402
|
<div class="rowf">
|
|
@@ -392,21 +1404,21 @@ ${Qa}</script>`})}var Ka=`
|
|
|
392
1404
|
<div><label>Signing secret env-var<span class="hint">(optional)</span></label><input id="w-secret" placeholder="GITLAB_WEBHOOK_SECRET" /></div>
|
|
393
1405
|
</div>
|
|
394
1406
|
<label>Description<span class="hint">(optional)</span></label>
|
|
395
|
-
<input id="w-desc" placeholder="
|
|
1407
|
+
<input id="w-desc" placeholder="Globex main project webhooks" />
|
|
396
1408
|
<div class="actions"><button class="primary" onclick="addWebhook()">Add webhook</button><div id="w-msg" class="msg"></div></div>
|
|
397
1409
|
</div>
|
|
398
1410
|
</section>
|
|
399
1411
|
|
|
400
1412
|
<section id="tab-mesh" class="tab">
|
|
401
|
-
${N({icon:
|
|
1413
|
+
${N({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."})}
|
|
402
1414
|
<div id="mesh-hero" class="ax-mesh-hero"></div>
|
|
403
1415
|
${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
|
-
${
|
|
1416
|
+
${Ie({label:"Connected peers"})}
|
|
405
1417
|
<div id="mesh-peers" class="ax-stack"></div>
|
|
406
1418
|
<div class="add-form">
|
|
407
1419
|
<h3>Add a peer</h3>
|
|
408
1420
|
<div class="rowf">
|
|
409
|
-
<div><label>Peer name<span class="hint">(human label)</span></label><input id="m-name" placeholder="
|
|
1421
|
+
<div><label>Peer name<span class="hint">(human label)</span></label><input id="m-name" placeholder="peer-server" /></div>
|
|
410
1422
|
<div><label>URL</label><input id="m-url" placeholder="http://192.168.1.50:18800" /></div>
|
|
411
1423
|
</div>
|
|
412
1424
|
<label>Auth token<span class="hint">(optional \u2014 use a scoped token with <code>mesh:peer</code>)</span></label>
|
|
@@ -428,7 +1440,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
428
1440
|
</section>
|
|
429
1441
|
|
|
430
1442
|
<section id="tab-business" class="tab">
|
|
431
|
-
${N({icon:
|
|
1443
|
+
${N({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
1444
|
${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
1445
|
|
|
434
1446
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -457,16 +1469,38 @@ ${Qa}</script>`})}var Ka=`
|
|
|
457
1469
|
<summary class="primary">+ Add or update project</summary>
|
|
458
1470
|
<div style="margin-top:10px">
|
|
459
1471
|
<label>Project id<span class="hint">(<code>owner/repo</code> for GitLab/GitHub; stable string for internal projects)</span></label>
|
|
460
|
-
<input id="bp-id" placeholder="
|
|
1472
|
+
<input id="bp-id" placeholder="globex/system" />
|
|
461
1473
|
<label>PM <span class="hint">(agentId \u2014 drives the PM gate)</span></label>
|
|
462
|
-
<input id="bp-pm" placeholder="pm-
|
|
1474
|
+
<input id="bp-pm" placeholder="pm-globex" />
|
|
463
1475
|
<label>Client <span class="hint">(used by the activity graph to attribute traffic)</span></label>
|
|
464
|
-
<input id="bp-client" placeholder="
|
|
1476
|
+
<input id="bp-client" placeholder="globex" />
|
|
465
1477
|
<div class="actions"><button class="primary" onclick="upsertProject()">Save project</button><div id="bp-msg" class="msg"></div></div>
|
|
466
1478
|
</div>
|
|
467
1479
|
</details>
|
|
468
1480
|
</div>
|
|
469
1481
|
|
|
1482
|
+
<div class="ax-stack" style="margin-top:24px">
|
|
1483
|
+
<h3 style="margin:0 0 6px;font-size:13px">Clients</h3>
|
|
1484
|
+
<p class="hint" style="margin:0 0 8px">Clients are derived from projects and the contact map — one exists as soon as either mentions it. Everything below is optional: set it only when you want the monitor to treat a client differently.</p>
|
|
1485
|
+
<div id="business-client-list"></div>
|
|
1486
|
+
<details class="add-form" style="margin-top:10px">
|
|
1487
|
+
<summary class="primary">+ Configure a client</summary>
|
|
1488
|
+
<div style="margin-top:10px">
|
|
1489
|
+
<label>Client id<span class="hint">(as it already appears on a project or contact)</span></label>
|
|
1490
|
+
<input id="bc-id" placeholder="globex" />
|
|
1491
|
+
<label>Display name <span class="hint">(optional)</span></label>
|
|
1492
|
+
<input id="bc-name" placeholder="Globex" />
|
|
1493
|
+
<label>Kind <span class="hint">(client = someone waiting on you; own = your product; internal = machinery)</span></label>
|
|
1494
|
+
<select id="bc-kind"><option value="">(default)</option><option value="client">client</option><option value="own">own</option><option value="internal">internal</option></select>
|
|
1495
|
+
<label>Respond within <span class="hint">(<code>4h</code>, <code>90m</code>, <code>2d</code> — blank means no clock, delay stays flat)</span></label>
|
|
1496
|
+
<input id="bc-respond" placeholder="4h" />
|
|
1497
|
+
<label>Standing authorizations <span class="hint">(comma-separated; <code>*</code> for all. Ignored for kind <code>client</code> — agents never act unattended on a client's work)</span></label>
|
|
1498
|
+
<input id="bc-standing" placeholder="rebase-branch, open-followup-issue" />
|
|
1499
|
+
<div class="actions"><button class="primary" onclick="upsertClient()">Save client</button><div id="bc-msg" class="msg"></div></div>
|
|
1500
|
+
</div>
|
|
1501
|
+
</details>
|
|
1502
|
+
</div>
|
|
1503
|
+
|
|
470
1504
|
<div class="ax-stack" style="margin-top:24px">
|
|
471
1505
|
<h3 style="margin:0 0 6px;font-size:13px">Contact map</h3>
|
|
472
1506
|
<div id="business-contact-list"></div>
|
|
@@ -478,15 +1512,15 @@ ${Qa}</script>`})}var Ka=`
|
|
|
478
1512
|
<label>Chat id <span class="hint">(e.g. <code>-100\u2026</code>, JID \u2014 pick at least one of these three)</span></label>
|
|
479
1513
|
<input id="bc-chatId" placeholder="-1003861455814" />
|
|
480
1514
|
<label>Username</label>
|
|
481
|
-
<input id="bc-username" placeholder="
|
|
1515
|
+
<input id="bc-username" placeholder="alex" />
|
|
482
1516
|
<label>Sender id</label>
|
|
483
1517
|
<input id="bc-senderId" placeholder="8500203323" />
|
|
484
1518
|
<label>Client <span class="hint">(required)</span></label>
|
|
485
|
-
<input id="bc-client" placeholder="
|
|
1519
|
+
<input id="bc-client" placeholder="acme" />
|
|
486
1520
|
<label>Project <span class="hint">(optional \u2014 defaults to <code><client>/_chat</code>)</span></label>
|
|
487
|
-
<input id="bc-project" placeholder="
|
|
1521
|
+
<input id="bc-project" placeholder="acme/internal" />
|
|
488
1522
|
<label>Display name <span class="hint">(initiator pill override)</span></label>
|
|
489
|
-
<input id="bc-displayName" placeholder="
|
|
1523
|
+
<input id="bc-displayName" placeholder="Alex Rivera" />
|
|
490
1524
|
<div class="actions"><button class="primary" onclick="upsertContact()">Save mapping</button><div id="bc-msg" class="msg"></div></div>
|
|
491
1525
|
</div>
|
|
492
1526
|
</details>
|
|
@@ -494,7 +1528,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
494
1528
|
</section>
|
|
495
1529
|
|
|
496
1530
|
<section id="tab-boards-cfg" class="tab">
|
|
497
|
-
${N({icon:
|
|
1531
|
+
${N({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
1532
|
${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
1533
|
|
|
500
1534
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -503,12 +1537,12 @@ ${Qa}</script>`})}var Ka=`
|
|
|
503
1537
|
<details class="add-form" style="margin-top:10px">
|
|
504
1538
|
<summary class="primary">+ Add or update board</summary>
|
|
505
1539
|
<div style="margin-top:10px">
|
|
506
|
-
<label>Board id<span class="hint">(unique slug, e.g. <code>
|
|
507
|
-
<input id="bd-id" placeholder="
|
|
1540
|
+
<label>Board id<span class="hint">(unique slug, e.g. <code>globex</code>)</span></label>
|
|
1541
|
+
<input id="bd-id" placeholder="globex" />
|
|
508
1542
|
<label>Display name</label>
|
|
509
|
-
<input id="bd-name" placeholder="
|
|
510
|
-
<label>GitLab project paths<span class="hint">(comma-separated, e.g. <code>
|
|
511
|
-
<input id="bd-projects" placeholder="
|
|
1543
|
+
<input id="bd-name" placeholder="Globex System" />
|
|
1544
|
+
<label>GitLab project paths<span class="hint">(comma-separated, e.g. <code>globex/system,globex/website</code>)</span></label>
|
|
1545
|
+
<input id="bd-projects" placeholder="globex/system" />
|
|
512
1546
|
<label>Primary tool label <span class="hint">(optional \u2014 ANDed into every query, e.g. <code>Tool::Claude</code>)</span></label>
|
|
513
1547
|
<input id="bd-label" placeholder="Tool::Claude" />
|
|
514
1548
|
<div style="display:flex;gap:6px"><label style="flex:1">Open-window days<input id="bd-days" type="number" min="1" max="365" value="30" /></label><label style="flex:1">Closed-window days<input id="bd-closed-days" type="number" min="1" max="365" value="30" /></label></div>
|
|
@@ -519,7 +1553,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
519
1553
|
</section>
|
|
520
1554
|
|
|
521
1555
|
<section id="tab-actions" class="tab">
|
|
522
|
-
${N({icon:
|
|
1556
|
+
${N({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
1557
|
${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
1558
|
|
|
525
1559
|
<div class="ax-stack" style="margin-top:14px">
|
|
@@ -575,7 +1609,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
575
1609
|
</section>
|
|
576
1610
|
|
|
577
1611
|
<section id="tab-tokens" class="tab">
|
|
578
|
-
${N({icon:
|
|
1612
|
+
${N({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
1613
|
${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
1614
|
<div id="token-list" class="ax-stack"></div>
|
|
581
1615
|
<div class="add-form">
|
|
@@ -595,7 +1629,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
595
1629
|
</section>
|
|
596
1630
|
|
|
597
1631
|
<section id="tab-advanced" class="tab">
|
|
598
|
-
${N({icon:
|
|
1632
|
+
${N({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
1633
|
${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
1634
|
|
|
601
1635
|
<div class="ax-jv-toolbar">
|
|
@@ -622,7 +1656,7 @@ ${Qa}</script>`})}var Ka=`
|
|
|
622
1656
|
<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
1657
|
</section>
|
|
624
1658
|
</main>
|
|
625
|
-
`,
|
|
1659
|
+
`,Tn=`
|
|
626
1660
|
|
|
627
1661
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
628
1662
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -830,7 +1864,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
830
1864
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
831
1865
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
832
1866
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
833
|
-
`,
|
|
1867
|
+
`,Cn=`
|
|
834
1868
|
const $ = (id) => document.getElementById(id);
|
|
835
1869
|
let state = null;
|
|
836
1870
|
|
|
@@ -1202,6 +2236,37 @@ function renderBusiness() {
|
|
|
1202
2236
|
}
|
|
1203
2237
|
}
|
|
1204
2238
|
|
|
2239
|
+
const clientsCfg = (state.business && state.business.clients) || {};
|
|
2240
|
+
// Show every client that resolves, not just the configured ones, so the
|
|
2241
|
+
// operator can see what exists before deciding to override anything.
|
|
2242
|
+
const derived = {};
|
|
2243
|
+
projects.forEach(function(p){ derived[p.client || (p.id.indexOf('/') > 0 ? p.id.slice(0, p.id.indexOf('/')) : p.id)] = true; });
|
|
2244
|
+
((state.business && state.business.contactMap) || []).forEach(function(c){ if (c.client) derived[c.client] = true; });
|
|
2245
|
+
Object.keys(clientsCfg).forEach(function(id){ derived[id] = true; });
|
|
2246
|
+
const clientIds = Object.keys(derived).sort();
|
|
2247
|
+
const kl = $('business-client-list');
|
|
2248
|
+
if (kl) {
|
|
2249
|
+
if (clientIds.length === 0) {
|
|
2250
|
+
kl.innerHTML = '<div class="ax-empty-card" style="text-align:center;padding:18px;background:var(--ax-surface);border:1px dashed var(--ax-border-2);border-radius:6px;color:var(--ax-muted);font-size:12px">no clients yet — add a project or a contact mapping</div>';
|
|
2251
|
+
} else {
|
|
2252
|
+
kl.innerHTML = clientIds.map(function(id){
|
|
2253
|
+
const c = clientsCfg[id] || {};
|
|
2254
|
+
const tag = function(t){ return '<span style="font-size:11px;color:var(--ax-muted)">' + t + '</span>'; };
|
|
2255
|
+
const bits = [
|
|
2256
|
+
tag(c.kind ? 'kind=' + escapeHtml(c.kind) : 'kind=client (default)'),
|
|
2257
|
+
c.respondWithin ? tag('within=' + escapeHtml(c.respondWithin)) : '',
|
|
2258
|
+
(c.standing && c.standing.length) ? tag('standing=' + escapeHtml(c.standing.join(' '))) : '',
|
|
2259
|
+
c.name ? tag('"' + escapeHtml(c.name) + '"') : '',
|
|
2260
|
+
clientsCfg[id] ? '' : tag('derived'),
|
|
2261
|
+
].filter(Boolean).join('');
|
|
2262
|
+
return '<div class="ax-row-card" style="display:flex;align-items:center;gap:10px;padding:8px 12px;border:1px solid var(--ax-border);border-radius:6px;margin-bottom:5px">' +
|
|
2263
|
+
'<div style="flex:1;min-width:0;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap"><code style="font-size:12px">' + escapeHtml(id) + '</code>' + bits + '</div>' +
|
|
2264
|
+
(clientsCfg[id] ? '<button class="ghost danger" data-act="biz-client-rm" data-id="' + escapeHtml(id) + '">Reset</button>' : '') +
|
|
2265
|
+
'</div>';
|
|
2266
|
+
}).join('');
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
|
|
1205
2270
|
const cl = $('business-contact-list');
|
|
1206
2271
|
if (cl) {
|
|
1207
2272
|
if (contactMap.length === 0) {
|
|
@@ -1240,6 +2305,11 @@ function wireBusinessHandlers() {
|
|
|
1240
2305
|
if (!confirm('Remove project ' + id + '?')) return;
|
|
1241
2306
|
try { await req('DELETE', '/api/admin/business/project', { id }); await load(); }
|
|
1242
2307
|
catch (e) { showMsg($('global-msg'), 'err', e.message); }
|
|
2308
|
+
} else if (act === 'biz-client-rm') {
|
|
2309
|
+
const id = t.getAttribute('data-id');
|
|
2310
|
+
if (!confirm('Reset ' + id + ' to derived defaults?')) return;
|
|
2311
|
+
try { await req('DELETE', '/api/admin/business/client', { id }); await load(); }
|
|
2312
|
+
catch (e) { showMsg($('global-msg'), 'err', e.message); }
|
|
1243
2313
|
} else if (act === 'biz-contact-rm') {
|
|
1244
2314
|
const idx = parseInt(t.getAttribute('data-idx') || '-1', 10);
|
|
1245
2315
|
const list = (state.business && state.business.contactMap) || [];
|
|
@@ -1271,6 +2341,23 @@ window.upsertOrgEntry = async function() {
|
|
|
1271
2341
|
} catch (e) { showMsg($('bo-msg'), 'err', e.message); }
|
|
1272
2342
|
}
|
|
1273
2343
|
|
|
2344
|
+
window.upsertClient = async function() {
|
|
2345
|
+
const id = $('bc-id').value.trim();
|
|
2346
|
+
const body = {
|
|
2347
|
+
id: id,
|
|
2348
|
+
name: $('bc-name').value.trim(),
|
|
2349
|
+
kind: $('bc-kind').value,
|
|
2350
|
+
respondWithin: $('bc-respond').value.trim(),
|
|
2351
|
+
standing: $('bc-standing').value.split(',').map(function(s){ return s.trim(); }).filter(Boolean),
|
|
2352
|
+
};
|
|
2353
|
+
try {
|
|
2354
|
+
await req('POST', '/api/admin/business/client', body);
|
|
2355
|
+
$('bc-id').value = ''; $('bc-name').value = ''; $('bc-respond').value = ''; $('bc-standing').value = '';
|
|
2356
|
+
showMsg($('bc-msg'), 'ok', 'Client saved');
|
|
2357
|
+
await load();
|
|
2358
|
+
} catch (e) { showMsg($('bc-msg'), 'err', e.message); }
|
|
2359
|
+
}
|
|
2360
|
+
|
|
1274
2361
|
window.upsertProject = async function() {
|
|
1275
2362
|
const id = $('bp-id').value.trim();
|
|
1276
2363
|
const pm = $('bp-pm').value.trim();
|
|
@@ -1879,7 +2966,7 @@ function renderIntegrationsBlock(a) {
|
|
|
1879
2966
|
'<div style="margin-top:10px;padding:8px 10px;background:var(--ax-bg);border:1px dashed var(--ax-border-2);border-radius:5px">' +
|
|
1880
2967
|
'<div style="display:grid;grid-template-columns:1fr 1.5fr;gap:6px">' +
|
|
1881
2968
|
'<select data-int-kind style="font-size:11px">' + kindOptions + '</select>' +
|
|
1882
|
-
'<input data-int-label-add placeholder="Label (e.g.
|
|
2969
|
+
'<input data-int-label-add placeholder="Label (e.g. Acme CRM, @cx_bot)" style="font-size:11px" />' +
|
|
1883
2970
|
'</div>' +
|
|
1884
2971
|
'<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:6px">' +
|
|
1885
2972
|
'<input data-int-tokenenv placeholder="Token env var (UPPERCASE)" style="font-size:11px" />' +
|
|
@@ -3501,11 +4588,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
3501
4588
|
})();
|
|
3502
4589
|
|
|
3503
4590
|
refresh();
|
|
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}
|
|
4591
|
+
`;function Vt(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Xt({peers:a,localToken:n}))}async function Yt(t,e){let a=Ye();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Qt(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 $n(t),r={"GET /api/admin/state":()=>Ln(),"POST /api/admin/agents":()=>Nn(n),"PATCH /api/admin/agents":()=>Bn(n),"DELETE /api/admin/agents":()=>zn(n),"POST /api/admin/agents/access":()=>Rn(n),"POST /api/admin/channels/telegram":()=>qn(n),"DELETE /api/admin/channels/telegram":()=>ur(n),"POST /api/admin/channels/telegram/toggle":()=>mr(n),"POST /api/admin/crons":()=>hr(n),"DELETE /api/admin/crons":()=>gr(n),"POST /api/admin/config/raw":()=>fr(n),"GET /api/admin/tokens":()=>Pn(),"POST /api/admin/tokens":()=>Dn(n),"DELETE /api/admin/tokens":()=>On(n),"POST /api/admin/agents/test":()=>Hn(n),"POST /api/admin/agents/integrations":()=>Vn(n),"DELETE /api/admin/agents/integrations":()=>Yn(n),"PATCH /api/admin/agents/integrations":()=>Qn(n),"PATCH /api/admin/channels/telegram":()=>Un(n),"POST /api/admin/channels/slack":()=>or(n),"POST /api/admin/channels/slack/toggle":()=>sr(n),"POST /api/admin/channels/discord":()=>ir(n),"POST /api/admin/channels/discord/toggle":()=>lr(n),"POST /api/admin/channels/gitlab":()=>dr(n),"POST /api/admin/channels/gitlab/toggle":()=>cr(n),"GET /api/admin/channels/whatsapp/state":()=>be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>be("/webrtc/history"),"POST /api/admin/actions":()=>Mr(n),"DELETE /api/admin/actions":()=>Ir(n),"POST /api/admin/actions/run":()=>$r(n),"GET /api/admin/channels/whatsapp/chats":()=>be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>te("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>pr(n),"POST /api/admin/webhooks":()=>Zn(n),"PATCH /api/admin/webhooks":()=>er(n),"DELETE /api/admin/webhooks":()=>rr(n),"POST /api/admin/mesh/peers":()=>tr(n),"DELETE /api/admin/mesh/peers":()=>ar(n),"POST /api/admin/mesh/toggle":()=>nr(n),"GET /api/admin/files":()=>Wn(t),"GET /api/admin/files/read":()=>Gn(t),"PUT /api/admin/files":()=>Xn(n),"POST /api/admin/files/skill":()=>Kn(n),"DELETE /api/admin/files/skill":()=>Jn(n),"POST /api/admin/business/orgchart":()=>xr(n),"DELETE /api/admin/business/orgchart":()=>vr(n),"POST /api/admin/business/project":()=>br(n),"DELETE /api/admin/business/project":()=>kr(n),"POST /api/admin/business/client":()=>yr(n),"DELETE /api/admin/business/client":()=>wr(n),"POST /api/admin/business/contact":()=>_r(n),"DELETE /api/admin/business/contact":()=>Er(n),"POST /api/admin/boards":()=>Sr(n),"DELETE /api/admin/boards":()=>Tr(n),"POST /api/admin/boards/columns":()=>Cr(n),"DELETE /api/admin/boards/columns":()=>Ar(n),"POST /api/admin/notifications":()=>Lr(n),"POST /api/admin/webhooks/triggers":()=>Rr(n),"POST /api/admin/mesh/health":()=>jr(n),"GET /api/admin/projects":()=>be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>te("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>te("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>te("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>te("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>te("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>te("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>te("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>te("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Je(e,404,{error:`unknown admin endpoint: ${o}`});return}let l=await s();Je(e,200,l)}catch(n){Je(e,400,{error:n.message||"admin op failed"})}}function Je(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $n(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 jn(t){let e=he(process.cwd(),t);if(!Le(e))return[];let a=[];for(let n of In(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Kt(he(e,n.name),"utf-8")))}catch{}return a}function Ye(){let t=he(process.cwd(),"agentx.json");return Le(t)?JSON.parse(Kt(t,"utf-8")):null}function Ln(){let t=Ye();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,p])=>({id:d,name:p.name,tier:p.tier,model:p.model,mentions:p.mentions||[],workspace:p.workspace,access:p.access||"private",systemPrompt:p.systemPrompt||"",maxConcurrent:p.maxConcurrent??1,maxExecutionMinutes:p.maxExecutionMinutes??20,permissionMode:p.permissionMode||"default",integrations:(Array.isArray(p.integrations)?p.integrations:[]).map(g=>{let f=g.credentials||{},h={};for(let[y,k]of Object.entries(f))typeof k=="string"&&/^[A-Z][A-Z0-9_]*$/.test(k)?h[y]=process.env[k]?"set":"unset":typeof k=="string"&&(h[y]="literal");return{kind:g.kind,label:g.label,enabled:g.enabled!==!1,credentials:f,credStatus:h,metadata:g.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,p])=>({id:d,botUsername:p.botUsername||"",agentBinding:p.agentBinding||"",botTokenRef:p.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(([d,p])=>({id:d,schedule:p.schedule,agent:p.agent,prompt:(p.prompt||"").slice(0,200),enabled:p.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],u={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},m=t.dashboard?.daemonUrl||"http://localhost:18800",x=t.business||{},b={enabled:!!x.enabled,timezone:x.timezone||"UTC",orgChart:x.orgChart||{},projects:Array.isArray(x.projects)?x.projects:[],contactMap:Array.isArray(x.contactMap)?x.contactMap:[],clients:x.clients&&typeof x.clients=="object"?x.clients:{}},_=t.notifications||{},M={longTaskThreshold:_.longTaskThreshold??30,destination:_.destination||null,on:{taskComplete:_.on?.taskComplete!==!1,taskError:_.on?.taskError!==!1,taskQueued:!!_.on?.taskQueued}},E=[];try{E=jn(".agentx/actions").filter(p=>p&&typeof p=="object"&&p.id).map(p=>({id:p.id,title:p.title,kind:p.kind,description:p.description||"",inputs:Array.isArray(p.inputs)?p.inputs:[],timeoutMs:p.timeoutMs??3e4,command:p.kind==="shell"?p.command:void 0,url:p.kind==="http"?p.url:void 0,method:p.kind==="http"?p.method:void 0})).sort((p,g)=>p.id.localeCompare(g.id))}catch{}let S=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:l,crons:i,webhooks:c,mesh:u,daemonUrl:m,nodeName:t.node?.name,business:b,boards:S,notifications:M,actions:E}}function Rn(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}=T(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 Pn(){return new ee().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 Dn(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 ee().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function On(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ee().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Hn(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 u=G();r=u.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=u.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(),c;try{c=JSON.parse(i)}catch{c={content:i}}if(!l.ok)throw new Error(c?.error||`daemon HTTP ${l.status}`);return{chatId:n,response:c}}function Nn(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=ea(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=he(process.cwd(),"agents",e),{summary:i}=T(u=>{if(u.agents=u.agents||{},u.agents[e])throw new Error(`Agent "${e}" already exists.`);let m={name:a,workspace:l,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(m.model=o),s&&(m.systemPrompt=s.slice(0,400)),u.agents[e]=m,`added agent "${e}"`}),c=he(l,"CLAUDE.md");if(!Le(c))try{An(l,{recursive:!0}),Jt(c,`# ${a}
|
|
3505
4592
|
|
|
3506
4593
|
${s||"You are "+a+"."}
|
|
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>
|
|
4594
|
+
`)}catch{}return{summary:i}}function Bn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=T(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=ea(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 zn(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=T(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 qn(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}=T(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 Un(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=T(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 be(t){let{url:e,headers:a}=Qe(),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 te(t,e){let{url:a,headers:n}=Qe(),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}=Qe(),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 Qe(){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 ye(t){let a=Ye()?.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 Ve(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Wn(t){let e=Ve(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=ue(ye(e));return{agentId:e,...a}}function Gn(t){let e=Ve(t,"agent").trim(),a=Ve(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return _e(ye(e),a)}function Xn(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=Ee(ye(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Kn(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=Se(ye(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Jn(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=Te(ye(e),a);return{summary:`removed skill "${a}"`,...n}}function Vn(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 c=o[i];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${i} must be uppercase identifier (got "${c}")`);r[i]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[i,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[i]=c);let{summary:l}=T(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(c=>c.kind===a&&c.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 Yn(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}=T(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let l=s.integrations||[],i=l.findIndex(c=>c.kind===a&&c.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 Qn(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}=T(s=>{let l=s.agents?.[e];if(!l)throw new Error(`Unknown agent "${e}"`);let c=(l.integrations||[]).find(u=>u.kind===a&&u.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Zt=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Zn(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(!Zt.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:l}=T(i=>{if(s){if(!(i.mesh?.peers||[]).find(m=>m.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(u=>u.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),i.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:l}}function er(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=T(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Zt.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 tr(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}=T(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 ar(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=T(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 nr(t){let e=!!t?.enabled,{summary:a}=T(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 rr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=T(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 or(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}=T(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 sr(t){let e=!!t?.enabled,{summary:a}=T(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 ir(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}=T(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 lr(t){let e=!!t?.enabled,{summary:a}=T(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 dr(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}=T(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 cr(t){let e=!!t?.enabled,{summary:a}=T(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 pr(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-GZZAN6ZG.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 ur(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=T(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 mr(t){let e=!!t?.enabled,{summary:a}=T(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 hr(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}=T(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 gr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=T(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function fr(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=he(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Le(n))try{Mn(n,r)}catch{}Jt(n,JSON.stringify(a,null,2)+`
|
|
4595
|
+
`,"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 ea(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function xr(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}=T(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:l},`orgChart "${e}" upserted`));return{summary:i}}async function vr(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=T(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 br(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}=T(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 yr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=T(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let l=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},l?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function wr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=T(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function kr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=T(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 _r(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}=T(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 Er(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}=T(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 Sr(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}=T(i=>{i.boards=Array.isArray(i.boards)?i.boards:[];let c=i.boards.findIndex(m=>m.id===e),u={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(u.primaryToolLabel=r),c>=0){let m=i.boards[c];return i.boards[c]={...m,...u,columns:m.columns,labels:m.labels},`board "${e}" updated`}return i.boards.push(u),`board "${e}" added`});return{summary:l}}async function Tr(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=T(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 Cr(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}=T(s=>{let i=(Array.isArray(s.boards)?s.boards:[]).find(m=>m.id===e);if(!i)throw new Error(`board "${e}" not found`);i.columns=Array.isArray(i.columns)?i.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let u=i.columns.findIndex(m=>m.id===a);return u>=0?(i.columns[u]={...i.columns[u],...c},`column "${a}" updated`):(i.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ar(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}=T(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 Mr(t){let{ActionStore:e}=await import("./store-MCOA6N4F.js"),{actionSchema:a}=await import("./types-H5ENIUIT.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 Ir(t){let{ActionStore:e}=await import("./store-MCOA6N4F.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 $r(t){let{ActionStore:e}=await import("./store-MCOA6N4F.js"),{runAction:a}=await import("./runner-YRBVNYTY.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 jr(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}=T(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 Lr(t){let{summary:e}=T(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}=T(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}}Ne();import{resolve as Or}from"path";function ta(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
3509
4596
|
|
|
3510
4597
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
3511
4598
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -3535,7 +4622,7 @@ ${s||"You are "+a+"."}
|
|
|
3535
4622
|
<summary>Add node</summary>
|
|
3536
4623
|
<div class="row" style="margin-top:10px">
|
|
3537
4624
|
<select id="n-level"></select>
|
|
3538
|
-
<input id="n-id" placeholder="node id (e.g.
|
|
4625
|
+
<input id="n-id" placeholder="node id (e.g. acme-devops)" />
|
|
3539
4626
|
<select id="n-parent"><option value="">\u2014 no parent \u2014</option></select>
|
|
3540
4627
|
</div>
|
|
3541
4628
|
<div class="row" style="margin-top:6px">
|
|
@@ -3560,7 +4647,7 @@ ${s||"You are "+a+"."}
|
|
|
3560
4647
|
<h2>Recent classifications</h2>
|
|
3561
4648
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
3562
4649
|
<div id="recent"></div>
|
|
3563
|
-
</section>`;return
|
|
4650
|
+
</section>`;return C({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Pr,scripts:`${e}<script>${Dr}</script>`})}var Pr=`
|
|
3564
4651
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
3565
4652
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
3566
4653
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -3664,7 +4751,7 @@ details {
|
|
|
3664
4751
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
3665
4752
|
}
|
|
3666
4753
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
3667
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
4754
|
+
details[open] summary { margin-bottom: 8px; }`,Dr=`
|
|
3668
4755
|
const $ = (id) => document.getElementById(id);
|
|
3669
4756
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
3670
4757
|
|
|
@@ -3884,7 +4971,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
3884
4971
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
3885
4972
|
|
|
3886
4973
|
refresh();
|
|
3887
|
-
`;function
|
|
4974
|
+
`;function na(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ta({peers:a,localToken:n}))}async function ra(t,e,a){try{let n=t.method==="GET"?void 0:await Gr(t),r=Hr(),o={"GET /api/admin/graph/state":()=>Nr(r),"POST /api/admin/graph/classifications/approve":()=>Br(r,n),"POST /api/admin/graph/classifications/reject":()=>zr(r,n),"POST /api/admin/graph/nodes":()=>qr(r,n),"PATCH /api/admin/graph/nodes":()=>Ur(r,n),"DELETE /api/admin/graph/nodes":()=>Fr(r,n),"PUT /api/admin/graph/schema":()=>Wr(r,n)},s=`${t.method} ${a}`,l=o[s];if(!l){Ze(e,404,{error:`unknown graph endpoint: ${s}`});return}let i=await l();Ze(e,200,i)}catch(n){Ze(e,400,{error:n?.message||"graph op failed"})}}function Hr(){let t=G(),e=Or(process.cwd(),t.graph.baseDir);return new gt({baseDir:e})}function Nr(t){let e=G(),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 Br(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=oa(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=et(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function zr(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=oa(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function oa(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 qr(t,e){let a=aa(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?aa(String(e.parentId)):null,o=et({[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 Ur(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=et({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Fr(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Wr(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 et(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 aa(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Ze(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Gr(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 Jr}from"path";import{existsSync as Vr}from"fs";import Yr from"better-sqlite3";function sa(t={}){let e=`<div class="ax-obs">
|
|
3888
4975
|
<header class="ax-obs__head">
|
|
3889
4976
|
<h1>Health</h1>
|
|
3890
4977
|
<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 +5093,7 @@ refresh();
|
|
|
4006
5093
|
</div>
|
|
4007
5094
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
4008
5095
|
</section>
|
|
4009
|
-
</div>`;return
|
|
5096
|
+
</div>`;return C({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Xr,scripts:`<script>${Kr}</script>`})}var Xr=`
|
|
4010
5097
|
.ax-obs { padding: 16px 24px; }
|
|
4011
5098
|
.ax-obs__head { margin-bottom: 16px; }
|
|
4012
5099
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -4099,17 +5186,17 @@ refresh();
|
|
|
4099
5186
|
.ax-obs__pill--idle { background: rgba(218, 119, 6, 0.15); color: #bf8700; }
|
|
4100
5187
|
.ax-obs__empty { color: var(--ax-muted); font-style: italic; padding: 18px 0; margin: 0; }
|
|
4101
5188
|
.ax-obs__logs-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; flex-wrap: wrap; }
|
|
4102
|
-
.ax-obs__logs-toolbar input[type="text"] { font-family: 'IBM Plex Mono', monospace; font-size: 12px; padding: 5px 9px; min-width: 220px; background: var(--ax-bg-elev); border: 1px solid var(--ax-border); border-radius: 4px; color: var(--ax-
|
|
4103
|
-
.ax-obs__logs-toolbar button { font-size: 11px; padding: 5px 11px; border-radius: 4px; border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-
|
|
5189
|
+
.ax-obs__logs-toolbar input[type="text"] { font-family: 'IBM Plex Mono', monospace; font-size: 12px; padding: 5px 9px; min-width: 220px; background: var(--ax-bg-elev); border: 1px solid var(--ax-border); border-radius: 4px; color: var(--ax-text); }
|
|
5190
|
+
.ax-obs__logs-toolbar button { font-size: 11px; padding: 5px 11px; border-radius: 4px; border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-text); cursor: pointer; }
|
|
4104
5191
|
.ax-obs__logs-toolbar button:hover { background: var(--ax-surface); }
|
|
4105
5192
|
.ax-obs__inline { font-size: 11px; color: var(--ax-muted); display: inline-flex; align-items: center; gap: 4px; }
|
|
4106
5193
|
.ax-obs__logs-body { font-family: 'IBM Plex Mono', monospace; font-size: 11px; line-height: 1.45; height: calc(100vh - 320px); min-height: 360px; overflow-y: auto; background: var(--ax-bg-elev); border: 1px solid var(--ax-border); border-radius: 4px; padding: 10px 12px; margin: 0; white-space: pre-wrap; word-break: break-word; }
|
|
4107
5194
|
.ax-obs__logs-body .err { color: var(--ax-err, #e74c3c); }
|
|
4108
5195
|
.ax-obs__logs-body .warn { color: #d4ac0d; }
|
|
4109
|
-
.ax-obs__logs-body .info { color: var(--ax-
|
|
5196
|
+
.ax-obs__logs-body .info { color: var(--ax-text); }
|
|
4110
5197
|
.ax-obs__logs-body .dim { color: var(--ax-muted); }
|
|
4111
5198
|
.ax-obs__doctor-toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
|
|
4112
|
-
.ax-obs__doctor-toolbar button { font-size: 11px; padding: 5px 11px; border-radius: 4px; border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-
|
|
5199
|
+
.ax-obs__doctor-toolbar button { font-size: 11px; padding: 5px 11px; border-radius: 4px; border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-text); cursor: pointer; }
|
|
4113
5200
|
.ax-obs__doctor-toolbar button:hover { background: var(--ax-surface); }
|
|
4114
5201
|
.ax-obs__doctor-body { display: flex; flex-direction: column; gap: 10px; }
|
|
4115
5202
|
.ax-obs__doctor-group { background: var(--ax-bg-elev); border: 1px solid var(--ax-border); border-radius: 6px; padding: 10px 14px; }
|
|
@@ -4123,7 +5210,7 @@ refresh();
|
|
|
4123
5210
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
4124
5211
|
.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
5212
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
4126
|
-
`,
|
|
5213
|
+
`,Kr=`
|
|
4127
5214
|
(function(){
|
|
4128
5215
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
4129
5216
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -4507,23 +5594,23 @@ refresh();
|
|
|
4507
5594
|
|
|
4508
5595
|
load(current);
|
|
4509
5596
|
})();
|
|
4510
|
-
`;var
|
|
5597
|
+
`;var da={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 ca(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function tt(t){let e=da[ca(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 Qr(){let t=Jr(process.cwd(),".agentx/db.sqlite");if(!Vr(t))return null;try{let e=new Yr(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function pa(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sa({peers:a}))}function Zr(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 ae(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function ua(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Qr();if(!r)return ae(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Zr(t);if(n==="routing"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
|
|
4511
5598
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
4512
5599
|
FROM route_traces
|
|
4513
|
-
${
|
|
5600
|
+
${l.length?"WHERE "+l.join(" AND "):""}
|
|
4514
5601
|
ORDER BY at DESC LIMIT @limit
|
|
4515
|
-
`,
|
|
5602
|
+
`,u=r.db.prepare(c).all(i);return ae(e,200,{rows:u}),!0}if(n==="rotations"){let l=[],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
|
|
4516
5603
|
SELECT rotated_at, agent_id, channel, reason, last_turn_input_tokens
|
|
4517
5604
|
FROM rotations
|
|
4518
|
-
${
|
|
5605
|
+
${l.length?"WHERE "+l.join(" AND "):""}
|
|
4519
5606
|
ORDER BY rotated_at DESC LIMIT @limit
|
|
4520
|
-
`,
|
|
5607
|
+
`,u=r.db.prepare(c).all(i);return ae(e,200,{rows:u}),!0}if(n==="errors"){let l=["status = 'error'"],i={limit:o};s&&(l.push("agent_id = @agent"),i.agent=s);let c=`
|
|
4521
5608
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
4522
5609
|
FROM task_history
|
|
4523
|
-
WHERE ${
|
|
5610
|
+
WHERE ${l.join(" AND ")}
|
|
4524
5611
|
ORDER BY started_at DESC LIMIT @limit
|
|
4525
|
-
`,
|
|
4526
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
5612
|
+
`,m=r.db.prepare(c).all(i).map(x=>({...x,plain:ma(x.error)}));return ae(e,200,{rows:m}),!0}if(n==="summary"||n==="overview")return ae(e,200,eo(r.db)),!0;if(n==="activity")return ae(e,200,to(r.db,{agent:s})),!0;if(n==="cost"){let l=new URL(t.url||"/","http://_"),i=ia(l.searchParams.get("range"));return ae(e,200,la(r.db,i)),!0}if(n==="cost.csv"){let l=new URL(t.url||"/","http://_"),i=ia(l.searchParams.get("range")),c=la(r.db,i),u=ao(c.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(u),!0}return ae(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ae(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function ma(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(`
|
|
5613
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function eo(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,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,u=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),m=k=>u.length?u[Math.min(u.length-1,Math.floor(u.length*k))].duration_ms:0,x=m(.5),b=m(.95),M=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((k,$)=>k+tt($),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((k,$)=>k+tt($),0),S=t.prepare(`
|
|
4527
5614
|
SELECT agent_id,
|
|
4528
5615
|
COUNT(*) AS tasks,
|
|
4529
5616
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -4533,7 +5620,7 @@ refresh();
|
|
|
4533
5620
|
WHERE started_at >= ?
|
|
4534
5621
|
GROUP BY agent_id
|
|
4535
5622
|
ORDER BY tasks DESC LIMIT 10
|
|
4536
|
-
`).all(a),
|
|
5623
|
+
`).all(a),d=t.prepare(`
|
|
4537
5624
|
SELECT COALESCE(channel, 'unknown') AS channel,
|
|
4538
5625
|
COUNT(*) AS tasks,
|
|
4539
5626
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -4541,12 +5628,12 @@ refresh();
|
|
|
4541
5628
|
WHERE started_at >= ?
|
|
4542
5629
|
GROUP BY channel
|
|
4543
5630
|
ORDER BY tasks DESC
|
|
4544
|
-
`).all(a),
|
|
5631
|
+
`).all(a),p=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(k=>k.agent_id),g=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(k=>k.agent_id)),f=p.filter(k=>!g.has(k)),y=t.prepare(`
|
|
4545
5632
|
SELECT started_at, agent_id, channel, message_preview, error
|
|
4546
5633
|
FROM task_history
|
|
4547
5634
|
WHERE status='error' AND started_at >= ?
|
|
4548
5635
|
ORDER BY started_at DESC LIMIT 5
|
|
4549
|
-
`).all(o).map(
|
|
5636
|
+
`).all(o).map(k=>({...k,plain:ma(k.error)}));return{kpis:{tasksToday:s,tasksDelta:s-l,errorsToday:i,errorRate:s>0?i/s:0,avgDurationMs:Math.round(c),p50DurationMs:x,p95DurationMs:b,spendToday:M,spendDelta:M-E,idleAgentCount:f.length},perAgent:S,perChannel:d,idleAgents:f,recentErrors:y}}function to(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
5637
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
4551
5638
|
COUNT(*) AS tasks,
|
|
4552
5639
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -4554,7 +5641,7 @@ refresh();
|
|
|
4554
5641
|
WHERE started_at >= @since ${r}
|
|
4555
5642
|
GROUP BY hour
|
|
4556
5643
|
ORDER BY hour
|
|
4557
|
-
`).all({since:a,...o}),
|
|
5644
|
+
`).all({since:a,...o}),l=t.prepare(`
|
|
4558
5645
|
SELECT date(started_at) AS day,
|
|
4559
5646
|
COUNT(*) AS tasks,
|
|
4560
5647
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -4562,7 +5649,7 @@ refresh();
|
|
|
4562
5649
|
WHERE started_at >= @since ${r}
|
|
4563
5650
|
GROUP BY day
|
|
4564
5651
|
ORDER BY day
|
|
4565
|
-
`).all({since:n,...o}),
|
|
5652
|
+
`).all({since:n,...o}),i=t.prepare(`
|
|
4566
5653
|
SELECT agent_id,
|
|
4567
5654
|
COUNT(*) AS tasks_7d,
|
|
4568
5655
|
SUM(CASE WHEN started_at >= @last24 THEN 1 ELSE 0 END) AS tasks_24h,
|
|
@@ -4573,7 +5660,7 @@ refresh();
|
|
|
4573
5660
|
WHERE started_at >= @since
|
|
4574
5661
|
GROUP BY agent_id
|
|
4575
5662
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
4576
|
-
`).all({since:n,last24:a});return{hourly:s,daily:
|
|
5663
|
+
`).all({since:n,last24:a});return{hourly:s,daily:l,perAgent:i}}function ia(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 la(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
4577
5664
|
SELECT day, agent_id, model,
|
|
4578
5665
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
4579
5666
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -4581,37 +5668,37 @@ refresh();
|
|
|
4581
5668
|
FROM usage_daily
|
|
4582
5669
|
${a}
|
|
4583
5670
|
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),
|
|
5671
|
+
`).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,c=0,u=0,m=0,x=0,b=0,_=0,M=0,E=0,S={},d={};for(let w of n){let j=tt(w),L=ca(w.model),D=da[L],H=(w.tier2_input_tokens||0)/1e6*D.input*.5+(w.tier2_output_tokens||0)/1e6*D.output*.5+(w.tier2_cache_read_tokens||0)/1e6*D.cacheRead*.5+(w.tier2_cache_create_tokens||0)/1e6*D.cacheCreate*.5,Z=(w.input_tokens||0)+(w.tier2_input_tokens||0),R=(w.output_tokens||0)+(w.tier2_output_tokens||0),J=(w.cache_read_tokens||0)+(w.tier2_cache_read_tokens||0),oe=(w.cache_create_tokens||0)+(w.tier2_cache_create_tokens||0);m+=j,w.day>=s&&(u+=j,_+=w.tasks||0),w.day>=l&&w.day<s&&(E+=j,M+=w.tasks||0),w.day===r&&(i+=j),w.day===o&&(c+=j),w.day===r&&(x+=H),w.day>=s&&(b+=H);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+=Z,q.output+=R,q.cacheRead+=J,q.cacheCreate+=oe,q.cost+=j,q.tier2+=H;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+=j,W.tier2+=H,W.input+=Z,W.output+=R,W.cacheRead+=J,W.cacheCreate+=oe,w.model&&(W.model=w.model);let U=d[w.agent_id]||(d[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+=j,U.tier2+=H,U.input+=Z,U.output+=R,U.cacheRead+=J,U.cacheCreate+=oe,w.model&&(U.model=w.model)}let p=Object.values(S).sort((w,j)=>w.date<j.date?-1:1),g=0,f=0,h=0,y=0,k=0,$=0;for(let w of p)g+=w.tasks,f+=w.input,h+=w.output,y+=w.cacheRead,k+=w.cacheCreate,$+=w.cost;let A=Object.entries(d).map(([w,j])=>({agent_id:w,...j,tokens:j.input+j.output+j.cacheRead+j.cacheCreate})).sort((w,j)=>j.cost-w.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:i,spendYesterday:c,spend7d:u,spend30d:m,tier2Today:x,tier2_7d:b,tier2PctToday:i>0?x/i:0,spendRange:$,avgDailyRange:p.length?$/p.length:0,tasksRange:g,tokensRange:f+h+y+k,cacheHitRange:y+f>0?y/(y+f):0,costPerTaskRange:g>0?$/g:0,spendDeltaWoW:E>0?(u-E)/E:0,tasksDeltaWoW:M>0?(_-M)/M:0},days:p,perAgent:A}}function ao(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
5672
|
`+a.join(`
|
|
4586
5673
|
`)+`
|
|
4587
|
-
`}import{resolve as
|
|
5674
|
+
`}import{resolve as no}from"path";import{existsSync as ro}from"fs";import oo from"better-sqlite3";function so(){let t=no(process.cwd(),".agentx/intent/ledger.sqlite");if(!ro(t))return null;try{let e=new oo(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ha>6e4&&(ha=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var ha=0;function de(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function io(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 ga(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=so();if(!r)return de(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=io(o.searchParams.get("since")),l=o.searchParams.get("source")||"",i=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),u=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let m=s!==void 0?"WHERE ts >= @since":"",x=s!==void 0?"WHERE decided_at >= @since":"",b=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),_=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${x}`).get({since:s}).n,M=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${x} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${m}`).get({since:s}).n,S=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${m} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
|
|
4588
5675
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
4589
5676
|
LEFT JOIN intent_resolutions r
|
|
4590
5677
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
4591
5678
|
WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
|
|
4592
|
-
`).get().n;return
|
|
5679
|
+
`).get().n;return de(e,200,{since:s??null,eventsBySource:b,totalDecisions:_,decisionsByOutcome:M,totalDivergences:E,divergencesBySource:S,inFlight:d}),!0}if(n==="events"){let m=[],x={limit:u};s!==void 0&&(m.push("ts >= @since"),x.since=s),l&&(m.push("source = @source"),x.source=l),i&&(m.push("project = @project"),x.project=i);let b=`
|
|
4593
5680
|
SELECT id, ts, source, source_event_id, project, subject, intent
|
|
4594
5681
|
FROM intent_events
|
|
4595
|
-
${
|
|
5682
|
+
${m.length?"WHERE "+m.join(" AND "):""}
|
|
4596
5683
|
ORDER BY ts DESC LIMIT @limit
|
|
4597
|
-
`;return
|
|
5684
|
+
`;return de(e,200,{rows:r.db.prepare(b).all(x)}),!0}if(n==="divergences"){let m=[],x={limit:u};s!==void 0&&(m.push("ts >= @since"),x.since=s),l&&(m.push("source = @source"),x.source=l);let b=`
|
|
4598
5685
|
SELECT ts, source, decided_by,
|
|
4599
5686
|
legacy_agent_id, legacy_outcome, legacy_reason,
|
|
4600
5687
|
ledger_agent_id, ledger_outcome, ledger_reason,
|
|
4601
5688
|
event_id
|
|
4602
5689
|
FROM intent_divergences
|
|
4603
|
-
${
|
|
5690
|
+
${m.length?"WHERE "+m.join(" AND "):""}
|
|
4604
5691
|
ORDER BY ts DESC LIMIT @limit
|
|
4605
|
-
`;return
|
|
5692
|
+
`;return de(e,200,{rows:r.db.prepare(b).all(x)}),!0}if(n==="active"){let m=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],x={limit:u};l&&(m.push("e.source = @source"),x.source=l);let b=`
|
|
4606
5693
|
SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
|
|
4607
5694
|
d.decided_by, d.decided_at, d.agent_id, d.reason
|
|
4608
5695
|
FROM intent_decisions d
|
|
4609
5696
|
JOIN intent_events e ON e.id = d.event_id
|
|
4610
5697
|
LEFT JOIN intent_resolutions r
|
|
4611
5698
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
4612
|
-
WHERE ${
|
|
5699
|
+
WHERE ${m.join(" AND ")}
|
|
4613
5700
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
4614
|
-
`;return
|
|
5701
|
+
`;return de(e,200,{rows:r.db.prepare(b).all(x)}),!0}return de(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return de(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function fa(t={}){return C({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
4615
5702
|
<header class="ax-led__head">
|
|
4616
5703
|
<h1>Intent ledger</h1>
|
|
4617
5704
|
<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 +5903,7 @@ refresh();
|
|
|
4816
5903
|
}
|
|
4817
5904
|
load();
|
|
4818
5905
|
})();
|
|
4819
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
5906
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function xa(t={}){return C({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
4820
5907
|
<header class="ax-cost__head">
|
|
4821
5908
|
<div>
|
|
4822
5909
|
<h1>Cost</h1>
|
|
@@ -5389,7 +6476,7 @@ refresh();
|
|
|
5389
6476
|
load();
|
|
5390
6477
|
setInterval(load, 30000);
|
|
5391
6478
|
})();
|
|
5392
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
6479
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function va(t={}){let e=`<div class="ax-pj__root">
|
|
5393
6480
|
<aside class="ax-pj__list">
|
|
5394
6481
|
<header>
|
|
5395
6482
|
<h2>Projects</h2>
|
|
@@ -5416,7 +6503,7 @@ refresh();
|
|
|
5416
6503
|
</header>
|
|
5417
6504
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
5418
6505
|
</section>
|
|
5419
|
-
</div>`;return
|
|
6506
|
+
</div>`;return C({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:lo,scripts:`<script>${co}</script>`})}var lo=`
|
|
5420
6507
|
.ax-pj__root {
|
|
5421
6508
|
display: grid;
|
|
5422
6509
|
grid-template-columns: 360px 1fr;
|
|
@@ -5435,7 +6522,7 @@ refresh();
|
|
|
5435
6522
|
}
|
|
5436
6523
|
.ax-pj__list > header h2 { margin: 0; font-size: 14px; }
|
|
5437
6524
|
.ax-pj__icon {
|
|
5438
|
-
background: transparent; color: var(--ax-fg-muted, var(--ax-
|
|
6525
|
+
background: transparent; color: var(--ax-fg-muted, var(--ax-text));
|
|
5439
6526
|
border: 1px solid transparent; border-radius: 4px;
|
|
5440
6527
|
padding: 4px 8px; cursor: pointer; font-size: 14px;
|
|
5441
6528
|
}
|
|
@@ -5444,7 +6531,7 @@ refresh();
|
|
|
5444
6531
|
.ax-pj__search input {
|
|
5445
6532
|
width: 100%; font: inherit; font-size: 12px;
|
|
5446
6533
|
padding: 6px 8px; border: 1px solid var(--ax-border);
|
|
5447
|
-
border-radius: 4px; background: var(--ax-bg); color: var(--ax-
|
|
6534
|
+
border-radius: 4px; background: var(--ax-bg); color: var(--ax-text);
|
|
5448
6535
|
}
|
|
5449
6536
|
.ax-pj__cards {
|
|
5450
6537
|
list-style: none; margin: 0; padding: 0;
|
|
@@ -5459,7 +6546,7 @@ refresh();
|
|
|
5459
6546
|
.ax-pj__card-title { font-weight: 500; font-size: 13px; margin-bottom: 4px; }
|
|
5460
6547
|
.ax-pj__card-meta {
|
|
5461
6548
|
display: flex; gap: 6px; flex-wrap: wrap;
|
|
5462
|
-
font-size: 11px; color: var(--ax-fg-muted, var(--ax-
|
|
6549
|
+
font-size: 11px; color: var(--ax-fg-muted, var(--ax-text));
|
|
5463
6550
|
}
|
|
5464
6551
|
.ax-pj__card-meta .stat { padding: 1px 6px; border-radius: 3px; background: var(--ax-bg); border: 1px solid var(--ax-border); }
|
|
5465
6552
|
.ax-pj__card-meta .stat.zero { opacity: 0.4; }
|
|
@@ -5480,11 +6567,11 @@ refresh();
|
|
|
5480
6567
|
.ax-pj__kind--github { color: #c9d1d9; background: rgba(110, 118, 129, 0.2); border-color: rgba(110, 118, 129, 0.4); }
|
|
5481
6568
|
.ax-pj__kind--jira { color: #2684ff; background: rgba(38, 132, 255, 0.1); border-color: rgba(38, 132, 255, 0.3); }
|
|
5482
6569
|
.ax-pj__kind--linear { color: #5e6ad2; background: rgba(94, 106, 210, 0.1); border-color: rgba(94, 106, 210, 0.3); }
|
|
5483
|
-
.ax-pj__kind--other { color: var(--ax-fg-muted, var(--ax-
|
|
5484
|
-
.ax-pj__keyhint { font-size: 12px; font-weight: normal; color: var(--ax-fg-muted, var(--ax-
|
|
6570
|
+
.ax-pj__kind--other { color: var(--ax-fg-muted, var(--ax-text)); background: var(--ax-bg); border-color: var(--ax-border); }
|
|
6571
|
+
.ax-pj__keyhint { font-size: 12px; font-weight: normal; color: var(--ax-fg-muted, var(--ax-text)); font-family: var(--ax-mono, monospace); }
|
|
5485
6572
|
.ax-pj__home {
|
|
5486
6573
|
font-size: 12px; text-decoration: none; padding: 2px 6px;
|
|
5487
|
-
color: var(--ax-fg-muted, var(--ax-
|
|
6574
|
+
color: var(--ax-fg-muted, var(--ax-text)); border: 1px solid var(--ax-border);
|
|
5488
6575
|
border-radius: 3px;
|
|
5489
6576
|
}
|
|
5490
6577
|
.ax-pj__home:hover { color: var(--ax-accent); border-color: var(--ax-accent); }
|
|
@@ -5494,7 +6581,7 @@ refresh();
|
|
|
5494
6581
|
.ax-pj__btn {
|
|
5495
6582
|
font: inherit; font-size: 11px;
|
|
5496
6583
|
padding: 3px 8px; border: 1px solid var(--ax-border);
|
|
5497
|
-
border-radius: 3px; background: var(--ax-bg); color: var(--ax-
|
|
6584
|
+
border-radius: 3px; background: var(--ax-bg); color: var(--ax-text);
|
|
5498
6585
|
cursor: pointer; text-transform: none; letter-spacing: 0;
|
|
5499
6586
|
margin-left: auto;
|
|
5500
6587
|
}
|
|
@@ -5502,7 +6589,7 @@ refresh();
|
|
|
5502
6589
|
.ax-pj__unlink {
|
|
5503
6590
|
margin-left: auto;
|
|
5504
6591
|
background: transparent; border: 1px solid transparent;
|
|
5505
|
-
color: var(--ax-fg-muted, var(--ax-
|
|
6592
|
+
color: var(--ax-fg-muted, var(--ax-text));
|
|
5506
6593
|
cursor: pointer; font-size: 14px; padding: 0 6px; border-radius: 3px;
|
|
5507
6594
|
}
|
|
5508
6595
|
.ax-pj__unlink:hover { color: var(--ax-err, #ef4444); border-color: var(--ax-err, #ef4444); }
|
|
@@ -5525,7 +6612,7 @@ refresh();
|
|
|
5525
6612
|
.ax-pj__modal-search input {
|
|
5526
6613
|
width: 100%; font: inherit; font-size: 13px;
|
|
5527
6614
|
padding: 6px 10px; border: 1px solid var(--ax-border);
|
|
5528
|
-
border-radius: 4px; background: var(--ax-bg); color: var(--ax-
|
|
6615
|
+
border-radius: 4px; background: var(--ax-bg); color: var(--ax-text);
|
|
5529
6616
|
margin-bottom: 12px;
|
|
5530
6617
|
}
|
|
5531
6618
|
.ax-pj__pick {
|
|
@@ -5535,7 +6622,7 @@ refresh();
|
|
|
5535
6622
|
}
|
|
5536
6623
|
.ax-pj__pick:hover { background: var(--ax-bg); border-color: var(--ax-border); }
|
|
5537
6624
|
.ax-pj__pick .pname { font-weight: 500; flex: 1; }
|
|
5538
|
-
.ax-pj__pick .pmeta { font-size: 11px; color: var(--ax-fg-muted, var(--ax-
|
|
6625
|
+
.ax-pj__pick .pmeta { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); }
|
|
5539
6626
|
.ax-pj__pick .ptag {
|
|
5540
6627
|
font-size: 11px; padding: 1px 6px; border-radius: 3px;
|
|
5541
6628
|
background: var(--ax-warn, #facc15); color: #1a1a1a;
|
|
@@ -5543,13 +6630,13 @@ refresh();
|
|
|
5543
6630
|
/* Form fields */
|
|
5544
6631
|
.ax-pj__form { display: flex; flex-direction: column; gap: 12px; }
|
|
5545
6632
|
.ax-pj__fld { display: flex; flex-direction: column; gap: 4px; }
|
|
5546
|
-
.ax-pj__fld-label { font-size: 12px; font-weight: 500; color: var(--ax-fg-muted, var(--ax-
|
|
6633
|
+
.ax-pj__fld-label { font-size: 12px; font-weight: 500; color: var(--ax-fg-muted, var(--ax-text)); }
|
|
5547
6634
|
.ax-pj__fld input, .ax-pj__fld select {
|
|
5548
6635
|
font: inherit; font-size: 13px;
|
|
5549
6636
|
padding: 6px 10px; border: 1px solid var(--ax-border);
|
|
5550
|
-
border-radius: 4px; background: var(--ax-bg); color: var(--ax-
|
|
6637
|
+
border-radius: 4px; background: var(--ax-bg); color: var(--ax-text);
|
|
5551
6638
|
}
|
|
5552
|
-
.ax-pj__fld-hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-
|
|
6639
|
+
.ax-pj__fld-hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); }
|
|
5553
6640
|
.ax-pj__form-actions {
|
|
5554
6641
|
display: flex; gap: 8px; align-items: center;
|
|
5555
6642
|
margin-top: 8px; padding-top: 14px;
|
|
@@ -5565,7 +6652,7 @@ refresh();
|
|
|
5565
6652
|
.ax-pj__fld textarea {
|
|
5566
6653
|
font: inherit; font-family: var(--ax-mono, monospace); font-size: 12px;
|
|
5567
6654
|
padding: 6px 10px; border: 1px solid var(--ax-border);
|
|
5568
|
-
border-radius: 4px; background: var(--ax-bg); color: var(--ax-
|
|
6655
|
+
border-radius: 4px; background: var(--ax-bg); color: var(--ax-text);
|
|
5569
6656
|
resize: vertical;
|
|
5570
6657
|
}
|
|
5571
6658
|
.ax-pj__clause {
|
|
@@ -5587,7 +6674,7 @@ refresh();
|
|
|
5587
6674
|
}
|
|
5588
6675
|
.ax-pj__section h3 {
|
|
5589
6676
|
font-size: 13px; text-transform: uppercase; letter-spacing: 0.6px;
|
|
5590
|
-
color: var(--ax-fg-muted, var(--ax-
|
|
6677
|
+
color: var(--ax-fg-muted, var(--ax-text)); margin: 0 0 10px 0;
|
|
5591
6678
|
}
|
|
5592
6679
|
.ax-pj__row {
|
|
5593
6680
|
display: flex; align-items: center; gap: 10px;
|
|
@@ -5595,15 +6682,15 @@ refresh();
|
|
|
5595
6682
|
border-radius: 4px; margin-bottom: 6px; background: var(--ax-bg);
|
|
5596
6683
|
}
|
|
5597
6684
|
.ax-pj__row .name { font-weight: 500; }
|
|
5598
|
-
.ax-pj__row .meta { font-size: 11px; color: var(--ax-fg-muted, var(--ax-
|
|
6685
|
+
.ax-pj__row .meta { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); }
|
|
5599
6686
|
.ax-pj__row a { color: var(--ax-accent); text-decoration: none; }
|
|
5600
6687
|
.ax-pj__row a:hover { text-decoration: underline; }
|
|
5601
6688
|
.ax-pj__empty, .ax-pj__warn {
|
|
5602
|
-
padding: 18px; font-size: 12px; color: var(--ax-fg-muted, var(--ax-
|
|
6689
|
+
padding: 18px; font-size: 12px; color: var(--ax-fg-muted, var(--ax-text));
|
|
5603
6690
|
}
|
|
5604
6691
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
5605
|
-
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-
|
|
5606
|
-
`,
|
|
6692
|
+
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
6693
|
+
`,co=`
|
|
5607
6694
|
(function(){
|
|
5608
6695
|
const $ = (sel) => document.querySelector(sel);
|
|
5609
6696
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -5972,7 +7059,7 @@ refresh();
|
|
|
5972
7059
|
// \u2500\u2500 Contact add/remove \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5973
7060
|
async function addContact(projectKey) {
|
|
5974
7061
|
const cid = prompt("Contact id to link to '" + projectKey + "':\\n\\n"
|
|
5975
|
-
+ "Use the id from .agentx/contacts.json (e.g. '
|
|
7062
|
+
+ "Use the id from .agentx/contacts.json (e.g. 'alex', 'jordan').");
|
|
5976
7063
|
if (!cid) return;
|
|
5977
7064
|
try {
|
|
5978
7065
|
await postJson("/api/admin/projects/contacts/link", { projectKey, contactId: cid.trim() });
|
|
@@ -6253,7 +7340,7 @@ refresh();
|
|
|
6253
7340
|
load();
|
|
6254
7341
|
});
|
|
6255
7342
|
})();
|
|
6256
|
-
`;import{resolve as
|
|
7343
|
+
`;import{resolve as nt,join as uo}from"path";import{existsSync as rt,readdirSync as mo,readFileSync as ho}from"fs";import go from"better-sqlite3";function ba(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:po,scripts:`<script src="${je("activity-graph.global.js")}" defer></script>`,noMain:!0})}var po=`
|
|
6257
7344
|
html, body { height: 100%; }
|
|
6258
7345
|
body { margin: 0; }
|
|
6259
7346
|
#ax-fleet-root { height: calc(100vh - 48px); }
|
|
@@ -6265,31 +7352,31 @@ body { margin: 0; }
|
|
|
6265
7352
|
font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
6266
7353
|
text-align: center;
|
|
6267
7354
|
}
|
|
6268
|
-
`;function
|
|
7355
|
+
`;function Re(){let t=nt(process.cwd(),".agentx/intent/ledger.sqlite");if(!rt(t))return null;try{let e=new go(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ya>6e4&&(ya=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ya=0;function ne(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function _a(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ba({peers:a}))}var ge={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 fo(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in ge)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in ge)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in ge)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 ge)return s}return"workflow"}return t}function xo(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function vo(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 Ea(t,e,a){return _t(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function bo(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 i=o.slice(6);if(i&&!at(i))return{id:i,name:i,avatar:B(i),kind:"a2a"}}let l=o||r||s;if(l&&!at(r||o||"")){let i=r||o||s,c=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":"mesh";return{id:i,name:o||r||i,avatar:B(l),kind:c}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,l=typeof s.username=="string"?s.username:null,i=typeof s.name=="string"?s.name:null,c=l||(s.id!=null?String(s.id):null)||i;if(c&&!at(l||i||"")){let u=typeof n.channel=="string"?n.channel:"",m=wa(u);return{id:c,name:i||l||c,avatar:B(i||l||c),kind:m}}}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,c=s.name||s.username;return{id:i,name:c,avatar:B(c),kind:"gitlab"}}let l=o.sender;if(l?.login)return{id:l.login,name:l.login,avatar:B(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:B(l),kind:wa(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 wa(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function at(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function 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 Sa(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
7356
|
${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
|
|
7357
|
+
${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 yo(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 ot(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
6271
7358
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
6272
7359
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
6273
|
-
`).all(r),s=new Map,
|
|
7360
|
+
`).all(r),s=new Map,l=new Map;if(o.length>0){let h=o.map(w=>w.id),y=h.map((w,j)=>`@id${j}`).join(","),k=Object.fromEntries(h.map((w,j)=>[`id${j}`,w])),$=t.prepare(`
|
|
6274
7361
|
SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
|
|
6275
|
-
FROM intent_decisions WHERE event_id IN (${
|
|
6276
|
-
`).all(
|
|
7362
|
+
FROM intent_decisions WHERE event_id IN (${y}) ORDER BY decided_at ASC
|
|
7363
|
+
`).all(k);for(let w of $)s.has(w.event_id)||s.set(w.event_id,[]),s.get(w.event_id).push(w);let A=t.prepare(`
|
|
6277
7364
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
6278
|
-
FROM intent_resolutions WHERE decision_event_id IN (${
|
|
6279
|
-
`).all(
|
|
7365
|
+
FROM intent_resolutions WHERE decision_event_id IN (${y})
|
|
7366
|
+
`).all(k);for(let w of A)l.set(`${w.decision_event_id}|${w.decision_decided_by}`,w)}let i=new Map,c=new Map,u=new Map,m=new Map,x=[],b=e?.business?.projects??[],_=e?.business?.contactMap??[],M=Ue(e?.business??{});for(let h of o){let y=null;try{y=JSON.parse(h.raw_json)}catch{}let k=Ea(h.source,y,_),$=null,A=null;k?($=k.client,A=k.project||`${k.client}/_chat`):h.project&&($=qe(h.project,b),A=h.project);let w=fo(h.source,h.intent||"",y),j=ge[w]||{label:w,color:"#6b7280"};u.has(w)||u.set(w,{id:w,label:j.label,color:j.color});let L="__system",D,H=bo(h.source,h.intent||"",y);if(H){L=H.id,D=H.kind;let R=k?.displayName||H.name;(!m.has(H.id)||k?.displayName)&&m.set(H.id,{id:H.id,name:R,avatar:B(R),kind:H.kind})}else m.has("__system")||m.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let Z=Sa(h.source,y);for(let R of s.get(h.id)??[]){if(R.outcome!=="dispatched"||!R.agent_id)continue;let J=`${h.id}|${R.decided_by}`,oe=l.get(J),q=R.decided_at,W=oe?.resolved_at??null,U=W===null,ln=oe?.duration_ms??(U?n-q:0),dn=U?"active":oe?.status==="error"||oe?.status==="fail"?"error":"completed",F,xe;if($)F=$,xe=A;else{let He=M.get(R.agent_id);He?(F=He,xe=`${He}/_${h.source}`):(F="unmapped",xe=`unmapped/_${h.source}`)}i.has(F)||i.set(F,{id:F,name:F,color:xo(F),projects:[]}),c.has(F)||c.set(F,new Set),c.get(F).add(xe),x.push({id:`${h.id}|${R.decided_by}`,agentId:R.agent_id,clientId:F,projectId:xe,channelId:w,initiatorId:L,initiatorKind:D,subject:yo(h.subject),intent:h.intent||"",startedAt:q,resolvedAt:W,duration:ln,active:U,outcome:dn,tokens:0,inputPreview:Z,system:vo(R.agent_id,e)})}}let E=[...i.values()].map(h=>({...h,projects:[...c.get(h.id)||[]].sort()})).sort((h,y)=>h.id.localeCompare(y.id)),S=[],d=new Set;if(e)for(let[h,y]of Object.entries(e.agents||{})){let k={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||""};S.push(k),d.add(h)}for(let h of x)d.has(h.agentId)||(S.push({id:h.agentId,name:h.agentId,tier:"worker",model:"",role:""}),d.add(h.agentId));S.sort((h,y)=>h.id.localeCompare(y.id));let p=[],g=new Set;for(let[h,y]of Object.entries(ge))p.push({id:h,label:y.label,color:y.color}),g.add(h);for(let h of u.values())g.has(h.id)||p.push(h);let f=[...m.values()];return f.find(h=>h.id==="__system")||f.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"}),{now:n,windowH:a,clients:E,agents:S,channels:p,initiators:f,dispatches:x}}function Ta(t){let e=Re();if(!e)return null;try{return ot(e.db,ce,t)}finally{e.close()}}function Ca(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,l=0;for(let{nodeId:i,snap:c}of t){c.now>s&&(s=c.now),c.windowH>l&&(l=c.windowH);for(let u of c.clients){let m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let x=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:x})}}for(let u of c.agents)a.has(u.id)||a.set(u.id,u);for(let u of c.channels)n.has(u.id)||n.set(u.id,u);for(let u of c.initiators)r.has(u.id)||r.set(u.id,u);for(let u of c.dispatches)o.push({...u,nodeId:i,id:`${i}::${u.id}`})}return{now:s||Date.now(),windowH:l||6,clients:[...e.values()].sort((i,c)=>i.id.localeCompare(c.id)),agents:[...a.values()].sort((i,c)=>i.id.localeCompare(c.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((i,c)=>c.startedAt-i.startedAt)}}var ce=null;function Aa(t){ce=t}async function Ma(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Re();if(!n)return ne(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=$a(parseInt(r.searchParams.get("hours")||"6",10));ne(e,200,ot(n.db,ce,o))}catch(r){ne(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var wo=5e3;async function Ia(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
7367
|
|
|
6281
|
-
`);let n=new URL(t.url||"/","http://_"),r
|
|
7368
|
+
`);let n=new URL(t.url||"/","http://_"),r=$a(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
|
|
6282
7369
|
|
|
6283
|
-
`)}catch{s()}},25e3);try{for(;!o;){let
|
|
6284
|
-
`),e.write(`data: ${JSON.stringify(
|
|
7370
|
+
`)}catch{s()}},25e3);try{for(;!o;){let i=Re();if(i)try{let u=ot(i.db,ce,r);e.write(`event: snapshot
|
|
7371
|
+
`),e.write(`data: ${JSON.stringify(u)}
|
|
6285
7372
|
|
|
6286
|
-
`)}catch(
|
|
6287
|
-
data: ${JSON.stringify({error:
|
|
7373
|
+
`)}catch(u){e.write(`event: error
|
|
7374
|
+
data: ${JSON.stringify({error:u?.message??String(u)})}
|
|
6288
7375
|
|
|
6289
|
-
`)}finally{
|
|
7376
|
+
`)}finally{i.close()}else e.write(`event: error
|
|
6290
7377
|
data: ${JSON.stringify({error:"ledger not available"})}
|
|
6291
7378
|
|
|
6292
|
-
`);let
|
|
7379
|
+
`);let c=Date.now();for(;!o&&Date.now()-c<wo;)await new Promise(u=>setTimeout(u,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function $a(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function ko(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=nt(process.cwd(),".agentx/task-history",t,n);if(!rt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=nt(process.cwd(),".agentx/task-history",t,o);return rt(s)?ka(s,e,a):null}return ka(r,e,a)}function ka(t,e,a){let n=null,r=1/0;for(let o of mo(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(ho(uo(t,o),"utf-8"))}catch{continue}let l=s.startedAt,i;if(typeof l=="number")i=l;else if(typeof l=="string"){let u=Date.parse(l);if(!Number.isFinite(u))continue;i=u}else continue;let c=Math.abs(i-e);c<r&&c<=a&&(n=s,r=c)}return n}async function ja(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 ne(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),l=r.slice(o+1),i=Re();if(!i)return ne(e,503,{error:"ledger not available"}),!0;try{let c=i.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return ne(e,404,{error:"event not found"}),!0;let u=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(!u)return ne(e,404,{error:"decision not found"}),!0;let m=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),x=null;try{x=JSON.parse(c.raw_json)}catch{}let b=Sa(c.source,x),_=x&&typeof x=="object"&&(x.text||x.message?.text||x.message?.caption||x.object_attributes?.note||x.object_attributes?.description||x.comment?.body||x.issue?.body||(typeof x.message=="string"?x.message:null)||(typeof x.prompt=="string"?x.prompt:null)||null)||b,M=null,E=null;if(u.agent_id){let h=ko(u.agent_id,u.decided_at);if(h){typeof h.responseText=="string"&&(M=h.responseText);let y=h.transcript;Array.isArray(y)&&(E=y.length)}}let S=ce?.business?.projects??[],d=ce?.business?.contactMap??[],p=Ue(ce?.business??{}),g={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},f=Ea(c.source,x,d);if(f)g={client:f.client,project:f.project||`${f.client}/_chat`,via:`contactMap (channel=${f.channel??"*"}${f.username?` username=${f.username}`:""}${f.chatId?` chatId=${f.chatId}`:""})`};else if(c.project)g={client:qe(c.project,S),project:c.project,via:`project namespace prefix (${c.project})`};else if(u.agent_id){let h=p.get(u.agent_id);h&&(g={client:h,project:`${h}/_${c.source}`,via:`orgChart fallback (agent ${u.agent_id} reports up to a PM whose project belongs to ${h})`})}ne(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:u.decided_by,agentId:u.agent_id,outcome:u.outcome,reason:u.reason,startedAt:u.decided_at,resolvedAt:m?.resolved_at??null,durationMs:m?.duration_ms??null,input:_,response:M,transcriptLen:E,resolutionStatus:m?.status??null,resultSummary:m?.result_summary??null,attribution:g})}catch(c){ne(e,500,{error:c?.message??String(c)})}finally{i.close()}return!0}import{existsSync as To,readFileSync as Co}from"fs";import{resolve as Ra}from"path";Ne();function La(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=_o.replace(/__AGENT_ID__/g,P(e));return C({title:`AgentX \xB7 ${P(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${P(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Eo,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>${So}</script>`})}var _o=`
|
|
6293
7380
|
<!-- Breadcrumb -->
|
|
6294
7381
|
<div class="ax-crumb">
|
|
6295
7382
|
<a href="/admin">Settings</a>
|
|
@@ -6662,7 +7749,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
6662
7749
|
</div>
|
|
6663
7750
|
<div class="ax-field">
|
|
6664
7751
|
<label class="lbl">Chat id <span class="opt">who's the person?</span></label>
|
|
6665
|
-
<input class="inp mono" id="ho-chatid" placeholder="1816212449 or +
|
|
7752
|
+
<input class="inp mono" id="ho-chatid" placeholder="1816212449 or +10000000000" />
|
|
6666
7753
|
</div>
|
|
6667
7754
|
<div class="ax-field">
|
|
6668
7755
|
<label class="lbl">Hand off to</label>
|
|
@@ -6878,7 +7965,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
6878
7965
|
</div>
|
|
6879
7966
|
</div>
|
|
6880
7967
|
</div>
|
|
6881
|
-
`,
|
|
7968
|
+
`,Eo=`
|
|
6882
7969
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
6883
7970
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
6884
7971
|
* primitives live in components.css.ts. */
|
|
@@ -6997,7 +8084,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
6997
8084
|
|
|
6998
8085
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
6999
8086
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
7000
|
-
`,
|
|
8087
|
+
`,So=`
|
|
7001
8088
|
const $ = (id) => document.getElementById(id);
|
|
7002
8089
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
7003
8090
|
|
|
@@ -7253,7 +8340,7 @@ async function loadAgent(){
|
|
|
7253
8340
|
const msg = document.getElementById('mcp-msg');
|
|
7254
8341
|
try {
|
|
7255
8342
|
await req('POST', '/api/admin/agent/' + AGENT_ID + '/mcp', body);
|
|
7256
|
-
if (msg) { msg.textContent = '\u2713 saved \u2014 agent picks it up at next daemon boot'; msg.style.color = 'var(--ax-
|
|
8343
|
+
if (msg) { msg.textContent = '\u2713 saved \u2014 agent picks it up at next daemon boot'; msg.style.color = 'var(--ax-ok)'; }
|
|
7257
8344
|
['mcp-name','mcp-command','mcp-args','mcp-env'].forEach(function(id){ document.getElementById(id).value = ''; });
|
|
7258
8345
|
await loadAgent();
|
|
7259
8346
|
} catch (e) {
|
|
@@ -7282,7 +8369,7 @@ async function loadAgent(){
|
|
|
7282
8369
|
const msg = document.getElementById('cap-msg');
|
|
7283
8370
|
try {
|
|
7284
8371
|
await req('PATCH', '/api/admin/agent/' + AGENT_ID + '/capability', body);
|
|
7285
|
-
if (msg) { msg.textContent = '\u2713 saved \u2014 restart the daemon for changes to take effect'; msg.style.color = 'var(--ax-
|
|
8372
|
+
if (msg) { msg.textContent = '\u2713 saved \u2014 restart the daemon for changes to take effect'; msg.style.color = 'var(--ax-ok)'; }
|
|
7286
8373
|
await loadAgent();
|
|
7287
8374
|
} catch (e) {
|
|
7288
8375
|
if (msg) { msg.textContent = e.message; msg.style.color = 'var(--ax-err)'; }
|
|
@@ -7786,7 +8873,7 @@ async function dispatchTd(text) {
|
|
|
7786
8873
|
appendTdTyping();
|
|
7787
8874
|
const t0 = Date.now();
|
|
7788
8875
|
try {
|
|
7789
|
-
// Use /chat endpoint so test-drive exercises the same path as
|
|
8876
|
+
// Use /chat endpoint so test-drive exercises the same path as example.com.
|
|
7790
8877
|
// Falls back to /task reply shape if /chat isn't reachable (no auth configured).
|
|
7791
8878
|
let reply, queuedTask;
|
|
7792
8879
|
try {
|
|
@@ -7851,15 +8938,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
7851
8938
|
/* ===== Boot ===== */
|
|
7852
8939
|
initOptsToggles();
|
|
7853
8940
|
loadAgent();
|
|
7854
|
-
`;function
|
|
7855
|
-
`);return
|
|
7856
|
-
`);return
|
|
8941
|
+
`;function Pa(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(La({agentId:a,peers:n,localToken:r}))}async function Da(t,e,a){try{let n=t.method==="GET"?void 0:await Jo(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){Pe(e,404,{error:`unknown agent endpoint: ${a}`});return}let l=s[1],i=s[2]||"",c=`${t.method} ${i}`,m={"GET ":()=>we(l),"PATCH ":()=>Ao(l,n),"PATCH capability":()=>$o(l,n),"POST mcp":()=>Mo(l,n),"DELETE mcp":()=>Io(l,n),"GET identity":()=>jo(l),"GET identity/file":()=>Lo(l,String(o.path||"")),"PUT identity/file":()=>Ro(l,n),"GET skills":()=>Po(l),"POST skills":()=>Do(l,n),"DELETE skills":()=>Oo(l,n),"GET skills/tree":()=>Ho(l,String(o.slug||"")),"GET skills/file":()=>No(l,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Bo(l,n),"GET skills/deps":()=>zo(l,String(o.slug||"")),"POST skills/install":()=>qo(l,n,t),"POST skills/deps":()=>Uo(l,n,t),"GET channels":()=>Fo(l),"GET activity":()=>Wo(l,t),"GET handovers":()=>Go(l),"POST handovers":()=>Xo(l,n),"DELETE handovers":()=>Ko(n)}[c];if(!m){Pe(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let x=await m();Pe(e,200,x)}catch(n){Pe(e,400,{error:n?.message||"agent op failed"})}}function Oa(){let t=Ra(process.cwd(),"agentx.json");return To(t)?JSON.parse(Co(t,"utf-8")):null}function z(t){let e=Oa();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 we(t){let{def:e,cfg:a}=z(t),n=e.workspace?ue(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 Ao(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}=T(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:we(t)}}function Mo(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}=T(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:we(t)}}function Io(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=T(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:we(t)}}function $o(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}=T(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:we(t)}}function jo(t){let{def:e}=z(t);return ue(e.workspace)}function Lo(t,e){if(!e)throw new Error("path query param required");let{def:a}=z(t);return _e(a.workspace,e)}function Ro(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=z(t);return Ee(n.workspace,a,String(e?.content??""))}function Po(t){let{def:e}=z(t),a=ue(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Do(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=z(t);return Se(n.workspace,a,{title:e?.title,content:e?.content})}function Oo(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=z(t);return Te(n.workspace,a)}function Ho(t,e){if(!e)throw new Error("slug query param required");let{def:a}=z(t),n=Ct(a.workspace,e),r=Ce(a.workspace,e);return{slug:e,tree:n,deps:r}}function No(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=z(t);return At(n.workspace,e,a)}function Bo(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 Mt(r.workspace,a,n,String(e?.content??""))}function zo(t,e){if(!e)throw new Error("slug query param required");let{def:a}=z(t);return Ce(a.workspace,e)}async function qo(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=Ha(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(`
|
|
8942
|
+
`);return Na(a,r,s,`install-${n}:${Date.now()}`)}async function Uo(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Ha(e?.worker),{def:o}=z(t),s=Ce(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=Ra(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(`
|
|
8943
|
+
`);return Na(a,r,i,`deps-${t}-${n}:${Date.now()}`)}function Ha(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 Na(t,e,a,n){let r=G(),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}})}),c=await i.text(),u;try{u=JSON.parse(c)}catch{u={content:c}}if(!i.ok)throw new Error(u?.error||`daemon /task HTTP ${i.status}`);return{worker:e,taskId:u?.taskId,content:u?.content,duration:u?.duration,error:u?.error}}function Fo(t){let e=Oa(),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 Wo(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(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 st(){return new ft}function Go(t){let e=st(),{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,l=e?.summary?String(e.summary):void 0,i=e?.expiresAt?String(e.expiresAt):void 0,c=st().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:c}}function Ko(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:st().remove(e,a,n)?"Released":"No active handover for that chat"}}function Pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Jo(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 pe={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 Ba=[{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 it(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(pe)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
7857
8944
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
7858
8945
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
7859
8946
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
7860
8947
|
<main id="grid" class="ax-live__body"></main>
|
|
7861
8948
|
</div>
|
|
7862
|
-
`;return
|
|
8949
|
+
`;return C({title:`${pe.brand} \xB7 ${pe.subtitle}`,activeTab:"live",subtitle:pe.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Vo,scripts:e+`<script>${Yo}</script>`,headExtras:`<script>
|
|
7863
8950
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
7864
8951
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
7865
8952
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -7870,7 +8957,7 @@ loadAgent();
|
|
|
7870
8957
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
7871
8958
|
right.insertBefore(extras, right.firstChild);
|
|
7872
8959
|
});
|
|
7873
|
-
</script>`})}var
|
|
8960
|
+
</script>`})}var Vo=`
|
|
7874
8961
|
/* --- Page frame --- */
|
|
7875
8962
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
7876
8963
|
|
|
@@ -8071,7 +9158,7 @@ loadAgent();
|
|
|
8071
9158
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
8072
9159
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
8073
9160
|
}
|
|
8074
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
9161
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,Yo=`
|
|
8075
9162
|
'use strict';
|
|
8076
9163
|
|
|
8077
9164
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -8322,7 +9409,7 @@ function renderAgent(a, node) {
|
|
|
8322
9409
|
// The page's job is "who is alive and what are they doing RIGHT NOW". Giving
|
|
8323
9410
|
// an idle agent the same real estate as a working one \u2014 model, last-reply
|
|
8324
9411
|
// excerpt, footer \u2014 is exactly backwards: it makes the answer harder to see
|
|
8325
|
-
// the more agents you run. On
|
|
9412
|
+
// the more agents you run. On peer (22 agents) the busy ones were lost in a
|
|
8326
9413
|
// wall of identical idle cards.
|
|
8327
9414
|
//
|
|
8328
9415
|
// Collapsed still carries what the question needs: who, engine, and when it
|
|
@@ -8543,7 +9630,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
8543
9630
|
});
|
|
8544
9631
|
}
|
|
8545
9632
|
|
|
8546
|
-
`;var
|
|
9633
|
+
`;var za=`
|
|
8547
9634
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
8548
9635
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
8549
9636
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -8713,7 +9800,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
8713
9800
|
.mx-summary{max-width:56vw}
|
|
8714
9801
|
}
|
|
8715
9802
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
8716
|
-
`;var
|
|
9803
|
+
`;var qa=`<script>
|
|
8717
9804
|
window.MX=(function(){
|
|
8718
9805
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
8719
9806
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -8822,7 +9909,7 @@ window.MX=(function(){
|
|
|
8822
9909
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
8823
9910
|
setHealth:setHealth,get:get};
|
|
8824
9911
|
})();
|
|
8825
|
-
</script>`;var
|
|
9912
|
+
</script>`;var Ua=`<script>
|
|
8826
9913
|
window.MXD=(function(){
|
|
8827
9914
|
function el(id){return document.getElementById(id)}
|
|
8828
9915
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -9036,7 +10123,7 @@ window.MXD=(function(){
|
|
|
9036
10123
|
|
|
9037
10124
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
9038
10125
|
})();
|
|
9039
|
-
</script>`;var
|
|
10126
|
+
</script>`;var Fa=`<script>
|
|
9040
10127
|
(function(){
|
|
9041
10128
|
var LANES=[
|
|
9042
10129
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -9352,7 +10439,7 @@ window.MXD=(function(){
|
|
|
9352
10439
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
9353
10440
|
load();
|
|
9354
10441
|
})();
|
|
9355
|
-
</script>`;var
|
|
10442
|
+
</script>`;var Wa=`<script>
|
|
9356
10443
|
(function(){
|
|
9357
10444
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
9358
10445
|
var esc=MX.esc;
|
|
@@ -9499,17 +10586,17 @@ window.MXD=(function(){
|
|
|
9499
10586
|
}
|
|
9500
10587
|
load();setInterval(load,5000);
|
|
9501
10588
|
})();
|
|
9502
|
-
</script>`;var
|
|
10589
|
+
</script>`;var Y={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 Q(t,e,a,n,r=""){return N({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Qo=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Zo=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Ga(t){let e=Ae({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Me([{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
10590
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
9504
|
-
${
|
|
10591
|
+
${Qo.map((l,i)=>`<button class="mx-tab" type="button" role="tab" id="mx-tab-${l.id}" aria-controls="mx-view-${l.id}" aria-selected="${i===0}" data-view="${l.id}">${l.label}</button>`).join("")}
|
|
9505
10592
|
</div>
|
|
9506
10593
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
9507
|
-
${
|
|
10594
|
+
${Zo.map(l=>`<button type="button" data-days="${l.days}" aria-pressed="${l.days===30}">${l.label}</button>`).join("")}
|
|
9508
10595
|
</div>
|
|
9509
10596
|
</div>
|
|
9510
10597
|
<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
10598
|
<section class="mx-section" aria-labelledby="mx-lanes-title">
|
|
9512
|
-
${Y
|
|
10599
|
+
${Q(Y.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
10600
|
<div id="mx-lanes"><div class="mx-empty">Loading activity...</div></div>
|
|
9514
10601
|
<div class="mx-axis" id="mx-axis"></div>
|
|
9515
10602
|
<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>
|
|
@@ -9517,32 +10604,32 @@ window.MXD=(function(){
|
|
|
9517
10604
|
|
|
9518
10605
|
<div class="mx-two">
|
|
9519
10606
|
<section class="mx-section" aria-labelledby="mx-origins-title">
|
|
9520
|
-
${Y
|
|
10607
|
+
${Q(Y.breakage,"Where it breaks","Attempts per origin, with the failed share marked on the same bar.","mx-origins-title")}
|
|
9521
10608
|
<div class="mx-bars" id="mx-origins"><div class="mx-empty">Loading...</div></div>
|
|
9522
10609
|
</section>
|
|
9523
10610
|
<section class="mx-section" aria-labelledby="mx-causes-title">
|
|
9524
|
-
${Y
|
|
10611
|
+
${Q(Y.breakage,"Why it fails","Failures grouped by cause class, matched from the recorded error text.","mx-causes-title")}
|
|
9525
10612
|
<div class="mx-bars" id="mx-causes"><div class="mx-empty">Loading...</div></div>
|
|
9526
10613
|
<p class="mx-note" id="mx-cause-note"></p>
|
|
9527
10614
|
</section>
|
|
9528
10615
|
</div>
|
|
9529
10616
|
|
|
9530
10617
|
<section class="mx-section" aria-labelledby="mx-scatter-title">
|
|
9531
|
-
${Y
|
|
10618
|
+
${Q(Y.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
10619
|
<div class="mx-scatter" id="mx-scatter"><div class="mx-empty">Loading jobs...</div></div>
|
|
9533
10620
|
<div class="mx-legend" id="mx-scatter-legend"></div>
|
|
9534
10621
|
<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>
|
|
9535
10622
|
</section>
|
|
9536
10623
|
</div>`,r=`<div class="mx-view" id="mx-view-lifetime" role="tabpanel" aria-labelledby="mx-tab-lifetime" hidden>
|
|
9537
10624
|
<section class="mx-section" aria-labelledby="mx-threads-title">
|
|
9538
|
-
${Y
|
|
10625
|
+
${Q(Y.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
10626
|
<div class="mx-chips" id="mx-thread-chips"></div>
|
|
9540
10627
|
<div id="mx-threads"><div class="mx-empty">Loading threads...</div></div>
|
|
9541
10628
|
<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>
|
|
9542
10629
|
</section>
|
|
9543
10630
|
|
|
9544
10631
|
<section class="mx-section" aria-labelledby="mx-rot-title">
|
|
9545
|
-
${Y
|
|
10632
|
+
${Q(Y.cuts,"Session cuts","Why threads lost their session, across the fleet.","mx-rot-title")}
|
|
9546
10633
|
<div class="mx-bars" id="mx-rotations"><div class="mx-empty">Loading...</div></div>
|
|
9547
10634
|
<p class="mx-note" id="mx-rot-note"></p>
|
|
9548
10635
|
</section>
|
|
@@ -9550,23 +10637,23 @@ window.MXD=(function(){
|
|
|
9550
10637
|
<p id="mx-updated" class="mx-updated" aria-live="polite">Connecting to the fleet...</p>
|
|
9551
10638
|
|
|
9552
10639
|
<section class="mx-section" aria-labelledby="mx-auto-title">
|
|
9553
|
-
${Y
|
|
10640
|
+
${Q(Y.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
10641
|
<div class="ax-stack" id="mx-runs"><div class="mx-empty">Loading schedules...</div></div>
|
|
9555
10642
|
</section>
|
|
9556
10643
|
|
|
9557
10644
|
<div class="mx-columns">
|
|
9558
10645
|
<section class="mx-section" aria-labelledby="mx-active-title">
|
|
9559
|
-
${Y
|
|
10646
|
+
${Q(Y.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
10647
|
<div class="ax-stack" id="mx-active"><div class="mx-empty">No activity loaded.</div></div>
|
|
9561
10648
|
</section>
|
|
9562
10649
|
<section class="mx-section" aria-labelledby="mx-nodes-title">
|
|
9563
|
-
${Y
|
|
10650
|
+
${Q(Y.nodes,"Nodes","Reachability and capacity across the fleet.","mx-nodes-title",'<span class="ax-tab-count" id="mx-node-count">0 nodes</span>')}
|
|
9564
10651
|
<div class="ax-stack" id="mx-nodes"><div class="mx-empty">No nodes loaded.</div></div>
|
|
9565
10652
|
</section>
|
|
9566
10653
|
</div>
|
|
9567
10654
|
|
|
9568
10655
|
<section class="mx-section" aria-labelledby="mx-agents-title">
|
|
9569
|
-
${Y
|
|
10656
|
+
${Q(Y.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
10657
|
<div class="mx-agent-grid" id="mx-agents"><div class="mx-empty">No agents loaded.</div></div>
|
|
9571
10658
|
</section>
|
|
9572
10659
|
</div>`,s=`${e}<main class="mx-content">
|
|
@@ -9582,7 +10669,7 @@ window.MXD=(function(){
|
|
|
9582
10669
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
9583
10670
|
</header>
|
|
9584
10671
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
9585
|
-
</aside>`;return
|
|
10672
|
+
</aside>`;return C({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:za,scripts:qa+es+Ua+Fa+Wa})}var es=`<script>
|
|
9586
10673
|
(function(){
|
|
9587
10674
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
9588
10675
|
var range=document.getElementById('mx-range');
|
|
@@ -9610,7 +10697,7 @@ window.MXD=(function(){
|
|
|
9610
10697
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
9611
10698
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
9612
10699
|
})();
|
|
9613
|
-
</script>`;async function
|
|
10700
|
+
</script>`;async function Xa(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 l=>{let i={Accept:"application/json"};l.token&&(i.Authorization=`Bearer ${l.token}`);try{let c=await fetch(l.url+"/analytics/mesh"+o,{headers:i,signal:n.signal});return c.ok?{node:l,data:await c.json()}:{node:l,error:`HTTP ${c.status}`}}catch(c){return{node:l,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return ts(s,e.days)}function ts(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,l=[],i=[],c=0,u=0,m=0,x=0,b=0,_=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 d of S.days){let p=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let g of["cron","workflow","direct"])p[g][0]+=d[g]?.[0]||0,p[g][1]+=d[g]?.[1]||0;n.set(d.day,p)}for(let d of S.origins){let p=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};p.runs+=d.runs,p.errors+=d.errors,p.hours+=d.hours,r.set(d.channel,p)}for(let d of S.causes){let p=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};p.count+=d.count;for(let g of d.agents)p.agents.includes(g)||p.agents.push(g);p.example||(p.example=d.example),o.set(d.cause,p)}for(let d of S.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=S.rotations.total,u+=S.rotations.tokenSum||0,m+=S.rotations.tokenSamples||0,x=Math.max(x,S.rotations.maxTokens),b+=S.retention.traces,_+=S.retention.tracesWithSteps;for(let d of S.jobs)l.push({...d,node:E.name,nodeUrl:E.url});for(let d of S.threads)i.push({...d,node:E.name,nodeUrl:E.url})}let M=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:M.length?Math.min(...M):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:l.sort((E,S)=>S.hours-E.hours),threads:i.sort((E,S)=>S.lastAt-S.firstAt-(E.lastAt-E.firstAt)||S.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,S])=>({reason:E,count:S})).sort((E,S)=>S.count-E.count),tokenSum:u,tokenSamples:m,maxTokens:x},retention:{traces:b,tracesWithSteps:_}}}async function Ka(t,e,a,n){let r=a.replace(/\/+$/,""),o=e.find(l=>l.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 l=await fetch(r+n,{headers:s}),i=await l.text();t.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8"}),t.end(i)}catch(l){t.writeHead(502,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:l?.message||"upstream fetch failed"}))}}async function Ja(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 l=>{let i={Accept:"application/json"};l.token&&(i.Authorization=`Bearer ${l.token}`);try{let c=await fetch(l.url+"/analytics/day"+o,{headers:i,signal:n.signal});return c.ok?{node:l,data:await c.json()}:{node:l,error:`HTTP ${c.status}`}}catch(c){return{node:l,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return as(s,e.day)}function as(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:l}of t)if(l){a.runs+=l.totals.runs,a.errors+=l.totals.errors,a.ms+=l.totals.ms,a.inputTokens+=l.totals.inputTokens,a.outputTokens+=l.totals.outputTokens;for(let i of l.origins){let c=n.get(i.channel)||{channel:i.channel,runs:0,errors:0,ms:0};c.runs+=i.runs,c.errors+=i.errors,c.ms+=i.ms,n.set(i.channel,c)}for(let i of l.causes)r.set(i.cause,(r.get(i.cause)||0)+i.count);for(let i of l.conversations)o.push({...i,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,l)=>l.runs-s.runs),causes:[...r.entries()].map(([s,l])=>({cause:s,count:l})).sort((s,l)=>l.count-s.count),conversations:o.sort((s,l)=>l.ms-s.ms||l.turns-s.turns)}}function Va(t={}){let e=`
|
|
9614
10701
|
<select id="boardPicker" title="Switch board"></select>
|
|
9615
10702
|
<div class="search">
|
|
9616
10703
|
<span class="icon">\u2315</span>
|
|
@@ -9711,7 +10798,7 @@ window.MXD=(function(){
|
|
|
9711
10798
|
</footer>
|
|
9712
10799
|
</div>
|
|
9713
10800
|
</div>
|
|
9714
|
-
<script src="/sortable.min.js"></script>`;return
|
|
10801
|
+
<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:ns,scripts:`<script>${rs}</script>`,headExtras:`<script>
|
|
9715
10802
|
// The boards page has its own connection dot + wants body height:100%
|
|
9716
10803
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
9717
10804
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -9727,7 +10814,7 @@ window.MXD=(function(){
|
|
|
9727
10814
|
right.insertBefore(dot, right.firstChild);
|
|
9728
10815
|
}
|
|
9729
10816
|
});
|
|
9730
|
-
</script>`})}var
|
|
10817
|
+
</script>`})}var ns=`
|
|
9731
10818
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
9732
10819
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
9733
10820
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -9980,7 +11067,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
9980
11067
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
9981
11068
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
9982
11069
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
9983
|
-
`,
|
|
11070
|
+
`,rs=`
|
|
9984
11071
|
'use strict';
|
|
9985
11072
|
const state = {
|
|
9986
11073
|
boards: [], current: null, items: {},
|
|
@@ -10916,7 +12003,7 @@ const activity = {
|
|
|
10916
12003
|
};
|
|
10917
12004
|
|
|
10918
12005
|
function resolveDaemonUrl() {
|
|
10919
|
-
// Allow ?daemon=http://host:port override; fall back to localhost:18800 (MacBook) then 19900 (
|
|
12006
|
+
// Allow ?daemon=http://host:port override; fall back to localhost:18800 (MacBook) then 19900 (peer).
|
|
10920
12007
|
const q = new URLSearchParams(window.location.search).get('daemon');
|
|
10921
12008
|
if (q) return q.replace(/\\/+$/, '');
|
|
10922
12009
|
return localStorage.getItem('agentx.daemon') || 'http://localhost:18800';
|
|
@@ -11039,9 +12126,9 @@ function appendEvents(events) {
|
|
|
11039
12126
|
}
|
|
11040
12127
|
|
|
11041
12128
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
11042
|
-
`;function
|
|
12129
|
+
`;function Ya(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
11043
12130
|
<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>
|
|
11044
|
-
${
|
|
12131
|
+
${Ba.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${P(n.alias)}</span>`:"";return`<article class="term"><h3>${P(n.term)}${r}</h3><p>${P(n.definition)}</p></article>`}).join("")}`;return C({title:`${pe.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:os})}var os=`
|
|
11045
12132
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
11046
12133
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
11047
12134
|
.lead {
|
|
@@ -11071,11 +12158,12 @@ article.term .alias {
|
|
|
11071
12158
|
}
|
|
11072
12159
|
article.term p {
|
|
11073
12160
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
11074
|
-
}`;function
|
|
12161
|
+
}`;function Qa(t={}){let e=`<div class="ax-wf__root">
|
|
11075
12162
|
<aside class="ax-wf__list">
|
|
11076
12163
|
<header>
|
|
11077
12164
|
<h2>Workflows</h2>
|
|
11078
12165
|
<div class="ax-wf__header-actions">
|
|
12166
|
+
<a id="wf-new" class="ax-wf__icon" href="/workflows/editor?new=1" title="Build a new workflow">+</a>
|
|
11079
12167
|
<button id="wf-refresh" class="ax-wf__icon" title="Refresh (r)">\u21BB</button>
|
|
11080
12168
|
</div>
|
|
11081
12169
|
</header>
|
|
@@ -11087,16 +12175,36 @@ article.term p {
|
|
|
11087
12175
|
</div>
|
|
11088
12176
|
<ul id="wf-list" class="ax-wf__cards" aria-live="polite"></ul>
|
|
11089
12177
|
<div id="wf-empty" class="ax-wf__empty" hidden>
|
|
11090
|
-
<p>No workflows
|
|
11091
|
-
<p class="hint">
|
|
12178
|
+
<p><b>No workflows yet.</b></p>
|
|
12179
|
+
<p class="hint">A workflow watches for something — a merge request, a message, a time of day — and puts an agent on it. Ask an agent to draft one for you, or connect n8n below and let it hand work over.</p>
|
|
11092
12180
|
</div>
|
|
11093
|
-
<section class="ax-
|
|
11094
|
-
<header>
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
|
|
12181
|
+
<section class="ax-wf__n8n">
|
|
12182
|
+
<header><h3>Hand work over from n8n</h3></header>
|
|
12183
|
+
<p class="hint">n8n already talks to hundreds of services. Let it keep doing that, and have it call a workflow here when it needs an agent.</p>
|
|
12184
|
+
|
|
12185
|
+
<ol class="ax-wf__n8n-steps">
|
|
12186
|
+
<li>
|
|
12187
|
+
<b>Name the job.</b> Pick a short word for what n8n is handing over —
|
|
12188
|
+
<code>invoice-received</code>, <code>lead-signed-up</code>. That word is the
|
|
12189
|
+
<i>topic</i>, and it is the last part of the address below.
|
|
12190
|
+
</li>
|
|
12191
|
+
<li>
|
|
12192
|
+
<b>In n8n</b>, add an <b>HTTP Request</b> node: method <code>POST</code>, this address
|
|
12193
|
+
with your topic on the end, and send whatever JSON the workflow should read.
|
|
12194
|
+
<div class="ax-wf__n8n-url" id="wf-n8n-in">…</div>
|
|
12195
|
+
<button class="ax-wf__n8n-copy" id="wf-n8n-copy" type="button">Copy address</button>
|
|
12196
|
+
<span class="hint" id="wf-n8n-auth"></span>
|
|
12197
|
+
</li>
|
|
12198
|
+
<li>
|
|
12199
|
+
<b>Here</b>, build a workflow that starts with <b>n8n hands work over</b> and set its
|
|
12200
|
+
topic to the same word. Without that, every workflow listening for n8n runs on
|
|
12201
|
+
every call.
|
|
12202
|
+
</li>
|
|
12203
|
+
</ol>
|
|
12204
|
+
|
|
12205
|
+
<p class="hint">Going the other way is one step: add <b>Call a web address</b> and point it at an n8n webhook — or connect n8n in Settings and pick one of your n8n workflows straight from the palette.</p>
|
|
11099
12206
|
</section>
|
|
12207
|
+
|
|
11100
12208
|
</aside>
|
|
11101
12209
|
|
|
11102
12210
|
<section class="ax-wf__detail">
|
|
@@ -11127,7 +12235,7 @@ article.term p {
|
|
|
11127
12235
|
</aside>
|
|
11128
12236
|
</div>
|
|
11129
12237
|
|
|
11130
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return
|
|
12238
|
+
<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:ss,scripts:`<script>${me({workflowHealth:kt})}${is}</script>`})}var ss=`
|
|
11131
12239
|
.ax-wf__root {
|
|
11132
12240
|
display: grid;
|
|
11133
12241
|
grid-template-columns: 340px 1fr;
|
|
@@ -11171,6 +12279,52 @@ article.term p {
|
|
|
11171
12279
|
border: 1px solid var(--ax-border); border-radius: 4px;
|
|
11172
12280
|
font-family: inherit;
|
|
11173
12281
|
}
|
|
12282
|
+
.ax-wf__state {
|
|
12283
|
+
font-size: 11.5px; font-weight: 600; margin-top: 4px;
|
|
12284
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
12285
|
+
}
|
|
12286
|
+
.ax-wf__state::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: currentColor; }
|
|
12287
|
+
.ax-wf__state--dormant { color: var(--ax-red-ink); }
|
|
12288
|
+
.ax-wf__state--failing { color: var(--ax-amber-ink); }
|
|
12289
|
+
.ax-wf__state--active { color: var(--ax-green-d); }
|
|
12290
|
+
.ax-wf__state--quiet,
|
|
12291
|
+
.ax-wf__state--never { color: var(--ax-text-2); }
|
|
12292
|
+
|
|
12293
|
+
.ax-wf__n8n {
|
|
12294
|
+
border-top: var(--ax-border-w) solid var(--ax-border);
|
|
12295
|
+
padding: 14px 16px; display: flex; flex-direction: column; gap: 8px;
|
|
12296
|
+
}
|
|
12297
|
+
.ax-wf__n8n h3 { font-size: 13px; font-weight: 600; margin: 0; }
|
|
12298
|
+
.ax-wf__n8n-lbl {
|
|
12299
|
+
font-size: 10px; font-family: var(--ax-mono); text-transform: uppercase;
|
|
12300
|
+
letter-spacing: 0.06em; color: var(--ax-text-2); font-weight: 600;
|
|
12301
|
+
}
|
|
12302
|
+
.ax-wf__n8n-steps {
|
|
12303
|
+
margin: 4px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 10px;
|
|
12304
|
+
font-size: 12px; line-height: 1.5; color: var(--ax-text-2);
|
|
12305
|
+
}
|
|
12306
|
+
.ax-wf__n8n-steps b { color: var(--ax-text); font-weight: 600; }
|
|
12307
|
+
.ax-wf__n8n-steps i { font-style: normal; color: var(--ax-text); font-weight: 600; }
|
|
12308
|
+
.ax-wf__n8n-steps code {
|
|
12309
|
+
font-family: var(--ax-mono); font-size: 11px; background: var(--ax-surface-2);
|
|
12310
|
+
border: 1px solid var(--ax-border); border-radius: 4px; padding: 0 4px;
|
|
12311
|
+
}
|
|
12312
|
+
.ax-wf__n8n-steps > li { padding-left: 2px; }
|
|
12313
|
+
.ax-wf__n8n-steps .ax-wf__n8n-url { margin: 7px 0 6px; }
|
|
12314
|
+
|
|
12315
|
+
.ax-wf__n8n-url {
|
|
12316
|
+
font-family: var(--ax-mono); font-size: 11px; word-break: break-all;
|
|
12317
|
+
background: var(--ax-surface-2); border: 1px solid var(--ax-border);
|
|
12318
|
+
border-radius: var(--ax-radius-sm); padding: 8px 10px; color: var(--ax-text);
|
|
12319
|
+
}
|
|
12320
|
+
.ax-wf__n8n-copy {
|
|
12321
|
+
align-self: flex-start; font: inherit; font-size: 12px; font-weight: 600;
|
|
12322
|
+
padding: 5px 12px; border-radius: var(--ax-radius-sm);
|
|
12323
|
+
border: var(--ax-border-w) solid var(--ax-border-2);
|
|
12324
|
+
background: var(--ax-surface); color: var(--ax-text); cursor: pointer;
|
|
12325
|
+
}
|
|
12326
|
+
.ax-wf__n8n-copy:hover { background: var(--ax-surface-2); }
|
|
12327
|
+
|
|
11174
12328
|
.ax-wf__cards {
|
|
11175
12329
|
list-style: none; margin: 0; padding: 8px 0;
|
|
11176
12330
|
overflow-y: auto; flex: 1 1 auto; min-height: 140px;
|
|
@@ -11201,37 +12355,6 @@ article.term p {
|
|
|
11201
12355
|
color: var(--ax-accent);
|
|
11202
12356
|
border-color: color-mix(in oklch, var(--ax-accent) 50%, transparent);
|
|
11203
12357
|
}
|
|
11204
|
-
.ax-wf__drafts {
|
|
11205
|
-
border-top: 1px solid var(--ax-border);
|
|
11206
|
-
flex: 0 0 min(34vh, 260px);
|
|
11207
|
-
display: flex; flex-direction: column;
|
|
11208
|
-
background: color-mix(in oklch, var(--ax-bg-elev) 92%, var(--ax-bg));
|
|
11209
|
-
}
|
|
11210
|
-
.ax-wf__drafts > header {
|
|
11211
|
-
display: flex; align-items: center; justify-content: space-between;
|
|
11212
|
-
padding: 10px 18px 8px;
|
|
11213
|
-
}
|
|
11214
|
-
.ax-wf__drafts h3 {
|
|
11215
|
-
margin: 0; font-size: 11px; font-weight: 650;
|
|
11216
|
-
letter-spacing: 0.04em; text-transform: uppercase; color: var(--ax-muted);
|
|
11217
|
-
}
|
|
11218
|
-
.ax-wf__draft-list {
|
|
11219
|
-
list-style: none; margin: 0; padding: 0 0 8px;
|
|
11220
|
-
overflow: auto;
|
|
11221
|
-
}
|
|
11222
|
-
.ax-wf__draft {
|
|
11223
|
-
padding: 9px 18px; cursor: pointer;
|
|
11224
|
-
border-top: 1px solid color-mix(in oklch, var(--ax-border) 55%, transparent);
|
|
11225
|
-
}
|
|
11226
|
-
.ax-wf__draft:hover { background: var(--ax-surface); }
|
|
11227
|
-
.ax-wf__draft.is-active { background: var(--ax-surface); box-shadow: inset 3px 0 0 var(--ax-warn); }
|
|
11228
|
-
.ax-wf__draft-title { font-size: 12px; font-weight: 600; color: var(--ax-text); margin-bottom: 2px; }
|
|
11229
|
-
.ax-wf__draft-meta {
|
|
11230
|
-
display: flex; gap: 6px; flex-wrap: wrap;
|
|
11231
|
-
font-family: var(--ax-mono); font-size: 10px; color: var(--ax-muted);
|
|
11232
|
-
}
|
|
11233
|
-
.ax-wf__draft-empty { padding: 10px 18px 16px; color: var(--ax-muted); font-size: 11px; }
|
|
11234
|
-
.ax-wf__draft-actions { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
11235
12358
|
.ax-wf__btn.danger:hover { background: color-mix(in oklch, var(--ax-err) 13%, transparent); border-color: var(--ax-err); color: var(--ax-err); }
|
|
11236
12359
|
.ax-wf__btn.primary { border-color: color-mix(in oklch, var(--ax-accent) 55%, var(--ax-border)); color: var(--ax-accent); }
|
|
11237
12360
|
|
|
@@ -11398,7 +12521,7 @@ article.term p {
|
|
|
11398
12521
|
border: 1px solid var(--ax-border);
|
|
11399
12522
|
border-radius: 4px;
|
|
11400
12523
|
background: var(--ax-bg);
|
|
11401
|
-
color: var(--ax-
|
|
12524
|
+
color: var(--ax-text);
|
|
11402
12525
|
margin-top: 6px;
|
|
11403
12526
|
width: 100%;
|
|
11404
12527
|
}
|
|
@@ -11470,7 +12593,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11470
12593
|
.ax-wf__status-pill.completed { color: var(--ax-muted); background: var(--ax-surface); }
|
|
11471
12594
|
.ax-wf__status-pill.failed { color: var(--ax-err); background: color-mix(in oklch, var(--ax-err) 15%, transparent); }
|
|
11472
12595
|
.ax-wf__run-actions { display: flex; gap: 4px; margin-left: auto; }
|
|
11473
|
-
.ax-wf__run-actions button { font-size: 11px; padding: 3px 9px; border-radius: 4px; border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-
|
|
12596
|
+
.ax-wf__run-actions button { font-size: 11px; padding: 3px 9px; border-radius: 4px; border: 1px solid var(--ax-border); background: var(--ax-bg); color: var(--ax-text); cursor: pointer; }
|
|
11474
12597
|
.ax-wf__run-actions button:hover { background: var(--ax-surface); }
|
|
11475
12598
|
.ax-wf__run-actions button.danger:hover { background: color-mix(in oklch, var(--ax-err) 15%, transparent); border-color: var(--ax-err); color: var(--ax-err); }
|
|
11476
12599
|
|
|
@@ -11496,17 +12619,15 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11496
12619
|
font-size: 12px; z-index: 50;
|
|
11497
12620
|
}
|
|
11498
12621
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
11499
|
-
|
|
12622
|
+
`,is=`
|
|
11500
12623
|
(() => {
|
|
11501
12624
|
const $ = (sel) => document.querySelector(sel)
|
|
11502
12625
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
11503
12626
|
|
|
11504
12627
|
const state = {
|
|
11505
12628
|
workflows: [],
|
|
11506
|
-
drafts: [],
|
|
11507
12629
|
runs: [],
|
|
11508
12630
|
selectedId: null,
|
|
11509
|
-
selectedDraftId: null,
|
|
11510
12631
|
filter: "",
|
|
11511
12632
|
/** Project filter \u2014 "" = all (incl. workflows without project),
|
|
11512
12633
|
* "__none__" = only workflows missing the project field,
|
|
@@ -11559,11 +12680,46 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11559
12680
|
+ (hasGlobal ? '<option value="__none__"' + (current === "__none__" ? ' selected' : '') + '>(no project)</option>' : "")
|
|
11560
12681
|
}
|
|
11561
12682
|
|
|
12683
|
+
const FRIENDLY_TRIGGER = { gitlab: "on GitLab activity", github: "on GitHub activity", cron: "on a schedule",
|
|
12684
|
+
manual: "when you run it", hook: "when something calls in", channel: "on a message", form: "from a form", n8n: "when n8n calls" }
|
|
12685
|
+
// Plain words for what the operator needs to know, in the order they care:
|
|
12686
|
+
// has it stopped, is it breaking, is anyone blocked, is it fine.
|
|
12687
|
+
const STATE_LABEL = { dormant: "stopped running", failing: "failing", active: "running normally",
|
|
12688
|
+
quiet: "idle", never: "never run yet" }
|
|
12689
|
+
const STATE_RANK = { dormant: 0, failing: 1, active: 2, quiet: 3, never: 4 }
|
|
12690
|
+
function healthOf(id, myRuns) {
|
|
12691
|
+
const rows = (myRuns || []).map(r => ({ workflowId: id, status: r.status, at: new Date(r.updatedAt).getTime() }))
|
|
12692
|
+
const h = workflowHealth([{ id: id }], rows)[0]
|
|
12693
|
+
return { state: h.state, label: STATE_LABEL[h.state] || h.state, rank: STATE_RANK[h.state] }
|
|
12694
|
+
}
|
|
12695
|
+
|
|
12696
|
+
// The address n8n posts to. Shown, and copyable with a real topic already
|
|
12697
|
+
// in it \u2014 a placeholder like <topic> is not something you can paste.
|
|
12698
|
+
(function n8nPanel() {
|
|
12699
|
+
const el = document.getElementById("wf-n8n-in")
|
|
12700
|
+
if (!el) return
|
|
12701
|
+
const base = location.origin + "/webhook/n8n/"
|
|
12702
|
+
el.textContent = base + "your-topic"
|
|
12703
|
+
// Loopback is exempt from mesh auth; anything else needs the token, and
|
|
12704
|
+
// saying so here saves a silent 401 inside n8n.
|
|
12705
|
+
const local = /^(localhost|127.0.0.1|[::1])$/.test(location.hostname)
|
|
12706
|
+
const auth = document.getElementById("wf-n8n-auth")
|
|
12707
|
+
if (auth) auth.textContent = local
|
|
12708
|
+
? "n8n on this machine needs no key."
|
|
12709
|
+
: "n8n is off-box, so add the header Authorization: Bearer <your MESH_TOKEN>."
|
|
12710
|
+
const btn = document.getElementById("wf-n8n-copy")
|
|
12711
|
+
if (btn) btn.onclick = async () => {
|
|
12712
|
+
try { await navigator.clipboard.writeText(el.textContent); btn.textContent = "Copied" }
|
|
12713
|
+
catch { btn.textContent = "Copy failed" }
|
|
12714
|
+
setTimeout(() => { btn.textContent = "Copy address" }, 1600)
|
|
12715
|
+
}
|
|
12716
|
+
})()
|
|
12717
|
+
|
|
11562
12718
|
function renderList() {
|
|
11563
12719
|
renderProjectFilter()
|
|
11564
12720
|
const needle = state.filter.toLowerCase()
|
|
11565
12721
|
const projectFilter = state.projectFilter || ""
|
|
11566
|
-
|
|
12722
|
+
let filtered = state.workflows.filter(wf => {
|
|
11567
12723
|
const matchesText = !needle || wf.id.toLowerCase().includes(needle) || (wf.title || "").toLowerCase().includes(needle)
|
|
11568
12724
|
// projectFilter values:
|
|
11569
12725
|
// "" \u2014 no filter (all projects + global)
|
|
@@ -11586,6 +12742,12 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11586
12742
|
}
|
|
11587
12743
|
$("#wf-empty").hidden = true
|
|
11588
12744
|
|
|
12745
|
+
// Anything that stopped or is failing comes first: a list sorted by name
|
|
12746
|
+
// hides the one workflow you needed to know about.
|
|
12747
|
+
filtered = filtered.slice().sort((a, b) =>
|
|
12748
|
+
healthOf(a.id, runsByWorkflow[a.id]).rank - healthOf(b.id, runsByWorkflow[b.id]).rank
|
|
12749
|
+
|| String(a.title || a.id).localeCompare(String(b.title || b.id)))
|
|
12750
|
+
|
|
11589
12751
|
$("#wf-list").innerHTML = filtered.map(wf => {
|
|
11590
12752
|
const myRuns = runsByWorkflow[wf.id] || []
|
|
11591
12753
|
const live = myRuns.filter(r => r.status === "running").length
|
|
@@ -11594,13 +12756,15 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11594
12756
|
// V2: trigger is a node inside wf.nodes, not a workflow-level field.
|
|
11595
12757
|
const triggerNode = (wf.nodes || []).find(n => n && n.type && n.type.indexOf("trigger.") === 0)
|
|
11596
12758
|
const triggerSource = triggerNode ? (triggerNode.config && triggerNode.config.source) || triggerNode.type.replace("trigger.", "") : "?"
|
|
12759
|
+
const health = healthOf(wf.id, myRuns)
|
|
11597
12760
|
return \`
|
|
11598
12761
|
<li class="ax-wf__card \${isActive ? "is-active" : ""}" data-id="\${wf.id}">
|
|
11599
12762
|
<div class="ax-wf__card-title">\${esc(wf.title || wf.id)}</div>
|
|
11600
|
-
<div class="ax-wf__card-id">\${esc(wf.id)}
|
|
12763
|
+
<div class="ax-wf__card-id">\${esc(wf.id)}</div>
|
|
12764
|
+
<div class="ax-wf__state ax-wf__state--\${health.state}">\${esc(health.label)}</div>
|
|
11601
12765
|
<div class="ax-wf__card-meta">
|
|
11602
12766
|
\${wf.project ? \`<span class="tag tag--project" title="Project">\${esc(wf.project)}</span>\` : ""}
|
|
11603
|
-
<span class="tag">\${esc(triggerSource)}</span>
|
|
12767
|
+
<span class="tag" title="What starts it">\${esc(FRIENDLY_TRIGGER[triggerSource] || triggerSource)}</span>
|
|
11604
12768
|
\${live > 0 ? \`<span class="tag live">\${live} running</span>\` : ""}
|
|
11605
12769
|
\${lastRun
|
|
11606
12770
|
? \`<span class="tag tag--\${esc(lastRun.status)}" title="\${esc(lastRun.id)} \xB7 \${esc(new Date(lastRun.updatedAt).toLocaleString())}">last: \${esc(lastRun.status)} \xB7 \${relTime(lastRun.updatedAt)}</span>\`
|
|
@@ -11614,35 +12778,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11614
12778
|
})
|
|
11615
12779
|
}
|
|
11616
12780
|
|
|
11617
|
-
function renderDraftList() {
|
|
11618
|
-
$("#wf-draft-count").textContent = String(state.drafts.length)
|
|
11619
|
-
if (!state.drafts.length) {
|
|
11620
|
-
$("#wf-draft-list").innerHTML = \`<li class="ax-wf__draft-empty">No drafts pending review.</li>\`
|
|
11621
|
-
return
|
|
11622
|
-
}
|
|
11623
|
-
$("#wf-draft-list").innerHTML = state.drafts.map(d => {
|
|
11624
|
-
const wf = d.workflow || {}
|
|
11625
|
-
const isActive = state.selectedDraftId === d.id
|
|
11626
|
-
const issues = Array.isArray(d.issues) ? d.issues.length : 0
|
|
11627
|
-
return \`<li class="ax-wf__draft \${isActive ? "is-active" : ""}" data-draft="\${esc(d.id)}">
|
|
11628
|
-
<div class="ax-wf__draft-title">\${esc(wf.title || d.id)}</div>
|
|
11629
|
-
<div class="ax-wf__draft-meta">
|
|
11630
|
-
<span>\${esc(d.id)}</span>
|
|
11631
|
-
<span>confidence=\${wf.confidence == null ? "\u2014" : Number(wf.confidence).toFixed(2)}</span>
|
|
11632
|
-
<span>\${issues ? issues + " issue" + (issues === 1 ? "" : "s") : "valid"}</span>
|
|
11633
|
-
</div>
|
|
11634
|
-
</li>\`
|
|
11635
|
-
}).join("")
|
|
11636
|
-
$$(".ax-wf__draft").forEach(el => {
|
|
11637
|
-
el.addEventListener("click", () => selectDraft(el.dataset.draft))
|
|
11638
|
-
})
|
|
11639
|
-
}
|
|
11640
|
-
|
|
11641
12781
|
function renderDetail() {
|
|
11642
|
-
if (state.selectedDraftId) {
|
|
11643
|
-
renderDraftDetail()
|
|
11644
|
-
return
|
|
11645
|
-
}
|
|
11646
12782
|
const wf = state.workflows.find(w => w.id === state.selectedId)
|
|
11647
12783
|
if (!wf) {
|
|
11648
12784
|
$("#wf-detail-head").innerHTML = \`<span class="hint">Select a workflow to inspect.</span>\`
|
|
@@ -11660,6 +12796,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
11660
12796
|
$("#wf-detail-head").innerHTML = \`
|
|
11661
12797
|
<div class="ax-wf__detail-title">
|
|
11662
12798
|
<h2>\${esc(wf.title || wf.id)}</h2>
|
|
12799
|
+
<a class="ax-wf__btn" href="/workflows/editor?id=\${encodeURIComponent(wf.id)}" title="Open on the canvas">Edit on canvas</a>
|
|
11663
12800
|
<span class="hint">\${esc(wf.id)} \xB7 v\${wf.version} \xB7 trigger: \${esc(triggerSource)}\${trigFilter ? " \xB7 " + esc(trigFilter) : ""}</span>
|
|
11664
12801
|
</div>
|
|
11665
12802
|
<div class="ax-wf__detail-actions">
|
|
@@ -12089,69 +13226,6 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12089
13226
|
}
|
|
12090
13227
|
}
|
|
12091
13228
|
|
|
12092
|
-
function renderDraftDetail() {
|
|
12093
|
-
const draft = state.drafts.find(d => d.id === state.selectedDraftId)
|
|
12094
|
-
if (!draft) {
|
|
12095
|
-
$("#wf-detail-head").innerHTML = \`<span class="hint">Select a workflow to inspect.</span>\`
|
|
12096
|
-
$("#wf-detail-body").innerHTML = ""
|
|
12097
|
-
return
|
|
12098
|
-
}
|
|
12099
|
-
const wf = draft.workflow || {}
|
|
12100
|
-
const issues = Array.isArray(draft.issues) ? draft.issues : []
|
|
12101
|
-
const sourceIds = Array.isArray(wf.sourceTaskIds) ? wf.sourceTaskIds : []
|
|
12102
|
-
$("#wf-detail-head").innerHTML = \`
|
|
12103
|
-
<div class="ax-wf__detail-title">
|
|
12104
|
-
<h2>\${esc(wf.title || draft.id)}</h2>
|
|
12105
|
-
<span class="hint">\${esc(draft.id)} \xB7 status=\${esc(wf.status || "draft")} \xB7 state=\${esc(wf.state || "disabled")} \xB7 confidence=\${wf.confidence == null ? "\u2014" : Number(wf.confidence).toFixed(2)}</span>
|
|
12106
|
-
</div>
|
|
12107
|
-
<div class="ax-wf__detail-actions ax-wf__draft-actions">
|
|
12108
|
-
<button class="ax-wf__btn" id="wf-draft-validate" type="button">Validate</button>
|
|
12109
|
-
<button class="ax-wf__btn" id="wf-draft-save" type="button">Save</button>
|
|
12110
|
-
<button class="ax-wf__btn" id="wf-draft-replay" type="button">Save & Replay</button>
|
|
12111
|
-
<button class="ax-wf__btn primary" id="wf-draft-promote" type="button">Promote</button>
|
|
12112
|
-
<button class="ax-wf__btn danger" id="wf-draft-reject" type="button">Reject</button>
|
|
12113
|
-
</div>\`
|
|
12114
|
-
|
|
12115
|
-
const issueHtml = issues.length
|
|
12116
|
-
? issues.map(i => \`<div class="ax-wf__trans"><span class="cond">\${esc(i)}</span></div>\`).join("")
|
|
12117
|
-
: \`<span class="hint">Draft validates against the workflow schema and lint rules.</span>\`
|
|
12118
|
-
const tags = Array.isArray(wf.tags) ? wf.tags : []
|
|
12119
|
-
$("#wf-detail-body").innerHTML = \`
|
|
12120
|
-
<div class="ax-wf__panel">
|
|
12121
|
-
<h3>Review state</h3>
|
|
12122
|
-
<div class="ax-wf__trans">
|
|
12123
|
-
<div>owner: \${esc(wf.ownerAgent || "\u2014")}</div>
|
|
12124
|
-
<div>entity: \${esc(wf.entity || "\u2014")}</div>
|
|
12125
|
-
<div>generatedFrom: \${esc(wf.generatedFrom || "\u2014")}</div>
|
|
12126
|
-
<div>path: \${esc(draft.path || "\u2014")}</div>
|
|
12127
|
-
</div>
|
|
12128
|
-
</div>
|
|
12129
|
-
<div class="ax-wf__panel">
|
|
12130
|
-
<h3>Signals</h3>
|
|
12131
|
-
<div class="ax-wf__states">
|
|
12132
|
-
\${tags.length ? tags.map(t => \`<span class="ax-wf__state">\${esc(t)}</span>\`).join("") : \`<span class="hint">No tags.</span>\`}
|
|
12133
|
-
</div>
|
|
12134
|
-
</div>
|
|
12135
|
-
<div class="ax-wf__panel ax-wf__panel--full">
|
|
12136
|
-
<h3>Source task ids (\${sourceIds.length})</h3>
|
|
12137
|
-
<div class="ax-wf__trans">\${sourceIds.length ? sourceIds.slice(0, 25).map(esc).join("<br>") : \`<span class="hint">No source task ids.</span>\`}</div>
|
|
12138
|
-
</div>
|
|
12139
|
-
<div class="ax-wf__panel ax-wf__panel--full">
|
|
12140
|
-
<h3>Validation</h3>
|
|
12141
|
-
\${issueHtml}
|
|
12142
|
-
</div>
|
|
12143
|
-
<div class="ax-wf__panel ax-wf__panel--full">
|
|
12144
|
-
<h3>Definition <span class="hint">(JSON; saved as YAML on disk)</span></h3>
|
|
12145
|
-
<textarea id="wf-draft-editor" class="ax-wf__editor" spellcheck="false">\${esc(JSON.stringify(wf, null, 2))}</textarea>
|
|
12146
|
-
</div>\`
|
|
12147
|
-
|
|
12148
|
-
$("#wf-draft-validate").addEventListener("click", () => validateDraft(draft.id))
|
|
12149
|
-
$("#wf-draft-save").addEventListener("click", () => saveDraft(draft.id))
|
|
12150
|
-
$("#wf-draft-replay").addEventListener("click", () => replayDraft(draft.id))
|
|
12151
|
-
$("#wf-draft-promote").addEventListener("click", () => promoteDraft(draft.id))
|
|
12152
|
-
$("#wf-draft-reject").addEventListener("click", () => rejectDraft(draft.id))
|
|
12153
|
-
}
|
|
12154
|
-
|
|
12155
13229
|
// --- Run drawer ------------------------------------------------------
|
|
12156
13230
|
|
|
12157
13231
|
async function openRun(runId) {
|
|
@@ -12212,22 +13286,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12212
13286
|
|
|
12213
13287
|
async function select(id) {
|
|
12214
13288
|
state.selectedId = id
|
|
12215
|
-
state.selectedDraftId = null
|
|
12216
13289
|
// Keep URL hash in sync so refreshes and editor deep-links stay on the
|
|
12217
13290
|
// same workflow. Use replaceState so the browser's back button doesn't
|
|
12218
13291
|
// accumulate selection history.
|
|
12219
13292
|
try { history.replaceState(null, "", "#" + encodeURIComponent(id)) } catch (_) { /* */ }
|
|
12220
13293
|
renderList()
|
|
12221
|
-
renderDraftList()
|
|
12222
|
-
renderDetail()
|
|
12223
|
-
}
|
|
12224
|
-
|
|
12225
|
-
async function selectDraft(id) {
|
|
12226
|
-
state.selectedDraftId = id
|
|
12227
|
-
state.selectedId = null
|
|
12228
|
-
try { history.replaceState(null, "", "#draft:" + encodeURIComponent(id)) } catch (_) { /* */ }
|
|
12229
|
-
renderList()
|
|
12230
|
-
renderDraftList()
|
|
12231
13294
|
renderDetail()
|
|
12232
13295
|
}
|
|
12233
13296
|
|
|
@@ -12237,126 +13300,23 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12237
13300
|
// 10-50KB each \u2014 at limit=100 the listing was multi-MB and gating
|
|
12238
13301
|
// first paint behind the slowest serialization path). Run-detail
|
|
12239
13302
|
// and SSE stream still return the full shape unchanged.
|
|
12240
|
-
const [workflows, runs
|
|
13303
|
+
const [workflows, runs] = await Promise.all([
|
|
12241
13304
|
fetchJSON("/api/workflows"),
|
|
12242
13305
|
fetchJSON("/api/workflows/runs?limit=100&summary=1"),
|
|
12243
|
-
fetchJSON("/api/workflows/drafts"),
|
|
12244
13306
|
])
|
|
12245
13307
|
state.workflows = workflows.workflows || workflows
|
|
12246
13308
|
state.runs = runs.runs || runs
|
|
12247
|
-
state.drafts = drafts.drafts || drafts
|
|
12248
13309
|
// If the URL hash names a workflow (e.g. /workflows#my-workflow)
|
|
12249
13310
|
// and nothing is selected yet, auto-select it. Editor's "History"
|
|
12250
13311
|
// button links here with the hash, so users land on the right detail.
|
|
12251
13312
|
if (!state.selectedId && location.hash) {
|
|
12252
13313
|
const fromHash = decodeURIComponent(location.hash.slice(1))
|
|
12253
|
-
if (
|
|
12254
|
-
else if (state.workflows.some(w => w.id === fromHash)) state.selectedId = fromHash
|
|
13314
|
+
if (state.workflows.some(w => w.id === fromHash)) state.selectedId = fromHash
|
|
12255
13315
|
}
|
|
12256
13316
|
renderList()
|
|
12257
|
-
renderDraftList()
|
|
12258
|
-
// Don't re-render the detail panel when the user is actively editing
|
|
12259
|
-
// a draft \u2014 the periodic 15s refresh would otherwise reset their
|
|
12260
|
-
// unsaved textarea on every tick. Resume rendering as soon as focus
|
|
12261
|
-
// leaves the editor.
|
|
12262
|
-
const editing = state.selectedDraftId && document.activeElement && document.activeElement.id === "wf-draft-editor"
|
|
12263
|
-
if (!editing) renderDetail()
|
|
12264
|
-
} catch (e) {
|
|
12265
|
-
toast("Failed to load workflows: " + e.message)
|
|
12266
|
-
}
|
|
12267
|
-
}
|
|
12268
|
-
|
|
12269
|
-
async function validateDraft(id) {
|
|
12270
|
-
try {
|
|
12271
|
-
const res = await postJSON("/api/workflows/drafts/" + encodeURIComponent(id) + "/validate")
|
|
12272
|
-
toast(res.ok ? "draft is valid" : "draft has validation issues")
|
|
12273
|
-
await refresh()
|
|
12274
|
-
state.selectedDraftId = id
|
|
12275
13317
|
renderDetail()
|
|
12276
13318
|
} catch (e) {
|
|
12277
|
-
toast("
|
|
12278
|
-
}
|
|
12279
|
-
}
|
|
12280
|
-
|
|
12281
|
-
async function promoteDraft(id) {
|
|
12282
|
-
if (!confirm("Promote this draft into the active workflow store?")) return
|
|
12283
|
-
try {
|
|
12284
|
-
await postJSON("/api/workflows/drafts/" + encodeURIComponent(id) + "/promote", { format: "yaml" })
|
|
12285
|
-
toast("draft promoted")
|
|
12286
|
-
state.selectedDraftId = null
|
|
12287
|
-
await refresh()
|
|
12288
|
-
} catch (e) {
|
|
12289
|
-
toast("promote failed: " + e.message)
|
|
12290
|
-
}
|
|
12291
|
-
}
|
|
12292
|
-
|
|
12293
|
-
async function rejectDraft(id) {
|
|
12294
|
-
if (!confirm("Reject and archive this draft?")) return
|
|
12295
|
-
try {
|
|
12296
|
-
await postJSON("/api/workflows/drafts/" + encodeURIComponent(id) + "/reject")
|
|
12297
|
-
toast("draft rejected")
|
|
12298
|
-
state.selectedDraftId = null
|
|
12299
|
-
await refresh()
|
|
12300
|
-
} catch (e) {
|
|
12301
|
-
toast("reject failed: " + e.message)
|
|
12302
|
-
}
|
|
12303
|
-
}
|
|
12304
|
-
|
|
12305
|
-
/** Read the textarea, parse as JSON (the editor is JSON; the server
|
|
12306
|
-
* re-serialises to YAML on disk), and PUT to the drafts endpoint. */
|
|
12307
|
-
async function persistDraftFromEditor(id) {
|
|
12308
|
-
const el = $("#wf-draft-editor")
|
|
12309
|
-
if (!el) throw new Error("editor not mounted")
|
|
12310
|
-
let workflow
|
|
12311
|
-
try {
|
|
12312
|
-
workflow = JSON.parse(el.value)
|
|
12313
|
-
} catch (e) {
|
|
12314
|
-
throw new Error("editor JSON is invalid: " + e.message)
|
|
12315
|
-
}
|
|
12316
|
-
const res = await fetch("/api/workflows/drafts/" + encodeURIComponent(id), {
|
|
12317
|
-
method: "PUT",
|
|
12318
|
-
headers: { "Content-Type": "application/json", "X-Requested-With": "agentx-board", ...headers() },
|
|
12319
|
-
credentials: "same-origin",
|
|
12320
|
-
body: JSON.stringify({ workflow }),
|
|
12321
|
-
})
|
|
12322
|
-
const data = await res.json().catch(() => ({}))
|
|
12323
|
-
if (!res.ok) {
|
|
12324
|
-
const issues = Array.isArray(data.issues) ? "\\n - " + data.issues.join("\\n - ") : ""
|
|
12325
|
-
throw new Error((data.error || "save failed") + issues)
|
|
12326
|
-
}
|
|
12327
|
-
return data
|
|
12328
|
-
}
|
|
12329
|
-
|
|
12330
|
-
async function saveDraft(id) {
|
|
12331
|
-
try {
|
|
12332
|
-
const res = await persistDraftFromEditor(id)
|
|
12333
|
-
const lint = Array.isArray(res.issues) && res.issues.length ? \` (\${res.issues.length} lint warning\${res.issues.length === 1 ? "" : "s"})\` : ""
|
|
12334
|
-
toast("draft saved" + lint)
|
|
12335
|
-
await refresh()
|
|
12336
|
-
state.selectedDraftId = id
|
|
12337
|
-
renderDetail()
|
|
12338
|
-
} catch (e) {
|
|
12339
|
-
toast("save failed: " + e.message)
|
|
12340
|
-
}
|
|
12341
|
-
}
|
|
12342
|
-
|
|
12343
|
-
async function replayDraft(id) {
|
|
12344
|
-
try {
|
|
12345
|
-
await persistDraftFromEditor(id)
|
|
12346
|
-
} catch (e) {
|
|
12347
|
-
toast("save failed: " + e.message)
|
|
12348
|
-
return
|
|
12349
|
-
}
|
|
12350
|
-
try {
|
|
12351
|
-
const res = await postJSON("/api/workflows/drafts/" + encodeURIComponent(id) + "/replay", {})
|
|
12352
|
-
toast("replay started: " + (res.runId || "?").slice(0, 8))
|
|
12353
|
-
if (res.runId) {
|
|
12354
|
-
await openRun(res.runId)
|
|
12355
|
-
} else {
|
|
12356
|
-
await refresh()
|
|
12357
|
-
}
|
|
12358
|
-
} catch (e) {
|
|
12359
|
-
toast("replay failed: " + e.message)
|
|
13319
|
+
toast("Failed to load workflows: " + e.message)
|
|
12360
13320
|
}
|
|
12361
13321
|
}
|
|
12362
13322
|
|
|
@@ -12447,7 +13407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12447
13407
|
setInterval(refresh, 15000)
|
|
12448
13408
|
})
|
|
12449
13409
|
})();
|
|
12450
|
-
`;function
|
|
13410
|
+
`;function Za(t={}){let e=`<div class="ax-proc__root">
|
|
12451
13411
|
<header class="ax-proc__header">
|
|
12452
13412
|
<h1>Procedures</h1>
|
|
12453
13413
|
<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>
|
|
@@ -12491,7 +13451,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12491
13451
|
<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>
|
|
12492
13452
|
<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>
|
|
12493
13453
|
</section>
|
|
12494
|
-
</div>`;return
|
|
13454
|
+
</div>`;return C({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ls,scripts:`<script>${ds}</script>`})}var ls=`
|
|
12495
13455
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
12496
13456
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
12497
13457
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -12517,7 +13477,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12517
13477
|
.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); }
|
|
12518
13478
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
12519
13479
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
12520
|
-
`,
|
|
13480
|
+
`,ds=`
|
|
12521
13481
|
(function(){
|
|
12522
13482
|
function $(sel){ return document.querySelector(sel) }
|
|
12523
13483
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -12617,24 +13577,24 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12617
13577
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
12618
13578
|
else bootAll()
|
|
12619
13579
|
})();
|
|
12620
|
-
`;function
|
|
12621
|
-
data-task-id="${
|
|
12622
|
-
data-agent-id="${
|
|
12623
|
-
data-node-url="${
|
|
13580
|
+
`;function en(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
13581
|
+
data-task-id="${P(t.taskId)}"
|
|
13582
|
+
data-agent-id="${P(t.agentId)}"
|
|
13583
|
+
data-node-url="${P(t.nodeUrl)}"
|
|
12624
13584
|
data-archived="${t.archived?"1":""}"
|
|
12625
|
-
data-ask="${
|
|
12626
|
-
data-ask-at="${
|
|
13585
|
+
data-ask="${P(t.ask||"")}"
|
|
13586
|
+
data-ask-at="${P(t.askAt||"")}">
|
|
12627
13587
|
|
|
12628
13588
|
<header class="ax-task-page__head">
|
|
12629
13589
|
<nav class="ax-crumbs" aria-label="Breadcrumb">
|
|
12630
13590
|
<a href="/live">Live</a>
|
|
12631
13591
|
<span class="ax-crumbs__sep">/</span>
|
|
12632
|
-
<a href="/agents/${
|
|
13592
|
+
<a href="/agents/${P(t.agentId)}/history?node=${encodeURIComponent(t.nodeUrl)}&name=${encodeURIComponent(e)}"><span class="ax-mention">@${P(t.agentId)}</span></a>
|
|
12633
13593
|
<span class="ax-crumbs__sep">/</span>
|
|
12634
13594
|
<span class="ax-crumbs__here">Task</span>
|
|
12635
13595
|
</nav>
|
|
12636
13596
|
<div class="ax-task-page__meta">
|
|
12637
|
-
${t.channel?`<span class="ax-badge ax-badge--mono ax-badge--ghost">${
|
|
13597
|
+
${t.channel?`<span class="ax-badge ax-badge--mono ax-badge--ghost">${P(t.channel)}</span>`:""}
|
|
12638
13598
|
<span class="ax-badge ax-badge--mono" id="task-status">connecting\u2026</span>
|
|
12639
13599
|
<span class="ax-mono ax-muted" id="task-elapsed"></span>
|
|
12640
13600
|
</div>
|
|
@@ -12660,7 +13620,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12660
13620
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
12661
13621
|
</div>
|
|
12662
13622
|
</footer>
|
|
12663
|
-
</div>`;return
|
|
13623
|
+
</div>`;return C({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:cs,scripts:`<script>${ps}</script>`})}var cs=`
|
|
12664
13624
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
12665
13625
|
the sticky topbar. Breathe. */
|
|
12666
13626
|
.ax-task-page {
|
|
@@ -12802,7 +13762,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
12802
13762
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
12803
13763
|
}
|
|
12804
13764
|
|
|
12805
|
-
`,
|
|
13765
|
+
`,ps=`
|
|
12806
13766
|
(function () {
|
|
12807
13767
|
var root = document.querySelector('.ax-task-page');
|
|
12808
13768
|
if (!root) return;
|
|
@@ -13158,15 +14118,15 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13158
14118
|
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') { e.preventDefault(); sendBtn.click(); }
|
|
13159
14119
|
});
|
|
13160
14120
|
})();
|
|
13161
|
-
`;function
|
|
13162
|
-
data-agent-id="${
|
|
13163
|
-
data-agent-name="${
|
|
13164
|
-
data-node-url="${
|
|
14121
|
+
`;function tn(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
14122
|
+
data-agent-id="${P(t.agentId)}"
|
|
14123
|
+
data-agent-name="${P(e)}"
|
|
14124
|
+
data-node-url="${P(t.nodeUrl)}">
|
|
13165
14125
|
<header class="ax-history__head">
|
|
13166
14126
|
<nav class="ax-crumbs" aria-label="Breadcrumb">
|
|
13167
14127
|
<a href="/live">Live</a>
|
|
13168
14128
|
<span class="ax-crumbs__sep">/</span>
|
|
13169
|
-
<span class="ax-mention">@${
|
|
14129
|
+
<span class="ax-mention">@${P(t.agentId)}</span>
|
|
13170
14130
|
<span class="ax-crumbs__sep">/</span>
|
|
13171
14131
|
<span class="ax-crumbs__here">History</span>
|
|
13172
14132
|
</nav>
|
|
@@ -13187,7 +14147,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13187
14147
|
<div class="ax-history__list" id="hist-list">
|
|
13188
14148
|
<div class="ax-history__empty">loading\u2026</div>
|
|
13189
14149
|
</div>
|
|
13190
|
-
</div>`;return
|
|
14150
|
+
</div>`;return C({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:us,scripts:`<script>${ms}</script>`})}var us=`
|
|
13191
14151
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
13192
14152
|
flush against the sticky topbar. */
|
|
13193
14153
|
.ax-history {
|
|
@@ -13239,7 +14199,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13239
14199
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
13240
14200
|
}
|
|
13241
14201
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
13242
|
-
`,
|
|
14202
|
+
`,ms=`
|
|
13243
14203
|
(function () {
|
|
13244
14204
|
var root = document.querySelector('.ax-history');
|
|
13245
14205
|
if (!root) return;
|
|
@@ -13339,25 +14299,25 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
13339
14299
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
13340
14300
|
});
|
|
13341
14301
|
})();
|
|
13342
|
-
`;function
|
|
14302
|
+
`;function nn(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"])?I(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 fe(t,e,i=>an(e,a,i,{mode:"create",convertFromYaml:l}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:gs(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return I(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return I(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?fe(t,e,l=>{let i=l,c=a.dispatcher.emitSignal({name:s,scope:i?.scope,workflowId:i?.workflowId,payload:i?.payload});return I(e,200,{ok:!0,emission:c})}):I(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"])?I(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?fe(t,e,i=>{try{let c=a.layouts.save(s,i);return I(e,200,{layout:c})}catch(c){return I(e,400,{error:"invalid layout",message:c.message})}}):!0}if(l==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?fe(t,e,i=>{let c=Be.safeParse(i);if(!c.success)return I(e,200,{ok:!1,issues:c.error.issues.map(m=>({path:m.path.join("."),message:m.message}))});let u=ze(c.data).map(m=>({path:"",message:m}));return I(e,200,{ok:u.length===0,issues:u,workflow:c.data})}):!0;if(!l){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let i=a.store.get(s);return i?I(e,200,{workflow:i}):I(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,c=i.get("convertFromYaml")==="true"||i.get("convertFromYaml")==="1";return fe(t,e,u=>an(e,a,u,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=a.store.delete(s);return a.layouts.delete(s),I(e,i?200:404,i?{ok:!0}:{error:"workflow not found"})}}}return I(e,404,{error:"unknown workflows endpoint",path:n})}var hs=["mesh"];function an(t,e,a,n){let r=Be.safeParse(a);if(!r.success)return I(t,400,{error:"invalid workflow",issues:r.error.issues.map(i=>({path:i.path.join("."),message:i.message}))});let o=r.data,s=ze(o);if(s.length>0)return I(t,400,{error:"lint errors",issues:s.map(i=>({path:"",message:i}))});if(n.mode==="update"&&o.id!==n.id)return I(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return I(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let i=a,c=e.store.get(n.id);if(c)for(let u of hs)!(u in i)&&u in c&&(o[u]=c[u])}let l;try{l=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(i){let c=i?.message||String(i),u=i?.yamlPath,m=!!u||/yaml round-trip failed/.test(c);return I(t,m?409:500,{error:m?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:m?"yaml-authored":"save-failed",...u?{path:u}:{}})}return e.layouts.sync(l.id,l.nodes.map(i=>i.id)),I(t,200,{workflow:l})}function gs(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))),c=r.get("workflowId")||void 0,u=r.get("summary")==="1"||r.get("summary")==="true",m=a.runs.list({workflowId:c,limit:i});if(!u)return I(e,200,{runs:m});let x=m.map(b=>({id:b.id,workflowId:b.workflowId,workflowVersion:b.workflowVersion,homeNode:b.homeNode,status:b.status,pending:b.pending,entityRef:b.entityRef,history:(b.history||[]).slice(-5),parentRunId:b.parentRunId,parentNodeId:b.parentNodeId,rootRunId:b.rootRunId,depth:b.depth,createdAt:b.createdAt,updatedAt:b.updatedAt}));return I(e,200,{runs:x})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return I(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let i=decodeURIComponent(s[1]);return fe(t,e,c=>{let u=c?.status;return u!=="paused"&&u!=="running"&&u!=="canceled"?I(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(i,u)?I(e,200,{ok:!0,runId:i,status:u}):I(e,404,{error:"run not found"})})}let l=o.match(/^\/([^\/?]+)(\/stream)?$/);if(l){let i=decodeURIComponent(l[1]);if(l[2])return fs(t,e,a,i);let c=a.runs.get(i);return c?I(e,200,{run:c}):I(e,404,{error:"run not found"})}return I(e,404,{error:"unknown runs endpoint"})}function fs(t,e,a,n){let r=a.runs.get(n);if(!r)return I(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)}
|
|
13343
14303
|
|
|
13344
|
-
`);let o=!1,s=()=>{o=!0,
|
|
14304
|
+
`);let o=!1,s=()=>{o=!0,i?.(),clearInterval(u);try{e.end()}catch{}};t.on("close",s);let l=m=>{if(!o)try{e.write(`data: ${JSON.stringify(m)}
|
|
13345
14305
|
|
|
13346
|
-
`)}catch{s()}},
|
|
13347
|
-
Live dashboard: http://${
|
|
14306
|
+
`)}catch{s()}},i=a.runEvents?.subscribe(n,l),c=r.updatedAt,u=setInterval(()=>{if(o)return;let m=a.runs.get(n);m&&m.updatedAt!==c&&(c=m.updatedAt,l(m))},2e3);return!0}function fe(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){I(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{I(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{I(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>I(e,400,{error:"body read failed",message:r.message})),!0}function I(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}function Rd(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let b of a)try{s.set(b.id,As(b,t))}catch(_){console.error(` Board "${b.id}" failed to initialize: ${_.message}`)}let l=t.node?.id||"local",i=t.workflows?.dir?ke(process.cwd(),t.workflows.dir):void 0,c=new xt(i?{baseDir:i}:void 0),u=new vt(i?{baseDir:i,nodeId:l}:{nodeId:l}),m=new bt(i?{baseDir:i}:void 0);Aa(t),Et({business:t.business?.enabled===!0}),xs(async(b,_)=>{try{await Es(b,_,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:u,workflowLayouts:m})}catch(M){v(_,500,{error:M.message||"internal error"})}}).listen(n,r,()=>{let b=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
14307
|
+
Live dashboard: http://${b}:${n}
|
|
13348
14308
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
13349
|
-
Kanban dashboard: http://${
|
|
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
|
|
14309
|
+
Kanban dashboard: http://${b}:${n}
|
|
14310
|
+
`),console.log(` Boards: ${a.map(_=>_.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var _s=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki","/admin/activity-graph"]);async function Es(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"&&_s.has(r)&&Ht("page",r),o==="GET"&&r==="/"){let d=Rt();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(it({peers:O(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Va({peers:O(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(it({peers:O(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ie(a.config);if(!d){v(e,503,{error:"no node available"});return}let p=await new Promise(f=>{let h="";t.on("data",y=>h+=y),t.on("end",()=>f(h)),t.on("error",()=>f(""))}),g=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:p||"{}"});e.writeHead(g.status,{"Content-Type":"application/json"}),e.end(await g.text())}catch(d){v(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await ie(a.config),p=o==="POST"?void 0:n.searchParams.get("node"),g=o==="POST"?await re(t):void 0,f=g?.node??p,h=f?d.find($=>$.url===f):d[0];if(!h){v(e,400,{error:"unknown node"});return}let y=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",k=await fetch(h.url+r+y,{method:o,headers:{"Content-Type":"application/json",...h.token?{Authorization:`Bearer ${h.token}`}:{}},...o==="POST"?{body:JSON.stringify({...g,node:void 0})}:{}});v(e,k.status,await k.json().catch(()=>({error:`HTTP ${k.status}`})))}catch(d){v(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await re(t),p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${g}/api/workflows/editor/chat`,{method:"POST",headers:p,body:JSON.stringify(d??{})}),h=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,h)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ie(a.config);if(!d){v(e,200,{configured:!1,workflows:[]});return}let p=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});v(e,p.status,await p.json().catch(()=>({configured:!1,workflows:[]})))}catch{v(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wt({peers:O(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ut({peers:O(a.config)}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zt({peers:O(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,p=setTimeout(()=>d.abort(),8e3);try{let g=wt(await ie(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let $=await Promise.all(g.map(async A=>{try{let w=await fetch(A.url+"/monitor",{headers:A.token?{Authorization:`Bearer ${A.token}`}:{},signal:d.signal});if(!w.ok)throw new Error(`HTTP ${w.status}`);return{name:A.name,url:A.url,ok:!0,data:await w.json()}}catch(w){return{name:A.name,url:A.url,ok:!1,error:w.message}}}));v(e,200,{nodes:$});return}let f=g.find($=>$.url===n.searchParams.get("node"));if(!f){v(e,400,{error:"Select a known node"});return}let h=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(h)||o==="POST"&&["register","ended","action","retry","clear"].includes(h))){v(e,405,{error:"Unknown monitor operation"});return}let y=o==="POST"?JSON.stringify(await yt(t)):void 0,k=await fetch(f.url+"/monitor/"+h+(h==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):h==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:y,signal:d.signal,headers:{"Content-Type":"application/json",...f.token?{Authorization:`Bearer ${f.token}`}:{}}});v(e,k.status,await k.json())}catch(g){v(e,502,{error:g.message})}finally{clearTimeout(p)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ga({peers:O(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ya({peers:O(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qa({peers:O(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Za({peers:O(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lt({}));return}let l=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(l){let d=n.searchParams.get("agent")||"",p=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(en({taskId:decodeURIComponent(l[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:p,peers:O(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(tn({agentId:decodeURIComponent(i[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:O(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Pt(t,e);return}if(o==="POST"&&r==="/api/setup"){await Dt(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Ot(t,e);return}if(o==="GET"&&r==="/admin"){Vt(t,e,O(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){na(t,e,O(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}pa(t,e,O(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await Us(t,e,a);return}let p=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(p){let g=decodeURIComponent(p[1]),f=g.indexOf("::");if(f>0){let h=g.slice(0,f),y=g.slice(f+2),k=a.config.node?.id||a.config.node?.name||"local";if(h===k)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(y)}`;else{let $=(a.config.dashboard?.daemons||[]).find(A=>(A.name||A.url)===h);if($){let A=ut($.url.replace(/\/+$/,""),a.config);if(A){await rn(t,e,A,`/api/admin/activity-graph/dispatch/${encodeURIComponent(y)}`);return}}v(e,404,{error:`unknown node "${h}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let p=ut(d,a.config);if(!p){v(e,404,{error:`unknown peer: ${d}`});return}let g=(n.search||"").replace(/[?&]peer=[^&]*/g,h=>h.startsWith("?")?"?":"");await rn(t,e,p,r+(g==="?"?"":g));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await ua(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Fs(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-PBAH6XL3.js"),g=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",f=await d({running:g});v(e,200,f)}catch(d){v(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fa({peers:O(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await ga(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xa({peers:O(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(va({peers:O(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await Is(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){_a(t,e,O(a.config));return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await Ma(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Ia(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await ja(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Pa(t,e,c[1],O(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",p=d.startsWith("Bearer ")?d.slice(7):"";if(p!==a.token){let g=new ee,f=p?g.verify(p):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Yt(t,e);return}if(r.startsWith("/api/admin/graph/")){await ra(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Da(t,e,r);return}if(r.startsWith("/api/admin/")){await Qt(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(Gt);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){v(e,400,{error:"invalid asset name"});return}let p=zs("web/"+d);try{let g=await qs(p),f=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",h=n.searchParams.has("v");e.writeHead(200,{"Content-Type":f,"Cache-Control":h?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(g)}catch{v(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await pt(a.config);v(e,200,d)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),p=n.searchParams.get("timezone")||"UTC",g=await pt(a.config,{date:d,timezone:p});v(e,200,g)}catch(d){v(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(p,g,f,h)=>{let y=parseInt(n.searchParams.get(p)||"",10);return Number.isFinite(y)?Math.max(f,Math.min(h,y)):g};try{let p=await ie(a.config);v(e,200,await Xa(p,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(p){v(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){v(e,400,{error:"day=YYYY-MM-DD query param required"});return}let p=(g,f,h,y)=>{let k=parseInt(n.searchParams.get(g)||"",10);return Number.isFinite(k)?Math.max(h,Math.min(y,k)):f};try{let g=await ie(a.config);v(e,200,await Ja(g,{day:d,tzOffsetMinutes:p("tzOffset",0,-840,840),limit:p("limit",40,1,200)}))}catch(g){v(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 d=n.searchParams.get("node");if(!d){v(e,400,{error:"node query param required"});return}let p=n.searchParams,g;if(r==="/api/mesh/thread"){let[f,h,y]=[p.get("agent"),p.get("channel"),p.get("chat")];if(!f||!h||!y){v(e,400,{error:"agent, channel, chat required"});return}g=`/analytics/thread?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(h)}&chat=${encodeURIComponent(y)}&limit=${encodeURIComponent(p.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[f,h]=[p.get("kind"),p.get("key")];if(!f||!h){v(e,400,{error:"kind and key required"});return}g=`/analytics/job?kind=${encodeURIComponent(f)}&key=${encodeURIComponent(h)}&limit=${encodeURIComponent(p.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[f,h,y]=[p.get("agent"),p.get("channel"),p.get("chat")];if(!f||!h||!y){v(e,400,{error:"agent, channel, chat required"});return}g=`/analytics/conversation?agent=${encodeURIComponent(f)}&channel=${encodeURIComponent(h)}&chat=${encodeURIComponent(y)}&tzOffset=${encodeURIComponent(p.get("tzOffset")||"0")}`}else{let f=p.get("task");if(!f){v(e,400,{error:"task required"});return}g=`/analytics/run/${encodeURIComponent(f)}`}try{await Ka(e,await ie(a.config),d,g)}catch(f){v(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/live/stream"){js(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),p=d.searchParams.get("node"),g=d.searchParams.get("agent"),f=d.searchParams.get("task");if(!p||!g||!f){v(e,400,{error:"node, agent, task query params required"});return}await Ls(t,e,a,p,g,f);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),p=d.searchParams.get("node"),g=d.searchParams.get("agent"),f=d.searchParams.get("task"),h=d.searchParams.get("limit")||"50";if(!p||!g){v(e,400,{error:"node and agent query params required"});return}await Ds(e,a,p,g,f,h);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),p=d.searchParams.get("node"),g=d.searchParams.get("task"),f=d.searchParams.get("kind");if(!p||!g||f!=="cancel"&&f!=="followup"){v(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Os(t,e,a,p,g,f);return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let p=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!p.ok)throw new Error(`HTTP ${p.status}`);let g=await p.json();v(e,200,g)}catch(d){v(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await re(t);try{let p=await Ns(a.config,d);v(e,200,p)}catch(p){v(e,502,{error:p.message||"draft failed"})}return}let u=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(u&&o==="POST"){let d=u[1];if(!Rs(t,e,[`agent:${d}`]))return;await Ps(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",p=d.startsWith("Bearer ")?d.slice(7):"";if(p!==a.token){let g=new ee,f=p?g.verify(p):null;if(!f||!ve(f,"dashboard:write")){v(e,401,{error:"unauthorized"});return}}}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){v(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="GET"&&r==="/events"){let p=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(k=>({name:k.name,url:k.url,token:k.token}))],f={flag:!1},h=[];t.on("close",()=>{f.flag=!0;for(let k of h)try{k.abort()}catch{}});let y=setInterval(()=>{if(!f.flag)try{e.write(`: ping
|
|
13351
14311
|
|
|
13352
|
-
`)}catch{}},15e3);t.on("close",()=>clearInterval(
|
|
14312
|
+
`)}catch{}},15e3);t.on("close",()=>clearInterval(y));for(let k of g)(async()=>{let $={Accept:"text/event-stream"};k.token&&($.Authorization=`Bearer ${k.token}`);let A=new AbortController;h.push(A);try{let w=await fetch(`${k.url.replace(/\/+$/,"")}/events${p?`?${p}`:""}`,{headers:$,signal:A.signal});if(!w.ok||!w.body)return;let j=w.body.getReader(),L=new TextDecoder,D="";for(;!f.flag;){let{done:H,value:Z}=await j.read();if(H)break;D+=L.decode(Z,{stream:!0});let R;for(;(R=D.indexOf(`
|
|
13353
14313
|
|
|
13354
|
-
`))>=0;){let
|
|
14314
|
+
`))>=0;){let J=D.slice(0,R);if(D=D.slice(R+2),f.flag)break;try{e.write(J+`
|
|
13355
14315
|
|
|
13356
|
-
`)}catch{
|
|
13357
|
-
`;
|
|
13358
|
-
data: ${JSON.stringify(
|
|
14316
|
+
`)}catch{f.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),p=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),g=d.searchParams.get("workflowId")||void 0,f=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",h=a.workflowRuns.list({limit:p,workflowId:g}),y=`?limit=${p}${g?`&workflowId=${encodeURIComponent(g)}`:""}${f?"&summary=1":""}`,k=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],$=await Promise.all(k.map(async L=>{let D={};L.token&&(D.Authorization=`Bearer ${L.token}`);try{let H=new AbortController,Z=setTimeout(()=>H.abort(),5e3);try{let R=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${y}`,{headers:D,signal:H.signal});if(!R.ok)return[];let J=await R.json();return Array.isArray(J.runs)?J.runs:[]}finally{clearTimeout(Z)}}catch{return[]}})),A=new Map;for(let L of h)A.set(L.id,L);for(let L of $)for(let D of L)A.set(D.id,D);let w=Array.from(A.values()).sort((L,D)=>L.updatedAt<D.updatedAt?1:-1).slice(0,p),j=f?w.map(L=>Cs(L)):w;v(e,200,{runs:j})}catch(d){v(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let x=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(x){let d=decodeURIComponent(x[1]),p=a.workflowRuns.get(d);if(p){v(e,200,{run:p});return}let g=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(f=>({url:f.url,token:f.token}))];for(let f of g)try{let h={};f.token&&(h.Authorization=`Bearer ${f.token}`);let y=await fetch(`${f.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:h});if(y.ok){v(e,200,await y.json());return}}catch{}v(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let p=a.config.dashboard.daemonUrl.replace(/\/+$/,""),g=await fetch(`${p}/api/actions/builtin`,{headers:d}),f=await g.json().catch(()=>({error:`HTTP ${g.status}`}));v(e,g.status,f)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let b=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(b){try{let d=await re(t).catch(()=>({})),p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let g=a.config.dashboard.daemonUrl.replace(/\/+$/,""),f=await fetch(`${g}/workflows/${encodeURIComponent(b[1])}/run`,{method:"POST",headers:p,body:JSON.stringify(d??{})}),h=await f.json().catch(()=>({error:`HTTP ${f.status}`}));v(e,f.status,h)}catch(d){v(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&nn(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(p,g,f)=>{if(a.token)return!0;let h=Fe(p);if(!h)return!0;let y=new ee().verify(h);if(!y)return v(g,401,{error:"invalid or revoked token"}),!1;for(let k of f)if(!ve(y,k))return v(g,403,{error:`token missing scope: ${k}`,scopes:y.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){v(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){v(e,404,{error:"unknown board"});return}try{let p=typeof d.listMembers=="function"?await d.listMembers():[];v(e,200,p)}catch(p){v(e,502,{error:p.message})}return}let M=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(M&&o==="GET"){let d=a.sources.get(M[1]);if(!d){v(e,404,{error:"unknown board"});return}try{let p=typeof d.listMilestones=="function"?await d.listMilestones():[];v(e,200,p)}catch(p){v(e,502,{error:p.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[,d,p]=E,g=decodeURIComponent(p),f=a.boards.find(A=>A.id===d);if(!f){v(e,404,{error:`unknown board: ${d}`});return}let h=a.sources.get(d);if(!h){v(e,503,{error:`board "${d}" source unavailable`});return}let y=await re(t),k=f.columns.find(A=>A.id===y.to),$=f.columns.find(A=>A.id===y.from);if(!k){v(e,400,{error:`unknown 'to' column: ${y.to}`});return}try{await Ts(h,g,$,k),lt({actor:dt(t),action:"move",boardId:d,itemId:g,payload:{from:y.from,to:y.to}}),v(e,200,{ok:!0})}catch(A){v(e,502,{error:A.message||"transition failed"})}return}if(S){let[,d,p]=S,g=p?decodeURIComponent(p):void 0,f=a.boards.find(y=>y.id===d);if(!f){v(e,404,{error:`unknown board: ${d}`});return}let h=a.sources.get(d);if(!h){v(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!g){let{columns:y,totals:k}=await Ss(f,h,n.searchParams);v(e,200,{columns:y,totals:k});return}if(o==="GET"&&g){try{let y=typeof h.getItem=="function"?await h.getItem(g):null;if(!y){v(e,404,{error:"not found"});return}v(e,200,y)}catch(y){v(e,502,{error:y.message})}return}if(o==="PATCH"&&g){let y=await re(t);try{let k=typeof h.updateItem=="function"?await h.updateItem(g,y):null;if(!k){v(e,501,{error:"update unsupported"});return}lt({actor:dt(t),action:"update",boardId:d,itemId:g,payload:y}),v(e,200,k)}catch(k){v(e,502,{error:k.message})}return}if(o==="POST"&&!g){let y=await re(t);if(!y.title){v(e,400,{error:"title required"});return}if(!h.capabilities.create||!h.create){v(e,400,{error:`source ${h.type} does not support create`});return}try{let k=await h.create({title:y.title,description:y.description,labels:y.labels,assigneeUsernames:y.assigneeUsernames,milestoneTitle:y.milestoneTitle,projectHint:y.projectHint});lt({actor:dt(t),action:"create",boardId:d,itemId:k.id,payload:{title:y.title}}),v(e,201,k)}catch(k){v(e,502,{error:k.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=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"}[d];if(g){e.writeHead(302,{Location:g}),e.end();return}}v(e,404,{error:"not found",path:r})}async function Ss(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let p of t.columns)d[p.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(p=>[p.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),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),u=t.columns.some(d=>d.kind!=="closed"),m=t.columns.some(d=>d.kind==="closed"),x=u?await e.listAll({sinceDays:i,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],b=m?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],_={};for(let d of t.columns)_[d.id]=[];let M=t.columns.find(d=>d.kind==="closed");for(let d of b)M&&_[M.id].push({...d,stage:M.id});let E=t.columns.filter(d=>d.kind!=="closed");for(let d of x){let p=mt(d,E);if(!p)continue;let g=_[p];g&&g.push({...d,stage:p})}if(l)for(let d of Object.keys(_))_[d]=_[d].filter(p=>p.assignee===l);for(let d of Object.keys(_))_[d].sort((p,g)=>{let f=(p.priority??99)-(g.priority??99);return f!==0?f:(g.updatedAt||"").localeCompare(p.updatedAt||"")});let S=Object.fromEntries(Object.entries(_).map(([d,p])=>[d,p.length]));return{columns:_,totals:S}}async function Ts(t,e,a,n){let r=ht(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 Cs(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 As(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 Tt(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function lt(t){try{let e=ke(process.cwd(),".agentx");on(e)||bs(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
14317
|
+
`;vs(ke(e,"board-audit.jsonl"),a)}catch{}}function dt(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}async function Ms(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,c,u,m]=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 x=await i.json();if(o.agents=x.map(b=>({id:b.id,name:b.name,tier:b.tier,model:b.model,skillCount:Number.isFinite(b.skillCount)?b.skillCount:void 0,active:b.active||0,total:b.total||0,errors:b.errors||0,lastActive:b.lastActive,lastSummary:b.lastSummary,hourlyTasks:Array.isArray(b.hourlyTasks)?b.hourlyTasks:void 0,runningTasks:Array.isArray(b.runningTasks)?b.runningTasks:[]})),l&&l.ok){let b=await l.json();o.uptimeSec=b.uptime,o.name=b.node?.name||b.node?.id||t,o.id=b.node?.id||t,b.usage&&(o.usage=b.usage)}if(u&&u.ok){let b=await u.json();o.crons=b.map(_=>({id:_.id,enabled:_.enabled===!0,schedule:String(_.schedule||""),timezone:_.timezone,agent:String(_.agent||""),model:_.model,nextRun:_.nextRun,retryPending:_.retryPending===!0,consecutiveErrors:Number(_.consecutiveErrors)||0}))}if(m&&m.ok){let b=await m.json();o.cronRuns=Array.isArray(b.runs)?b.runs:[]}o.reachable=!0,o._peers=Array.isArray(c&&await $s(c))?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var De=null;function Is(t){if(De)return De;let e=ke(process.cwd(),".agentx/wiki");return De=Nt({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),De}var ct=new WeakMap;async function $s(t){if(ct.has(t))return ct.get(t);try{let e=t.ok?await t.json():null;return ct.set(t,e),e}catch{return null}}async function Oe(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 ie(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 l=s.url.replace(/\/+$/,"");r.has(l)||r.set(l,{name:s.name,url:l,token:s.token})}let o=await Oe(n,a.token,e);for(let s of o)r.has(s.url)||r.set(s.url,s);return[...r.values()]}async function pt(t,e){let a=new AbortController,n=setTimeout(()=>a.abort(),3e3);try{let r=await ie(t,a.signal),o=await Promise.all(r.map(s=>Ms(s.url,s.token,a.signal,e)));return{ts:new Date().toISOString(),nodes:o}}finally{clearTimeout(n)}}function js(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}
|
|
14318
|
+
data: ${JSON.stringify(i)}
|
|
13359
14319
|
|
|
13360
|
-
`)},o=async()=>{try{let
|
|
14320
|
+
`)},o=async()=>{try{let l=await pt(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 Ls(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),l=new Set;l.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let _ of a.config.dashboard.daemons)l.add(_.url.replace(/\/+$/,""));try{let _=await Oe(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let M of _)l.add(M.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){v(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(_=>_.url.replace(/\/+$/,"")===s)?.token,c={Accept:"text/event-stream"};i&&(c.Authorization=`Bearer ${i}`);let u=new AbortController,m;try{m=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:u.signal})}catch(_){v(e,502,{error:_.message||"upstream connect failed"});return}if(!m.ok||!m.body){v(e,m.status||502,{error:`upstream HTTP ${m.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 x=m.body.getReader();(async()=>{try{for(;;){let{value:_,done:M}=await x.read();if(M)break;_&&e.write(_)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{u.abort();try{e.end()}catch{}})}function Rs(t,e,a){let n=Fe(t);if(!n)return v(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ee().verify(n);if(!r)return v(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ve(r,o))return v(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Ps(t,e,a,n){let r=a.agents?.[n];if(!r){v(e,404,{error:"unknown agent"});return}if(r.access!=="public"){v(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await re(t)}catch{v(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){v(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 c=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||{}}})}),u=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(u)}catch(c){v(e,502,{error:c.message||"upstream call failed"})}}async function Ds(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),l=new Set;l.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let m of e.config.dashboard.daemons)l.add(m.url.replace(/\/+$/,""));try{let m=await Oe(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let x of m)l.add(x.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){v(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(m=>m.url.replace(/\/+$/,"")===s)?.token,c={Accept:"application/json"};i&&(c.Authorization=`Bearer ${i}`);let u=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let m=await fetch(`${s}${u}`,{headers:c}),x=await m.text();t.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),t.end(x)}catch(m){v(t,502,{error:m.message||"upstream fetch failed"})}}async function Os(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),l=new Set;l.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let m of a.config.dashboard.daemons)l.add(m.url.replace(/\/+$/,""));try{let m=await Oe(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let x of m)l.add(x.url.replace(/\/+$/,""))}catch{}if(!l.has(s)){v(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(m=>m.url.replace(/\/+$/,"")===s)?.token,c={"Content-Type":"application/json",Accept:"application/json"};i&&(c.Authorization=`Bearer ${i}`);let u="{}";try{let m=await re(t);u=m?JSON.stringify(m):"{}"}catch{}try{let m=await fetch(`${s}/api/tasks/${encodeURIComponent(r)}/${o}`,{method:"POST",headers:c,body:u}),x=await m.text();e.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}),e.end(x)}catch(m){v(e,502,{error:m.message||"upstream fetch failed"})}}var Hs=`
|
|
13361
14321
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
13362
14322
|
|
|
13363
14323
|
Title pattern:
|
|
@@ -13389,16 +14349,16 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
13389
14349
|
Shape:
|
|
13390
14350
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
13391
14351
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
13392
|
-
`;async function
|
|
14352
|
+
`;async function Ns(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):
|
|
13393
14353
|
- ${r.knownLabels.slice(0,60).join(`
|
|
13394
14354
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
13395
|
-
`),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",
|
|
14355
|
+
`),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:Hs}})});if(!i.ok)throw new Error(`daemon /task HTTP ${i.status}: ${await i.text().catch(()=>"")}`);let c=await i.json();if(c.error)throw new Error(String(c.error));let u=(c.content||"").toString(),m=Bs(u);if(!m||typeof m.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+u.slice(0,400));let x=Array.isArray(m.labels)?m.labels.filter(b=>typeof b=="string"):[];return r.primaryLabel&&!x.includes(r.primaryLabel)&&x.unshift(r.primaryLabel),r.columnLabel&&!x.includes(r.columnLabel)&&x.unshift(r.columnLabel),{title:m.title.trim(),description:(m.description||"").toString(),labels:x,assigneeUsername:typeof m.assigneeUsername=="string"?m.assigneeUsername:void 0,kind:typeof m.kind=="string"?m.kind:void 0,raw:u}}function Bs(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 zs(t){let e=ks(ws(import.meta.url));return ke(e,t)}async function qs(t){return ys(t)}function v(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function re(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function sn(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function O(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:sn(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 Us(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=Ta(r);l&&s.push({nodeId:o,snap:l});let i=(a.config.dashboard?.daemons||[]).filter(c=>c.url);await Promise.all(i.map(async c=>{let u=ut(c.url.replace(/\/+$/,""),a.config);if(u)try{let m=new AbortController,x=setTimeout(()=>m.abort(),8e3);try{let b=await fetch(`${u.url}/api/admin/activity-graph?hours=${r}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...u.token?{Authorization:`Bearer ${u.token}`}:{}},signal:m.signal});if(!b.ok)return;let _=await b.json();s.push({nodeId:c.name||c.url,snap:_})}finally{clearTimeout(x)}}catch{}})),v(e,200,Ca(s))}async function Fs(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 m=process.env.HOME||"",x=[m&&`${m}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),b=x.find(_=>on(_));if(!b){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:x}));return}r="tail",o=["-F","-n","200",b]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
|
|
13396
14356
|
|
|
13397
|
-
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),
|
|
13398
|
-
`))>=0;){let
|
|
13399
|
-
data: ${
|
|
14357
|
+
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),l="",i=m=>{l+=m.toString("utf8");let x;for(;(x=l.indexOf(`
|
|
14358
|
+
`))>=0;){let b=l.slice(0,x).replace(/\r$/,"");l=l.slice(x+1);try{e.write(`event: line
|
|
14359
|
+
data: ${b.replace(/\n/g," ")}
|
|
13400
14360
|
|
|
13401
|
-
`)}catch{}}};s.stdout?.on("data",
|
|
14361
|
+
`)}catch{}}};s.stdout?.on("data",i),s.stderr?.on("data",i);let c=setInterval(()=>{try{e.write(`: hb
|
|
13402
14362
|
|
|
13403
|
-
`)}catch{}},15e3),
|
|
13404
|
-
//# sourceMappingURL=board-dashboard-
|
|
14363
|
+
`)}catch{}},15e3),u=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",u),s.on("exit",u),s.on("error",u)}async function rn(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),l=o!=="GET"&&o!=="HEAD"?await new Promise((m,x)=>{let b=[];t.on("data",_=>b.push(_)),t.on("end",()=>m(Buffer.concat(b))),t.on("error",x)}):void 0,i={},c=t.headers["content-type"];c&&(i["Content-Type"]=Array.isArray(c)?c[0]:c);let u=t.headers["x-requested-with"];u&&(i["X-Requested-With"]=Array.isArray(u)?u[0]:u),a.token&&(i.Authorization=`Bearer ${a.token}`),i["X-Agentx-Peer"]="primary";try{let m=await fetch(r,{method:o,headers:i,body:l&&l.length>0?l:void 0}),x=Buffer.from(await m.arrayBuffer());e.writeHead(m.status,{"Content-Type":m.headers.get("content-type")||"application/json","Cache-Control":"no-store","Access-Control-Allow-Origin":"*"}),e.end(x)}catch(m){v(e,502,{error:`proxy to peer failed: ${m?.message||m}`,target:r})}}function ut(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:sn(n),token:n.dashboardToken||n.token}:null}export{Rd as startBoardDashboard};
|
|
14364
|
+
//# sourceMappingURL=board-dashboard-TTMAYRLG.js.map
|