@mgsoftwarebv/mg-dashboard-mcp 3.10.0 → 3.10.1
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/index.js +23 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/proxy-mode.ts","../src/trigger-tools.ts","../src/agent-tools.ts","../src/index.ts"],"names":["args","proxyUrl","apiKey","Client","sshExec","getServerConnection","name","text","getArg","runProxyMode","runProcess","spawn","join","existsSync","SshClient","lines","content","elapsed","inner","cmd","result","acceptable","stageIds","Server","ListToolsRequestSchema","CallToolRequestSchema","createHttpServer","StdioServerTransport"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAA,kBAAA,GAAA,EAAA;AAAA,QAAA,CAAA,kBAAA,EAAA;AAAA,EAAA,YAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAyDA,SAAS,MAAA,CAAOA,OAAgB,IAAA,EAAkC;AAChE,EAAA,OAAOA,MAAK,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,UAAA,CAAW,KAAK,IAAI,CAAA,CAAA,CAAG,CAAC,CAAA,EAAG,MAAM,GAAG,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AACnF;AAEA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,GAAG,OAAO,IAAA;AAClC,EAAA,MAAM,OAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,IAAQ,OAAA,CAAQ,IAAI,WAAA,IAAe,EAAA;AAC5D,EAAA,OAAO,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AACjC;AAEA,SAAS,kBAAkB,KAAA,EAAqD;AAC9E,EAAA,MAAM,SAAA,GAAY,WAAW,KAAK,CAAA;AAClC,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAA,GAAU,SAAA;AAAA,EACZ,CAAA,MAAA,IAAW,UAAA,CAAW,CAAA,EAAG,SAAS,MAAM,CAAA,EAAG;AACzC,IAAA,OAAA,GAAU,GAAG,SAAS,CAAA,IAAA,CAAA;AAAA,EACxB,CAAA,MAAA,IAAW,UAAA,CAAW,SAAS,CAAA,EAAG;AAChC,IAAA,OAAA,GAAU,SAAA;AAAA,EACZ,CAAA,MAAO;AACL,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,SAAS,CAAA,aAAA,EAAgB,SAAS,CAAA,KAAA,CAAO,CAAA;AAAA,EACtF;AACA,EAAA,MAAM,OAAA,GAAU,YAAA,CAAa,OAAA,EAAS,MAAM,EAAE,IAAA,EAAK;AACnD,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,OAAO,CAAA,CAAE,CAAA;AACxE,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC5B;AAEA,SAAS,UAAA,CACP,OAAA,EACA,IAAA,EACA,OAAA,GAA8B,EAAC,EAC4B;AAC3D,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM,EAAE,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM,CAAA,EAAG,CAAA;AACtE,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAM;AAC7B,MAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,IACvB,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAM;AAC7B,MAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,IACvB,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,OAAA,CAAQ,EAAE,QAAQ,MAAA,EAAQ,MAAA,GAAS,OAAO,GAAG,CAAA,EAAG,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,IAC5D,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAA,IAAQ,IAAI,CAAA;AAAA,IAC9C,CAAC,CAAA;AACD,IAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW;AAC/B,MAAA,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA;AAC/B,MAAA,KAAA,CAAM,MAAM,GAAA,EAAI;AAAA,IAClB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,MAAM,GAAA,EAAI;AAAA,IAClB;AAAA,EACF,CAAC,CAAA;AACH;AAYA,SAAS,kBAAkBC,SAAAA,EAA0B;AAGnD,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAIA,SAAQ,CAAA;AAC1B,EAAA,OAAO,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,EAAE,IAAI,CAAA,CAAA;AACjC;AAEA,eAAe,gBAAA,CACbA,SAAAA,EACAC,OAAAA,EACA,OAAA,EACA,OAAA,EAC0B;AAC1B,EAAA,MAAM,IAAA,GAAO,kBAAkBD,SAAQ,CAAA;AAEvC,EAAA,MAAM,YAAA,GAAe,MAAM,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,sBAAA,CAAA,EAA0B;AAAA,IAChE,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,IAC9C,IAAA,EAAM;AAAA,GACP,CAAA;AACD,EAAA,IAAI,CAAC,aAAa,EAAA,EAAI;AACpB,IAAA,MAAM,MAAM,MAAM,YAAA,CAAa,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AACpD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,aAAa,MAAM,CAAA,GAAA,EAAM,GAAG,CAAA,CAAE,CAAA;AAAA,EAC7E;AACA,EAAA,MAAM,SAAA,GAAa,MAAM,YAAA,CAAa,IAAA,EAAK;AAM3C,EAAA,MAAM,OAAO,MAAM,UAAA;AAAA,IACjB,YAAA;AAAA,IACA,CAAC,MAAM,MAAA,EAAQ,IAAA,EAAM,SAAS,IAAA,EAAM,SAAA,CAAU,WAAW,IAAI,CAAA;AAAA,IAC7D,EAAE,KAAA,EAAO,SAAA,CAAU,KAAA;AAAM,GAC3B;AACA,EAAA,IAAI,IAAA,CAAK,SAAS,CAAA,IAAK,CAAC,KAAK,MAAA,CAAO,QAAA,CAAS,qBAAqB,CAAA,EAAG;AACnE,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,KAAK,IAAI,CAAA,mFAAA,EACa,KAAK,MAAA,CAAO,IAAA,MAAU,SAAS,CAAA;AAAA,KACvF;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,MAAM,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,mBAAA,CAAA,EAAuB;AAAA,IAC1D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,IAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,cAAc,SAAA,CAAU,YAAA;AAAA,MACxB,OAAA,EAASC,OAAAA;AAAA,MACT,MAAA,EAAQ,OAAA;AAAA,MACR,WAAW,IAAA,CAAK;AAAA,KACjB;AAAA,GACF,CAAA;AACD,EAAA,IAAI,CAAC,UAAU,EAAA,EAAI;AACjB,IAAA,MAAM,MAAM,MAAM,SAAA,CAAU,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AACjD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,UAAU,MAAM,CAAA,GAAA,EAAM,GAAG,CAAA,CAAE,CAAA;AAAA,EACvE;AACA,EAAA,MAAM,QAAA,GAAY,MAAM,SAAA,CAAU,IAAA,EAAK;AAMvC,EAAA,OAAO;AAAA,IACL,OAAO,QAAA,CAAS,KAAA;AAAA,IAChB,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,SAAS,kBAAA,GAAqB,GAAA;AAAA,IACtD,cAAc,QAAA,CAAS;AAAA,GACzB;AACF;AAWA,eAAe,SAAA,CAAU,SAAA,EAA4BD,SAAAA,EAAkB,OAAA,EAAyC;AAC9G,EAAA,IAAI,eAAe,SAAA,CAAU,KAAA;AAC7B,EAAA,MAAM,cAAA,GAAyC;AAAA,IAC7C,aAAA,EAAe,UAAU,YAAY,CAAA;AAAA,GACvC;AAEA,EAAA,MAAM,oBAAoB,IAAI,6BAAA,CAA8B,IAAI,GAAA,CAAIA,SAAQ,CAAA,EAAG;AAAA,IAC7E,WAAA,EAAa,EAAE,OAAA,EAAS,cAAA;AAAe,GACxC,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,IAAIE,QAAA,CAAO,EAAE,MAAM,+BAAA,EAAiC,OAAA,EAAS,SAAS,CAAA;AAGvF,EAAA,MAAM,eAAA,GAAkB,CAAC,MAAA,KAA4B;AACnD,IAAA,MAAM,cAAA,GAAiB,KAAK,GAAA,CAAI,GAAA,EAAQ,OAAO,SAAA,GAAY,IAAA,CAAK,GAAA,EAAI,GAAI,IAAO,CAAA;AAC/E,IAAA,UAAA,CAAW,YAAY;AACrB,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,EAAQ;AAC5B,QAAA,YAAA,GAAe,KAAA,CAAM,KAAA;AACrB,QAAA,cAAA,CAAe,aAAA,GAAgB,UAAU,YAAY,CAAA,CAAA;AACrD,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,8BAAA,EAAiC,KAAA,CAAM,YAAY,CAAA,CAAA,CAAG,CAAA;AACpE,QAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,MACvB,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,iCAAiC,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAEjG,QAAA,UAAA,CAAW,MAAM,eAAA,CAAgB,EAAE,GAAG,MAAA,EAAQ,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,GAAA,EAAQ,CAAA,EAAG,GAAM,CAAA;AAAA,MACzF;AAAA,IACF,CAAA,EAAG,cAAc,CAAA,CAAE,KAAA,EAAM;AAAA,EAC3B,CAAA;AACA,EAAA,eAAA,CAAgB,SAAS,CAAA;AAGzB,EAAA,MAAM,cAAc,IAAI,MAAA;AAAA,IACtB,EAAE,IAAA,EAAM,wBAAA,EAA0B,OAAA,EAAS,OAAA,EAAQ;AAAA,IACnD,EAAE,YAAA,EAAc,EAAE,KAAA,EAAO,EAAC,EAAG,OAAA,EAAS,EAAC,EAAG,WAAW,EAAC,EAAG,OAAA,EAAS,IAAG;AAAE,GACzE;AAEA,EAAA,MAAM,cAAA,GACJ,CAAC,YAAA,KACD,OAAO,YACL,QAAA,CAAS,OAAA;AAAA,IACP,OAAA;AAAA,IACA;AAAA,GACF;AAKJ,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,sBAAA;AAAA,IACA,eAAe,qBAAqB;AAAA,GACtC;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,qBAAA;AAAA,IACA,eAAe,oBAAoB;AAAA,GACrC;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,wBAAA;AAAA,IACA,eAAe,uBAAuB;AAAA,GACxC;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,sBAAA;AAAA,IACA,eAAe,qBAAqB;AAAA,GACtC;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,0BAAA;AAAA,IACA,eAAe,yBAAyB;AAAA,GAC1C;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,yBAAA;AAAA,IACA,eAAe,wBAAwB;AAAA,GACzC;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,kCAAA;AAAA,IACA,eAAe,iCAAiC;AAAA,GAClD;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,sBAAA;AAAA,IACA,eAAe,iBAAiB;AAAA,GAClC;AACA,EAAA,WAAA,CAAY,iBAAA;AAAA,IACV,wBAAA;AAAA,IACA,eAAe,iBAAiB;AAAA,GAClC;AAGA,EAAA,WAAA,CAAY,sBAAA,GAAyB,OAAO,OAAA,KAAqB;AAC/D,IAAA,OAAO,MAAM,QAAA,CAAS,OAAA;AAAA,MACpB,OAAA;AAAA;AAAA;AAAA,MAGA;AAAA,KACF;AAAA,EACF,CAAA;AAEA,EAAA,WAAA,CAAY,2BAAA,GAA8B,OAAO,YAAA,KAA0B;AACzE,IAAA,MAAM,QAAA,CAAS,aAAa,YAA2D,CAAA;AAAA,EACzF,CAAA;AAEA,EAAA,MAAM,QAAA,CAAS,QAAQ,iBAAiB,CAAA;AAGxC,EAAA,QAAA,CAAS,2BAAA,GAA8B,OAAO,YAAA,KAA0B;AACtE,IAAA,MAAM,WAAA,CAAY,aAAa,YAA8D,CAAA;AAAA,EAC/F,CAAA;AAEA,EAAA,MAAM,WAAA,CAAY,OAAA,CAAQ,IAAI,oBAAA,EAAsB,CAAA;AACpD,EAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,8CAAA,EAA4CF,SAAQ,CAAA,CAAE,CAAA;AAOpE,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,IAAA,MAAM,SAAA,GAAY,WAAA,CAAY,MAAM,MAAA,EAAW,UAAa,CAAA;AAC5D,IAAA,MAAM,OAAO,MAAM;AACjB,MAAA,aAAA,CAAc,SAAS,CAAA;AACvB,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AACA,IAAA,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,IAAI,CAAA;AAChC,IAAA,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AAC9B,IAAA,OAAA,CAAQ,IAAA,CAAK,UAAU,IAAI,CAAA;AAC3B,IAAA,OAAA,CAAQ,IAAA,CAAK,WAAW,IAAI,CAAA;AAAA,EAC9B,CAAC,CAAA;AACH;AAMA,eAAsB,aAAaD,KAAAA,EAA+B;AAChE,EAAA,MAAMC,YAAW,MAAA,CAAOD,KAAAA,EAAM,WAAW,CAAA,IAAK,QAAQ,GAAA,CAAI,sBAAA;AAC1D,EAAA,MAAME,UAAS,MAAA,CAAOF,KAAAA,EAAM,SAAS,CAAA,IAAK,QAAQ,GAAA,CAAI,oBAAA;AACtD,EAAA,MAAM,SAAS,MAAA,CAAOA,KAAAA,EAAM,SAAS,CAAA,IAAK,QAAQ,GAAA,CAAI,oBAAA;AAEtD,EAAA,IAAI,CAACC,SAAAA,EAAU;AACb,IAAA,OAAA,CAAQ,MAAM,yDAAyD,CAAA;AACvE,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,IAAI,CAACC,OAAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,MAAM,mEAAmE,CAAA;AACjF,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,MAAM,mEAAmE,CAAA;AACjF,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,6CAAA,EAA2CD,SAAQ,CAAA,CAAE,CAAA;AAEnE,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAW,kBAAkB,MAAM,CAAA;AAAA,EACrC,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,WAAW,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC3E,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,OAAA,GAAU,MAAM,gBAAA,CAAiBA,SAAAA,EAAUC,SAAQ,QAAA,CAAS,OAAA,EAAS,SAAS,OAAO,CAAA;AAE3F,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI;AACF,IAAA,SAAA,GAAY,MAAM,OAAA,EAAQ;AAAA,EAC5B,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,6BAA6B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC7F,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,0BAAA,EAA6B,SAAA,CAAU,YAAY,CAAA,CAAA,CAAG,CAAA;AACpE,EAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAA,CAAK,KAAA,CAAA,CAAO,SAAA,CAAU,SAAA,GAAY,IAAA,CAAK,GAAA,EAAI,IAAK,GAAK,CAAC,CAAA,IAAA,CAAM,CAAA;AAErG,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,CAAU,SAAA,EAAWD,SAAAA,EAAU,OAAO,CAAA;AAAA,EAC9C,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC3F,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;AA3XA,IAAA,eAAA,GAAA,KAAA,CAAA;AAAA,EAAA,mBAAA,GAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACgFA,IAAM,iBAAA,uBAAwB,GAAA,CAAI;AAAA,EAChC,WAAA;AAAA,EAAa,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,UAAA;AAAA,EAClC,gBAAA;AAAA,EAAkB,aAAA;AAAA,EAAe;AACnC,CAAC,CAAA;AAOD,IAAM,iBAAA,GAAoB,sCAAA;AAG1B,IAAM,eAAA,GAAkB,+BAAA;AAExB,IAAM,YAAA,GAAe,GAAG,eAAe,CAAA,WAAA,CAAA;AACvC,IAAM,YAAA,GAAe,GAAG,eAAe,CAAA,SAAA,CAAA;AAOhC,IAAM,aAAA,GAAgB;AAAA,EAC3B;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,EACE,qIAAA;AAAA,IAEF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,YAAY;AAAC;AACf,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,EACE,+GAAA;AAAA,IAEF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2DAAA,EAA4D;AAAA,QACpG,MAAA,EAAQ;AAAA,UACN,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACf;AAAA,QACA,cAAA,EAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gDAAA,EAAiD;AAAA,QAChG,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0CAAA;AAA2C,OACnF;AAAA,MACA,QAAA,EAAU,CAAC,SAAS;AAAA;AACtB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,oBAAA;AAAA,IACN,WAAA,EACE,sJAAA;AAAA,IAEF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACzE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yBAAA;AAA0B,OAClE;AAAA,MACA,QAAA,EAAU,CAAC,SAAA,EAAW,OAAO;AAAA;AAC/B,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,mBAAA;AAAA,IACN,WAAA,EACE,mKAAA;AAAA,IAEF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACzE,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0DAAA,EAA2D;AAAA,QAClG,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,oDAAA,EAAqD;AAAA,QAC7F,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0DAAA;AAA2D,OACzG;AAAA,MACA,QAAA,EAAU,CAAC,SAAA,EAAW,QAAQ;AAAA;AAChC,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,oBAAA;AAAA,IACN,WAAA,EAAa,4FAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACzE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,mCAAA;AAAoC,OAC5E;AAAA,MACA,QAAA,EAAU,CAAC,SAAA,EAAW,OAAO;AAAA;AAC/B;AAEJ,CAAA;AAGO,IAAM,kBAAA,GAAqB,IAAI,GAAA,CAAI,aAAA,CAAc,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAGnE,IAAM,uBAAA,GAAkD;AAAA,EAC7D,cAAA,EAAgB,OAAA;AAAA,EAChB,cAAA,EAAgB,OAAA;AAAA,EAChB,oBAAA,EAAsB,OAAA;AAAA,EACtB,mBAAA,EAAqB,OAAA;AAAA,EACrB,oBAAA,EAAsB;AACxB,CAAA;AAgBA,eAAe,gBAAA,CACb,WAAA,EACA,IAAA,EACA,KAAA,EACAG,QAAAA,EAC0B;AAC1B,EAAA,MAAM,GAAA,GAAM,2HAES,WAAW,CAAA,4BAAA,CAAA;AAEhC,EAAA,MAAM,GAAA,GAAM;AAAA,IACV,uBAAuB,YAAY,CAAA,iDAAA,CAAA;AAAA,IACnC,CAAA,mBAAA,EAAsB,YAAY,CAAA,qCAAA,EAAwC,GAAG,CAAA,kCAAA,CAAA;AAAA,IAC7E;AAAA,GACF,CAAE,KAAK,MAAM,CAAA;AAEb,EAAA,MAAM,MAAA,GAAS,MAAMA,QAAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC7C,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,IAAA,EAAK;AAClC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AAEjC,EAAA,MAAM,OAAO,MAAA,GAAS,CAAA,GAAI,OAAO,SAAA,CAAU,CAAA,EAAG,MAAM,CAAA,GAAI,EAAA;AACxD,EAAA,MAAMF,UAAS,MAAA,GAAS,CAAA,GAAI,OAAO,SAAA,CAAU,MAAA,GAAS,CAAC,CAAA,GAAI,EAAA;AAE3D,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kCAAkC,YAAY,CAAA,2BAAA;AAAA,KAChD;AAAA,EACF;AACA,EAAA,IAAI,CAACA,OAAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,sCAAsC,WAAW,CAAA,2DAAA;AAAA,KAEnD;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAAA,OAAAA,EAAO;AACxB;AAMA,eAAe,YAAA,CACb,KAAA,EACA,IAAA,EACA,KAAA,EACAE,QAAAA,EACiB;AACjB,EAAA,MAAM,GAAA,GAAM,mGAEgB,KAAK,CAAA,mGAAA,CAAA;AAIjC,EAAA,MAAM,GAAA,GAAM,CAAA,aAAA,EAAgB,YAAY,CAAA,qCAAA,EAAwC,GAAG,CAAA,aAAA,CAAA;AACnF,EAAA,MAAM,MAAA,GAAS,MAAMA,QAAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC7C,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,IAAA,EAAK;AAElC,EAAA,IAAI,CAAC,QAAQ,OAAO,EAAA;AAEpB,EAAA,OAAO,OAAO,KAAA,CAAM,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS;AACtC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,IAAA,MAAM,SAAS,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA,EAAI,OAAO,CAAC,CAAA;AACvC,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AAC5B,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,CAAC,CAAA,KAAM,GAAA;AAC7B,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AACvB,IAAA,MAAM,IAAA,GAAO,EAAA,GAAK,EAAA,CAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA,IAAK,EAAA,GAAK,EAAA;AAC5D,IAAA,MAAM,MAAA,GAAS,UAAU,GAAA,GAAM,GAAA;AAC/B,IAAA,OAAO,GAAG,MAAM,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,KAAK,KAAK,OAAO,CAAA,CAAA;AAAA,EAC/C,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACd;AAMA,eAAe,WACb,IAAA,EACA,KAAA,EACAA,UACA,QAAA,EACA,MAAA,EACA,MACA,IAAA,EACiB;AACjB,EAAA,MAAM,QAAQ,CAAC,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,cAAc,IAAI,CAAA;AACrD,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,MAAM,MAAM,CAAA;AAC7C,EAAA,KAAA,CAAM,KAAK,CAAA,kBAAA,EAAqB,QAAA,CAAS,IAAI,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA;AACvD,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,0BAAA,EAA6B,QAAA,CAAS,MAAM,CAAA,CAAA,CAAG,CAAA;AAC1D,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,KAAA,CAAM,KAAK,qCAAqC,CAAA;AAChD,IAAA,KAAA,CAAM,KAAK,CAAA,IAAA,EAAO,IAAA,CAAK,QAAQ,IAAA,EAAM,OAAO,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EAClD;AAEA,EAAA,MAAM,MAAA,GAAS,MAAMA,QAAAA,CAAQ,IAAA,EAAM,MAAM,IAAA,CAAK,GAAG,GAAG,KAAK,CAAA;AACzD,EAAA,IAAI,MAAA,CAAO,QAAA,KAAa,CAAA,IAAK,CAAC,OAAO,MAAA,EAAQ;AAC3C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,GAAA,EAAM,OAAO,MAAA,IAAU,CAAA,UAAA,EAAa,MAAA,CAAO,QAAQ,CAAA,CAAE,CAAA;AAAA,KACrG;AAAA,EACF;AACA,EAAA,OAAO,MAAA,CAAO,MAAA;AAChB;AAMA,SAAS,gBAAgB,IAAA,EAAgC;AACvD,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,eAAA;AAE9B,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM;AAC5B,IAAA,MAAM,QAAA,GAAW,CAAA,CAAE,UAAA,IAAc,IAAA,GAAO,CAAA,EAAA,CAAI,CAAA,CAAE,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA,GAAM,GAAA;AACjF,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,MAAA,GAAS,SAAA,GAAY,EAAA;AACpC,IAAA,MAAM,OAAA,GAAU,CAAA,CAAE,SAAA,GAAY,IAAI,KAAK,CAAA,CAAE,SAAS,CAAA,CAAE,cAAA,CAAe,OAAA,EAAS,EAAE,QAAA,EAAU,kBAAA,EAAoB,CAAA,GAAI,EAAA;AAChH,IAAA,OAAO,CAAA,EAAG,EAAE,EAAE,CAAA,EAAA,EAAK,EAAE,cAAA,CAAe,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,QAAA,CAAS,QAAA,CAAS,CAAC,CAAC,CAAA,EAAA,EAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA;AAAA,EACpH,CAAC,CAAA;AAED,EAAA,OAAO,GAAG,IAAA,CAAK,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,OAAO,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,QAAA,CAAS,OAAO,EAAE,CAAC,KAAK,UAAA,CAAW,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,CAAA,GAChG,IAAI,MAAA,CAAO,GAAG,IAAI,IAAA,GAClB,KAAA,CAAM,KAAK,IAAI,CAAA;AACnB;AAEA,SAAS,gBAAgB,GAAA,EAA+B;AACtD,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,QAAA,CAAS,IAAA,CAAK,CAAA,QAAA,EAAW,GAAA,CAAI,EAAE,CAAA,IAAA,CAAM,CAAA;AACrC,EAAA,QAAA,CAAS,IAAA,CAAK,CAAA,UAAA,EAAa,GAAA,CAAI,cAAc,CAAA,CAAE,CAAA;AAC/C,EAAA,QAAA,CAAS,IAAA,CAAK,CAAA,UAAA,EAAa,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACvC,EAAA,QAAA,CAAS,IAAA,CAAK,CAAA,UAAA,EAAa,GAAA,CAAI,OAAA,IAAW,GAAG,CAAA,CAAE,CAAA;AAE/C,EAAA,IAAI,IAAI,SAAA,EAAW,QAAA,CAAS,IAAA,CAAK,CAAA,UAAA,EAAa,IAAI,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,eAAe,OAAA,EAAS,EAAE,UAAU,kBAAA,EAAoB,CAAC,CAAA,CAAE,CAAA;AACjI,EAAA,IAAI,IAAI,UAAA,EAAY,QAAA,CAAS,IAAA,CAAK,CAAA,UAAA,EAAa,IAAI,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,CAAE,eAAe,OAAA,EAAS,EAAE,UAAU,kBAAA,EAAoB,CAAC,CAAA,CAAE,CAAA;AACnI,EAAA,IAAI,GAAA,CAAI,UAAA,IAAc,IAAA,EAAM,QAAA,CAAS,IAAA,CAAK,CAAA,UAAA,EAAA,CAAc,GAAA,CAAI,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAE5F,EAAA,IAAI,GAAA,CAAI,YAAY,MAAA,EAAW;AAC7B,IAAA,MAAM,UAAA,GAAa,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,GACtC,GAAA,CAAI,OAAA,GACJ,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA;AACvC,IAAA,QAAA,CAAS,IAAA,CAAK,EAAA,EAAI,iBAAA,EAAmB,UAAU,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,GAAA,CAAI,WAAW,MAAA,EAAW;AAC5B,IAAA,MAAM,SAAA,GAAY,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,GACpC,GAAA,CAAI,MAAA,GACJ,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA;AACtC,IAAA,QAAA,CAAS,IAAA,CAAK,EAAA,EAAI,gBAAA,EAAkB,SAAS,CAAA;AAAA,EAC/C;AAEA,EAAA,IAAI,GAAA,CAAI,QAAA,IAAY,GAAA,CAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AAC3C,IAAA,KAAA,MAAW,OAAA,IAAW,IAAI,QAAA,EAAU;AAClC,MAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,QAAA,QAAA,CAAS,IAAA;AAAA,UACP,EAAA;AAAA,UACA,CAAA,WAAA,EAAc,QAAQ,EAAE,CAAA,KAAA,CAAA;AAAA,UACxB,CAAA,EAAG,QAAQ,KAAA,CAAM,IAAA,IAAQ,OAAO,CAAA,EAAA,EAAK,OAAA,CAAQ,MAAM,OAAO,CAAA;AAAA,SAC5D;AACA,QAAA,IAAI,OAAA,CAAQ,MAAM,UAAA,EAAY;AAC5B,UAAA,QAAA,CAAS,IAAA,CAAK,EAAA,EAAI,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAA;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,QAAA,CAAS,KAAK,IAAI,CAAA;AAC3B;AAeA,eAAsB,iBAAA,CACpB,IAAA,EACAJ,KAAAA,EACA,IAAA,EACqB;AACrB,EAAA,MAAM,EAAE,OAAA,EAAAI,QAAAA,EAAS,mBAAA,EAAAC,sBAAoB,GAAI,IAAA;AACzC,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAMA,qBAAoB,iBAAiB,CAAA;AAEnE,EAAA,QAAQ,IAAA;AAAM;AAAA,IAEZ,KAAK,cAAA,EAAgB;AACnB,MAAA,MAAM,GAAA,GAAM,oDAAA;AACZ,MAAA,MAAM,GAAA,GAAM,CAAA,aAAA,EAAgB,YAAY,CAAA,qCAAA,EAAwC,GAAG,CAAA,aAAA,CAAA;AAEnF,MAAA,MAAM,MAAA,GAAS,MAAMD,QAAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC7C,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,IAAA,EAAK;AAElC,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,gCAAA,EAAkC,CAAA,EAAE;AAAA,MAC/E;AAEA,MAAA,MAAM,MAAA,GAAS,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,EAAE,CAAC,CAAA,MAAA,CAAA;AACnC,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA;AACzB,MAAA,MAAM,QAAQ,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS;AAC7C,QAAA,MAAM,CAAC,IAAA,EAAME,KAAI,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AACnC,QAAA,OAAO,CAAA,EAAA,CAAI,QAAQ,EAAA,EAAI,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAKA,SAAQ,EAAE,CAAA,CAAA;AAAA,MAClD,CAAC,CAAA;AAED,MAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,GAAG,MAAM;AAAA,EAAK,GAAG;AAAA,EAAK,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,IACvF;AAAA;AAAA,IAGA,KAAK,cAAA,EAAgB;AACnB,MAAA,MAAM,OAAA,GAAU,MAAA,CAAON,KAAAA,CAAK,OAAO,CAAA;AACnC,MAAA,MAAM,WAAW,MAAM,gBAAA,CAAiB,OAAA,EAAS,IAAA,EAAM,OAAOI,QAAO,CAAA;AAErE,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAOJ,KAAAA,CAAK,KAAK,CAAA,IAAK,EAAA,EAAI,CAAC,CAAA,EAAG,GAAG,CAAA;AACjE,MAAA,MAAM,UAAA,GAAa,CAAC,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAE,CAAA;AAC7C,MAAA,IAAIA,KAAAA,CAAK,QAAQ,UAAA,CAAW,IAAA,CAAK,sBAAsB,MAAA,CAAOA,KAAAA,CAAK,MAAM,CAAC,CAAA,CAAE,CAAA;AAC5E,MAAA,IAAIA,KAAAA,CAAK,gBAAgB,UAAA,CAAW,IAAA,CAAK,8BAA8B,MAAA,CAAOA,KAAAA,CAAK,cAAc,CAAC,CAAA,CAAE,CAAA;AAEpG,MAAA,MAAM,UAAU,MAAM,UAAA;AAAA,QACpB,IAAA;AAAA,QAAM,KAAA;AAAA,QAAOI,QAAAA;AAAA,QAAS,QAAA;AAAA,QACtB,KAAA;AAAA,QAAO,CAAA,aAAA,EAAgB,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,OAC7C;AAEA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA;AAAA,EAA0B,QAAQ,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACpG;AAEA,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,IAAQ,EAAC;AAC7B,MAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,eAAA,CAAgB,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,IACpE;AAAA;AAAA,IAGA,KAAK,oBAAA,EAAsB;AACzB,MAAA,MAAM,OAAA,GAAU,MAAA,CAAOJ,KAAAA,CAAK,OAAO,CAAA;AACnC,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAOA,KAAAA,CAAK,KAAK,CAAA;AAC/B,MAAA,MAAM,WAAW,MAAM,gBAAA,CAAiB,OAAA,EAAS,IAAA,EAAM,OAAOI,QAAO,CAAA;AAErE,MAAA,MAAM,CAAC,OAAA,EAAS,IAAI,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QACxC,UAAA,CAAW,IAAA,EAAM,KAAA,EAAOA,QAAAA,EAAS,QAAA,EAAU,OAAO,CAAA,aAAA,EAAgB,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,QAC7F,YAAA,CAAa,KAAA,EAAO,IAAA,EAAM,KAAA,EAAOA,QAAO;AAAA,OACzC,CAAA;AAED,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC1B,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA;AAAA,EAA0B,QAAQ,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACpG;AAEA,MAAA,IAAI,IAAA,GAAO,gBAAgB,GAAG,CAAA;AAC9B,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAA,IAAQ,oBAAA,GAAuB,IAAA;AAAA,MACjC;AAEA,MAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAE;AAAA,IAC7C;AAAA;AAAA,IAGA,KAAK,mBAAA,EAAqB;AACxB,MAAA,MAAM,OAAA,GAAU,MAAA,CAAOJ,KAAAA,CAAK,OAAO,CAAA;AACnC,MAAA,MAAM,MAAA,GAAS,MAAA,CAAOA,KAAAA,CAAK,MAAM,CAAA;AACjC,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAOA,KAAAA,CAAK,WAAW,CAAA,IAAK,EAAA,EAAI,CAAC,CAAA,EAAG,GAAG,CAAA;AAE7E,MAAA,IAAA,CAAK,OAAA,GAAA,CAAW,cAAc,EAAA,IAAM,GAAA;AAEpC,MAAA,MAAM,WAAW,MAAM,gBAAA,CAAiB,OAAA,EAAS,IAAA,EAAM,OAAOI,QAAO,CAAA;AAErE,MAAA,IAAI,OAAA,GAAU,IAAA;AACd,MAAA,IAAIJ,MAAK,OAAA,EAAS;AAChB,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,KAAA,CAAM,MAAA,CAAOA,KAAAA,CAAK,OAAO,CAAC,CAAA;AAC/B,UAAA,OAAA,GAAU,MAAA,CAAOA,MAAK,OAAO,CAAA;AAAA,QAC/B,CAAA,CAAA,MAAQ;AACN,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,MAAA,CAAOA,KAAAA,CAAK,OAAO,CAAA,CAAE,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,QACnF;AAAA,MACF;AAEA,MAAA,MAAM,WAAA,GAAc,KAAK,SAAA,CAAU;AAAA,QACjC,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAAA,QAC3B,SAAS,EAAE,IAAA,EAAM,CAAC,UAAU,CAAA,EAAG,MAAM,IAAA;AAAK,OAC3C,CAAA;AAED,MAAA,MAAM,cAAc,MAAM,UAAA;AAAA,QACxB,IAAA;AAAA,QAAM,KAAA;AAAA,QAAOI,QAAAA;AAAA,QAAS,QAAA;AAAA,QACtB,MAAA;AAAA,QAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,MAAM,CAAC,CAAA,QAAA,CAAA;AAAA,QACnD;AAAA,OACF;AAEA,MAAA,IAAI,WAAA;AACJ,MAAA,IAAI;AACF,QAAA,WAAA,GAAc,IAAA,CAAK,MAAM,WAAW,CAAA;AAAA,MACtC,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA;AAAA,EAA0C,YAAY,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACxH;AAEA,MAAA,MAAM,QAAQ,WAAA,CAAY,EAAA;AAC1B,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA;AAAA,EAAyC,YAAY,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACvH;AAEA,MAAA,MAAM,YAAA,GAAe,GAAA;AACrB,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAM,WAAA,GAAc,MAAQ,YAAY,CAAA;AAE9D,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,EAAU,CAAA,EAAA,EAAK;AACjC,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,YAAY,CAAC,CAAA;AAEpD,QAAA,MAAM,WAAW,MAAM,UAAA;AAAA,UACrB,IAAA;AAAA,UAAM,KAAA;AAAA,UAAOA,QAAAA;AAAA,UAAS,QAAA;AAAA,UACtB,KAAA;AAAA,UAAO,CAAA,aAAA,EAAgB,kBAAA,CAAmB,KAAK,CAAC,CAAA;AAAA,SAClD;AAEA,QAAA,IAAI,GAAA;AACJ,QAAA,IAAI;AACF,UAAA,GAAA,GAAM,IAAA,CAAK,MAAM,QAAQ,CAAA;AAAA,QAC3B,CAAA,CAAA,MAAQ;AACN,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,iBAAA,CAAkB,GAAA,CAAI,GAAA,CAAI,MAAM,CAAA,EAAG;AACrC,UAAA,IAAI,IAAA,GAAO,gBAAgB,GAAG,CAAA;AAC9B,UAAA,MAAM,OAAO,MAAM,YAAA,CAAa,KAAA,EAAO,IAAA,EAAM,OAAOA,QAAO,CAAA;AAC3D,UAAA,IAAI,IAAA,UAAc,oBAAA,GAAuB,IAAA;AACzC,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAE;AAAA,QAC7C;AAAA,MACF;AAEA,MAAA,OAAO;AAAA,QACL,SAAS,CAAC;AAAA,UACR,IAAA,EAAM,MAAA;AAAA,UACN,IAAA,EAAM,CAAA,IAAA,EAAO,KAAK,CAAA,yBAAA,EAA4B,WAAW,CAAA,yDAAA;AAAA,SAC1D;AAAA,OACH;AAAA,IACF;AAAA;AAAA,IAGA,KAAK,oBAAA,EAAsB;AACzB,MAAA,MAAM,OAAA,GAAU,MAAA,CAAOJ,KAAAA,CAAK,OAAO,CAAA;AACnC,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAOA,KAAAA,CAAK,KAAK,CAAA;AAC/B,MAAA,MAAM,WAAW,MAAM,gBAAA,CAAiB,OAAA,EAAS,IAAA,EAAM,OAAOI,QAAO,CAAA;AAErE,MAAA,MAAM,UAAU,MAAM,UAAA;AAAA,QACpB,IAAA;AAAA,QAAM,KAAA;AAAA,QAAOA,QAAAA;AAAA,QAAS,QAAA;AAAA,QACtB,MAAA;AAAA,QAAQ,CAAA,aAAA,EAAgB,kBAAA,CAAmB,KAAK,CAAC,CAAA,OAAA;AAAA,OACnD;AAEA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA;AAAA,EAAqB,QAAQ,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MAC/F;AAEA,MAAA,OAAO;AAAA,QACL,SAAS,CAAC;AAAA,UACR,IAAA,EAAM,MAAA;AAAA,UACN,MAAM,MAAA,CAAO,EAAA,GACT,CAAA,0BAAA,EAA6B,MAAA,CAAO,EAAE,CAAA,CAAA,GACtC,CAAA;AAAA,EAAqB,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,SACnD;AAAA,OACH;AAAA,IACF;AAAA;AAAA,IAGA;AACE,MAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,sBAAA,EAAyB,IAAI,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA;AAElF;;;ACxiBA,SAAS,KAAA,CAAM,GAAA,EAAa,GAAA,EAAa,GAAA,EAAqB;AAC5D,EAAA,OAAO,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,GAAG,CAAC,CAAA;AACzC;AAEA,SAAS,cAAA,CAAe,KAAc,MAAA,EAAwB;AAC5D,EAAA,OAAO,OAAO,GAAA,IAAO,EAAE,CAAA,CAAE,KAAA,CAAM,GAAG,MAAM,CAAA;AAC1C;AAEO,IAAM,WAAA,GAAc;AAAA,EACzB;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EACE,kJAAA;AAAA,IAEF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uDAAA,EAAwD;AAAA,QAC9F,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8CAAA;AAA+C,OAC7F;AAAA,MACA,QAAA,EAAU,CAAC,OAAO;AAAA;AACpB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACE,yLAAA;AAAA,IAGF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uDAAA,EAAwD;AAAA,QAC5F,aAAA,EAAe,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,uDAAA;AAAwD,OACzG;AAAA,MACA,QAAA,EAAU,CAAC,KAAK;AAAA;AAClB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,mBAAA;AAAA,IACN,WAAA,EACE,6UAAA;AAAA,IAIF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,GAAA,EAAK;AAAA,UACH,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACf;AAAA,QACA,YAAA,EAAc;AAAA,UACZ,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACf;AAAA,QACA,cAAA,EAAgB;AAAA,UACd,IAAA,EAAM,SAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACf,OACF;AAAA,MACA,QAAA,EAAU,CAAC,KAAK;AAAA;AAClB;AAEJ,CAAA;AAGO,IAAM,gBAAA,GAAmB,IAAI,GAAA,CAAI,WAAA,CAAY,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAG/D,IAAM,qBAAA,GAAgD;AAAA,EAC3D,YAAA,EAAc,iBAAA;AAAA,EACd,WAAA,EAAa,iBAAA;AAAA,EACb,mBAAA,EAAqB;AACvB,CAAA;AAYA,IAAM,cAAA,GACJ,iHAAA;AAEF,eAAe,SAAA,CAAU,OAAe,UAAA,EAA6C;AACnF,EAAA,MAAM,GAAA,GAAM,CAAA,oCAAA,EAAuC,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAE5E,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAChC,OAAA,EAAS;AAAA,MACP,YAAA,EAAc,cAAA;AAAA,MACd,QAAA,EAAU,WAAA;AAAA,MACV,iBAAA,EAAmB;AAAA,KACrB;AAAA,IACA,QAAA,EAAU;AAAA,GACX,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAC1E,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,EAAA,MAAM,UAA0B,EAAC;AACjC,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,iBAAiB,CAAA;AAEjD,EAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,YAAA,CAAa,UAAU,OAAA,CAAQ,MAAA,GAAS,YAAY,CAAA,EAAA,EAAK;AAC3E,IAAA,MAAM,KAAA,GAAQ,aAAa,CAAC,CAAA;AAE5B,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,CAAM,iCAAiC,CAAA;AAChE,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,CAAM,oCAAoC,CAAA;AAClE,IAAA,MAAM,YAAA,GAAe,KAAA,CAAM,KAAA,CAAM,8CAA8C,CAAA;AAE/E,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,IAAI,IAAA,GAAO,UAAU,CAAC,CAAA;AACtB,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,IAAA,EAAM,wBAAwB,CAAA,CAAE,YAAA,CAAa,IAAI,MAAM,CAAA;AAC5E,MAAA,IAAI,MAAM,IAAA,GAAO,IAAA;AAAA,IACnB;AAEA,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,EAAG;AAE9B,IAAA,MAAM,KAAA,GAAQ,UAAA,GACV,UAAA,CAAW,CAAC,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAA,CAAE,QAAQ,OAAA,EAAS,GAAG,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CAAE,IAAA,EAAK,GACtI,IAAA;AAEJ,IAAA,MAAM,OAAA,GAAU,YAAA,GACZ,YAAA,CAAa,CAAC,EAAE,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,CAAE,QAAQ,QAAA,EAAU,GAAG,CAAA,CAAE,OAAA,CAAQ,SAAS,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,GAAG,EAAE,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,CAAE,MAAK,GACrL,EAAA;AAEJ,IAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM,SAAS,CAAA;AAAA,EAC5C;AAEA,EAAA,OAAO,OAAA;AACT;AAYA,IAAM,WAAA,GAAc,mDAAA;AACpB,IAAM,cAAA,GAAiB,gEAAA;AACvB,IAAM,cAAA,GAAiB,2EAAA;AAEvB,IAAM,oBAAA,GAAuB;AAAA,EAC3B,WAAA;AAAA,EAAa,YAAA;AAAA,EAAc,iBAAA;AAAA,EAAmB,cAAA;AAAA,EAC9C,aAAA;AAAA,EAAe,QAAA;AAAA,EAAU,aAAA;AAAA,EAAe,eAAA;AAAA,EACxC,eAAA;AAAA,EAAiB,kBAAA;AAAA,EAAoB,gBAAA;AAAA,EACrC,YAAA;AAAA,EAAc,kBAAA;AAAA,EAAoB,gBAAA;AAAA,EAAkB,iBAAA;AAAA,EACpD,gBAAA;AAAA,EAAkB,gBAAA;AAAA,EAAkB,YAAA;AAAA,EAAc,aAAA;AAAA,EAClD,eAAA;AAAA,EAAiB,YAAA;AAAA,EAAc,aAAA;AAAA,EAAe,eAAA;AAAA,EAC9C,qBAAA;AAAA,EAAuB,WAAA;AAAA,EAAa,WAAA;AAAA,EAAa,aAAA;AAAA,EACjD,WAAA;AAAA,EAAa,UAAA;AAAA,EAAY,QAAA;AAAA,EAAU,gBAAA;AAAA,EACnC,iBAAA;AAAA,EAAmB,iBAAA;AAAA,EAAmB,aAAA;AAAA,EACtC,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,UAAA;AAAA,EAC9B,QAAA;AAAA,EAAU,YAAA;AAAA,EAAc,cAAA;AAAA,EAAgB,SAAA;AAAA,EACxC,YAAA;AAAA,EAAc,aAAA;AAAA,EAAe,YAAA;AAAA,EAC7B,UAAA;AAAA,EAAY,YAAA;AAAA,EAAc,gBAAA;AAAA,EAAkB,QAAA;AAAA,EAAU;AACxD,CAAA;AAEA,IAAM,qBAAA,GAAwB;AAAA,EAC5B,SAAA;AAAA,EAAW,OAAA;AAAA,EAAS,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,YAAA;AAAA,EAChD,WAAA;AAAA,EAAa,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,YAAA;AAAA,EAChD,aAAA;AAAA,EAAe,UAAA;AAAA,EAAY,cAAA;AAAA,EAAgB,cAAA;AAAA,EAAgB;AAC7D,CAAA;AAEA,IAAM,oBAAA,GAAuB;AAAA,EAC3B,UAAA;AAAA,EAAY,WAAA;AAAA,EAAa,QAAA;AAAA,EAAU,WAAA;AAAA,EAAa,OAAA;AAAA,EAChD,aAAA;AAAA,EAAe,OAAA;AAAA,EAAS,eAAA;AAAA,EAAiB,WAAA;AAAA,EACzC,oBAAA;AAAA,EAAsB,cAAA;AAAA,EAAgB,cAAA;AAAA,EACtC,qBAAA;AAAA,EAAuB;AACzB,CAAA;AAEA,SAAS,qBAAqB,IAAA,EAAsB;AAClD,EAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IAAQ,sBAAA;AAAA,IAAwB,CAAC,GAAG,GAAA,KAC9C,MAAA,CAAO,aAAa,QAAA,CAAS,GAAA,EAAK,EAAE,CAAC;AAAA,GACvC;AACF;AAEA,SAAS,mBAAmB,IAAA,EAAsB;AAChD,EAAA,OAAO,IAAA,CACJ,OAAA,CAAQ,WAAA,EAAa,CAAC,CAAA,EAAG,GAAA,KAAQ,MAAA,CAAO,YAAA,CAAa,QAAA,CAAS,GAAG,CAAC,CAAC,CAAA,CACnE,OAAA;AAAA,IAAQ,qBAAA;AAAA,IAAuB,CAAC,GAAG,GAAA,KAClC,MAAA,CAAO,aAAa,QAAA,CAAS,GAAA,EAAK,EAAE,CAAC;AAAA,GACvC;AACJ;AAEA,SAAS,sBAAsB,IAAA,EAAwB;AACrD,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAE/B,EAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,oBAAA,CAAqB,IAAI,CAAC,CAAA;AAE7D,EAAA,MAAM,WAAA,GAAc,6DAAA;AACpB,EAAA,IAAI,CAAA;AACJ,EAAA,KAAA,MAAW,GAAA,IAAO,CAAC,IAAA,EAAM,OAAO,CAAA,EAAG;AACjC,IAAA,OAAA,CAAQ,CAAA,GAAI,WAAA,CAAY,IAAA,CAAK,GAAG,CAAA,MAAO,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,CAAC,CAAA,CAAG,WAAA,EAAa,CAAA;AAAA,EAC7E;AAEA,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,OAAA,CAAQ,2BAAA,EAA6B,EAAE,CAAA;AAChE,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,CAAM,WAAW,KAAK,EAAC;AACnD,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,MAAM,KAAA,GAAQ,EAAE,WAAA,EAAY;AAC5B,IAAA,IAAI,CAAC,yDAAA,CAA0D,IAAA,CAAK,KAAK,CAAA,EAAG;AAC1E,MAAA,MAAA,CAAO,IAAI,KAAK,CAAA;AAAA,IAClB;AAAA,EACF;AAEA,EAAA,OAAO,CAAC,GAAG,MAAM,CAAA,CAAE,OAAO,CAAA,CAAA,KAAK,CAAC,oBAAA,CAAqB,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA;AAC3E;AAEA,SAAS,sBAAsB,IAAA,EAAwB;AACrD,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAC/B,EAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,oBAAA,CAAqB,IAAI,CAAC,CAAA;AAE7D,EAAA,MAAM,QAAA,GAAW,sBAAA;AACjB,EAAA,IAAI,CAAA;AACJ,EAAA,KAAA,MAAW,GAAA,IAAO,CAAC,IAAA,EAAM,OAAO,CAAA,EAAG;AACjC,IAAA,OAAA,CAAQ,CAAA,GAAI,QAAA,CAAS,IAAA,CAAK,GAAG,OAAO,IAAA,EAAM;AACxC,MAAA,MAAM,QAAQ,CAAA,CAAE,CAAC,CAAA,CAAG,OAAA,CAAQ,cAAc,EAAE,CAAA;AAC5C,MAAA,IAAI,KAAA,CAAM,MAAA,IAAU,EAAA,IAAM,KAAA,CAAM,MAAA,IAAU,EAAA,EAAI,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,CAAC,CAAA,CAAG,IAAA,EAAM,CAAA;AAAA,IACvE;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GAAW,OAAA,CACd,OAAA,CAAQ,6BAAA,EAA+B,EAAE,CAAA,CACzC,OAAA,CAAQ,2BAAA,EAA6B,EAAE,CAAA,CACvC,OAAA,CAAQ,UAAA,EAAY,GAAG,CAAA;AAC1B,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,CAAM,cAAc,KAAK,EAAC;AACtD,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AACxC,IAAA,IAAI,KAAA,CAAM,MAAA,IAAU,EAAA,IAAM,KAAA,CAAM,MAAA,IAAU,IAAI,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAA;AAAA,EACnE;AAEA,EAAA,OAAO,CAAC,GAAG,MAAM,CAAA,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AAChC;AAEA,SAAS,wBAAwB,IAAA,EAAwB;AACvD,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAC9B,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,cAAc,KAAK,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAA,IAAK,SAAS,KAAA,CAAM,GAAA,CAAI,EAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA;AACvD,EAAA,OAAO,CAAC,GAAG,KAAK,CAAA;AAClB;AAEA,SAAS,oBAAA,CAAqB,MAAc,OAAA,EAA2B;AACrE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AAAE,IAAA,IAAA,GAAO,IAAI,IAAI,OAAO,CAAA;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,EAAC;AAAA,EAAG;AAEpD,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAE9B,EAAA,KAAA,MAAW,QAAQ,oBAAA,EAAsB;AACvC,IAAA,KAAA,CAAM,IAAI,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA;AAAA,EACnC;AAEA,EAAA,MAAM,SAAA,GAAY,kCAAA;AAClB,EAAA,IAAI,CAAA;AACJ,EAAA,OAAA,CAAQ,CAAA,GAAI,SAAA,CAAU,IAAA,CAAK,IAAI,OAAO,IAAA,EAAM;AAC1C,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,IAAI,GAAA,CAAI,CAAA,CAAE,CAAC,GAAG,OAAO,CAAA;AACjC,MAAA,IAAI,GAAA,CAAI,QAAA,KAAa,IAAA,CAAK,QAAA,EAAU;AACpC,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,QAAA,CAAS,WAAA,EAAY;AACtC,MAAA,IAAI,sBAAsB,IAAA,CAAK,CAAA,EAAA,KAAM,KAAK,QAAA,CAAS,EAAE,CAAC,CAAA,EAAG;AACvD,QAAA,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,MAAA,GAAS,GAAA,CAAI,QAAQ,CAAA;AAAA,MACrC;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAA0B;AAAA,EACpC;AAEA,EAAA,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,QAAQ,CAAA;AACxC,EAAA,OAAO,CAAC,GAAG,KAAK,CAAA,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AAC/B;AAEA,SAAS,kBAAkB,MAAA,EAA0B;AACnD,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AACrC,EAAA,OAAO,CAAC,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAI,WAAW,CAAC,CAAA,CAAA,EAAI,CAAA,MAAA,EAAS,CAAC,IAAI,CAAA,cAAA,EAAiB,CAAC,CAAA,CAAA,EAAI,CAAA,QAAA,EAAW,CAAC,CAAA,CAAE,CAAA;AACzF;AAEA,IAAM,wBAAA,GAA2B;AAAA,EAC/B,WAAA;AAAA,EAAa,oBAAA;AAAA,EAAsB,yBAAA;AAAA,EACnC,eAAA;AAAA,EAAiB,uBAAA;AAAA,EAAyB,+BAAA;AAAA,EAC1C,oBAAA;AAAA,EAAsB;AACxB,CAAA;AAEA,SAAS,mBAAmB,IAAA,EAAuB;AACjD,EAAA,IAAI,IAAA,CAAK,MAAA,GAAS,GAAA,EAAM,OAAO,KAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,KAAK,WAAA,EAAY;AAC/B,EAAA,OAAO,wBAAA,CAAyB,KAAK,CAAA,GAAA,KAAO,KAAA,CAAM,SAAS,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AAC/E;AAEA,eAAe,YAAA,CAAa,GAAA,EAAa,SAAA,GAAY,GAAA,EAA+B;AAClF,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC5D,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAC3B,OAAA,EAAS;AAAA,QACP,YAAA,EAAc,cAAA;AAAA,QACd,QAAA,EAAU,iCAAA;AAAA,QACV,iBAAA,EAAmB;AAAA,OACrB;AAAA,MACA,QAAA,EAAU,QAAA;AAAA,MACV,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AACD,IAAA,MAAM,EAAA,GAAK,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAC9C,IAAA,IAAI,CAAC,EAAA,CAAG,QAAA,CAAS,WAAW,KAAK,CAAC,EAAA,CAAG,QAAA,CAAS,YAAY,KAAK,CAAC,EAAA,CAAG,QAAA,CAAS,OAAO,GAAG,OAAO,IAAA;AAC7F,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,IAAM,GAAA,CAAI,MAAA,KAAW,KAAK,OAAO,IAAA;AAC1C,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,kBAAA,CAAmB,IAAI,CAAA,EAAG,OAAO,IAAA;AACrC,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AAEA,eAAe,gBAAA,CAAiB,GAAA,EAAa,SAAA,GAAY,IAAA,EAA+B;AACtF,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,OAAA,CAAQ,cAAA,EAAgB,EAAE,CAAA;AAC/C,EAAA,MAAM,KAAA,GAAQ,oCAAoC,QAAQ,CAAA,CAAA;AAC1D,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC5D,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,KAAA,EAAO;AAAA,MAC7B,OAAA,EAAS,EAAE,YAAA,EAAc,cAAA,EAAe;AAAA,MACxC,QAAA,EAAU,QAAA;AAAA,MACV,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AACD,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,IAAA;AACpB,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,IAAA,CAAK,MAAA,GAAS,GAAA,EAAK,OAAO,IAAA;AAC9B,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AAEA,eAAe,QAAA,CAAS,KAAa,YAAA,EAAgD;AACnF,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,UAAU,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,IAAK,CAAA;AAE1D,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAChC,OAAA,EAAS;AAAA,QACP,YAAA,EAAc,cAAA;AAAA,QACd,QAAA,EAAU,iCAAA;AAAA,QACV,iBAAA,EAAmB;AAAA,OACrB;AAAA,MACA,QAAA,EAAU,QAAA;AAAA,MACV,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAEzE,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAC5D,IAAA,IAAI,CAAC,WAAA,CAAY,QAAA,CAAS,WAAW,KAAK,CAAC,WAAA,CAAY,QAAA,CAAS,YAAY,CAAA,IAAK,CAAC,WAAA,CAAY,QAAA,CAAS,mBAAmB,CAAA,EAAG;AAC3H,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,WAAW,CAAA,iCAAA,CAAmC,CAAA;AAAA,IAC7F;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,IAAA,MAAM,QAA0C,EAAC;AACjD,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,MAAM,SAAA,GAAY,gDAAA;AAClB,MAAA,IAAI,KAAA;AACJ,MAAA,OAAA,CAAQ,KAAA,GAAQ,SAAA,CAAU,IAAA,CAAK,IAAI,OAAO,IAAA,EAAM;AAC9C,QAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,QAAA,MAAMG,KAAAA,GAAO,MAAM,CAAC,CAAA,CAAE,QAAQ,UAAA,EAAY,EAAE,EAAE,IAAA,EAAK;AACnD,QAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,EAAG;AACnC,UAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAMA,MAAK,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,GAAO,IAAA,CACR,OAAA,CAAQ,6BAAA,EAA+B,EAAE,CAAA,CACzC,OAAA,CAAQ,2BAAA,EAA6B,EAAE,CAAA,CACvC,OAAA,CAAQ,iCAAA,EAAmC,EAAE,EAC7C,OAAA,CAAQ,uBAAA,EAAyB,SAAS,CAAA,CAC1C,OAAA,CAAQ,6BAAA,EAA+B,YAAY,CAAA,CACnD,QAAQ,6BAAA,EAA+B,YAAY,CAAA,CACnD,OAAA,CAAQ,qBAAqB,IAAI,CAAA,CACjC,OAAA,CAAQ,4CAAA,EAA8C,IAAI,CAAA,CAC1D,OAAA,CAAQ,UAAA,EAAY,GAAG,CAAA,CACvB,OAAA,CAAQ,SAAA,EAAW,GAAG,EACtB,OAAA,CAAQ,QAAA,EAAU,GAAG,CAAA,CACrB,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAA,CACpB,QAAQ,OAAA,EAAS,GAAG,CAAA,CACpB,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CACtB,OAAA,CAAQ,WAAW,GAAG,CAAA,CACtB,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CACtB,OAAA,CAAQ,UAAA,EAAY,IAAI,EACxB,IAAA,EAAK;AAER,IAAA,MAAM,QAAA,GAAW,IAAA;AACjB,IAAA,IAAI,IAAA,CAAK,SAAS,QAAA,EAAU;AAC1B,MAAA,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAA,GAAI,wCAAA;AAAA,IACnC;AAEA,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,KAAA,EAAM;AAAA,EACtC,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,OAAO,CAAA;AAAA,EACtB;AACF;AAMA,eAAsB,eAAA,CACpB,MACAP,KAAAA,EACqB;AACrB,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,YAAA,EAAc;AACjB,MAAA,MAAM,KAAA,GAAQ,cAAA,CAAeA,KAAAA,CAAK,KAAA,EAAO,GAAG,CAAA;AAC5C,MAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAC/C,MAAA,MAAM,UAAA,GAAa,MAAM,MAAA,CAAOA,KAAAA,CAAK,WAAW,CAAA,IAAK,EAAA,EAAI,GAAG,EAAE,CAAA;AAE9D,MAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,KAAA,EAAO,UAAU,CAAA;AAEjD,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,8BAAA,EAAiC,KAAK,CAAA,CAAA,CAAA,EAAK,CAAA,EAAE;AAAA,MACxF;AAEA,MAAA,MAAM,YAAY,OAAA,CAAQ,GAAA;AAAA,QAAI,CAAC,GAAG,CAAA,KAChC,CAAA,EAAG,IAAI,CAAC,CAAA,EAAA,EAAK,EAAE,KAAK;AAAA,QAAA,EAAa,EAAE,GAAG;AAAA,GAAA,EAAQ,EAAE,OAAO,CAAA;AAAA,OACzD,CAAE,KAAK,MAAM,CAAA;AAEb,MAAA,OAAO;AAAA,QACL,SAAS,CAAC;AAAA,UACR,IAAA,EAAM,MAAA;AAAA,UACN,IAAA,EAAM,CAAA,oBAAA,EAAuB,KAAK,CAAA,GAAA,EAAM,QAAQ,MAAM,CAAA;;AAAA,EAAiB,SAAS,CAAA;AAAA,SACjF;AAAA,OACH;AAAA,IACF;AAAA,IAEA,KAAK,WAAA,EAAa;AAChB,MAAA,MAAM,GAAA,GAAM,cAAA,CAAeA,KAAAA,CAAK,GAAA,EAAK,GAAI,CAAA;AACzC,MAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,iBAAiB,CAAA;AAC3C,MAAA,IAAI,CAAC,gBAAgB,IAAA,CAAK,GAAG,GAAG,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAEzF,MAAA,MAAM,YAAA,GAAe,OAAA,CAAQA,KAAAA,CAAK,aAAa,CAAA;AAC/C,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,GAAA,EAAK,YAAY,CAAA;AAE/C,MAAA,IAAI,OAAO,CAAA,aAAA,EAAgB,GAAG,CAAA,EAAA,EAAK,MAAA,CAAO,KAAK,MAAM,CAAA;;AAAA,EAAe,OAAO,IAAI,CAAA,CAAA;AAE/E,MAAA,IAAI,YAAA,IAAgB,MAAA,CAAO,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AAC3C,QAAA,MAAM,WAAW,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,GAAA;AAAA,UAAI,CAAA,CAAA,KAC7C,CAAA,EAAA,EAAK,CAAA,CAAE,IAAA,GAAO,CAAA,CAAE,OAAO,IAAA,GAAO,EAAE,CAAA,EAAG,CAAA,CAAE,IAAI,CAAA;AAAA,SAC3C,CAAE,KAAK,IAAI,CAAA;AACX,QAAA,IAAA,IAAQ;;AAAA,WAAA,EAAkB,MAAA,CAAO,MAAM,MAAM,CAAA;AAAA,EAAgC,QAAQ,CAAA,CAAA;AAAA,MACvF;AAEA,MAAA,MAAM,UAAA,GAAa,qBAAA,CAAsB,MAAA,CAAO,OAAO,CAAA;AACvD,MAAA,MAAM,UAAA,GAAa,qBAAA,CAAsB,MAAA,CAAO,OAAO,CAAA;AACvD,MAAA,MAAM,YAAA,GAAe,uBAAA,CAAwB,MAAA,CAAO,OAAO,CAAA;AAE3D,MAAA,IAAI,UAAA,CAAW,SAAS,CAAA,IAAK,UAAA,CAAW,SAAS,CAAA,IAAK,YAAA,CAAa,SAAS,CAAA,EAAG;AAC7E,QAAA,IAAA,IAAQ,yCAAA;AACR,QAAA,IAAI,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG,IAAA,IAAQ;AAAA,QAAA,EAAa,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AACrE,QAAA,IAAI,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG,IAAA,IAAQ;AAAA,QAAA,EAAa,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AACrE,QAAA,IAAI,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG,IAAA,IAAQ;AAAA,UAAA,EAAe,YAAA,CAAa,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,MAC7E;AAEA,MAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAE;AAAA,IAC7C;AAAA,IAEA,KAAK,mBAAA,EAAqB;AACxB,MAAA,MAAM,QAAA,GAAW,cAAA,CAAeA,KAAAA,CAAK,GAAA,EAAK,GAAI,CAAA;AAC9C,MAAA,IAAI,CAAC,QAAA,EAAU,MAAM,IAAI,MAAM,iBAAiB,CAAA;AAChD,MAAA,MAAM,WAAA,GAAc,cAAA,CAAeA,KAAAA,CAAK,YAAA,EAAc,GAAG,CAAA;AACzD,MAAA,MAAM,aAAA,GAAgBA,MAAK,cAAA,KAAmB,KAAA;AAE9C,MAAA,MAAM,UAAU,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,GAAI,QAAA,GAAW,WAAW,QAAQ,CAAA,CAAA;AAC5E,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AAAE,QAAA,OAAA,GAAU,IAAI,IAAI,OAAO,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAE,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAgB,QAAQ,CAAA,CAAE,CAAA;AAAA,MAAG;AACzF,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,UAAU,EAAE,CAAA;AAEpD,MAAA,MAAM,SAAA,GAAY,CAAC,OAAO,CAAA;AAC1B,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,SAAS,CAAC,CAAA;AAC/E,MAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,OAAO,CAAA,EAAG;AAC/B,QAAA,SAAA,CAAU,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,OAAA,EAAS,MAAM,CAAC,CAAA;AAC/C,QAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,UAAA,EAAY,aAAa,CAAC,CAAA;AAAA,MAC1F;AACA,MAAA,IAAI,IAAA,GAAsB,IAAA;AAC1B,MAAA,IAAI,WAAA,GAAc,KAAA;AAClB,MAAA,KAAA,MAAW,UAAU,SAAA,EAAW;AAC9B,QAAA,IAAA,GAAO,MAAM,YAAA,CAAa,MAAA,EAAQ,IAAK,CAAA;AACvC,QAAA,IAAI,IAAA,EAAM;AAAA,MACZ;AACA,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,IAAA,GAAO,MAAM,gBAAA,CAAiB,CAAA,QAAA,EAAW,MAAM,IAAI,IAAK,CAAA;AACxD,QAAA,IAAI,MAAM,WAAA,GAAc,IAAA;AAAA,MAC1B;AACA,MAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,OAAO,CAAA,+BAAA,CAAiC,CAAA;AAEtF,MAAA,MAAM,eAAe,WAAA,GAAc,EAAC,GAAI,oBAAA,CAAqB,MAAM,OAAO,CAAA;AAE1E,MAAA,MAAM,YAAA,GAAe,YAAA,CAAa,GAAA,CAAI,OAAO,OAAA,KAAY;AACvD,QAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,OAAA,EAAS,GAAI,CAAA;AACjD,QAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AAAA,MACxC,CAAC,CAAA;AACD,MAAA,MAAM,WAAA,GAAc,MAAM,OAAA,CAAQ,UAAA,CAAW,YAAY,CAAA;AAEzD,MAAA,MAAM,eAAyB,CAAC,WAAA,GAAc,CAAA,UAAA,EAAa,MAAM,KAAK,OAAO,CAAA;AAC7E,MAAA,MAAM,QAAA,GAAW,CAAC,IAAI,CAAA;AACtB,MAAA,KAAA,MAAW,UAAU,WAAA,EAAa;AAChC,QAAA,IAAI,MAAA,CAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,MAAM,IAAA,EAAM;AACtD,UAAA,QAAA,CAAS,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC/B,UAAA,YAAA,CAAa,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAAA,QACpC;AAAA,MACF;AAEA,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,mBAAA,GAAsB,CAAC,UAAA,EAAY,WAAA,EAAa,UAAU,OAAO,CAAA;AACvE,QAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,GAAA,CAAI,OAAO,IAAA,KAAS;AACzD,UAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,CAAiB,CAAA,QAAA,EAAW,MAAM,CAAA,EAAG,IAAI,IAAI,IAAK,CAAA;AACvE,UAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,MAAA,EAAO;AAAA,QAC9B,CAAC,CAAA;AACD,QAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,UAAA,CAAW,UAAU,CAAA;AACrD,QAAA,KAAA,MAAW,MAAM,SAAA,EAAW;AAC1B,UAAA,IAAI,EAAA,CAAG,MAAA,KAAW,WAAA,IAAe,EAAA,CAAG,MAAM,IAAA,EAAM;AAC9C,YAAA,QAAA,CAAS,IAAA,CAAK,EAAA,CAAG,KAAA,CAAM,IAAI,CAAA;AAC3B,YAAA,YAAA,CAAa,KAAK,CAAA,UAAA,EAAa,MAAM,GAAG,EAAA,CAAG,KAAA,CAAM,IAAI,CAAA,CAAE,CAAA;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,MAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,MAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AAEpC,MAAA,KAAA,MAAW,YAAY,QAAA,EAAU;AAC/B,QAAA,KAAA,MAAW,KAAK,qBAAA,CAAsB,QAAQ,CAAA,EAAG,SAAA,CAAU,IAAI,CAAC,CAAA;AAChE,QAAA,KAAA,MAAW,KAAK,qBAAA,CAAsB,QAAQ,CAAA,EAAG,SAAA,CAAU,IAAI,CAAC,CAAA;AAChE,QAAA,KAAA,MAAW,KAAK,uBAAA,CAAwB,QAAQ,CAAA,EAAG,WAAA,CAAY,IAAI,CAAC,CAAA;AAAA,MACtE;AAEA,MAAA,IAAI,UAAA,GAAa,EAAA;AACjB,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,IAAI;AACF,UAAA,MAAM,OAAA,GAAU,cACZ,CAAC,CAAA,CAAA,EAAI,WAAW,CAAA,GAAA,EAAM,MAAM,WAAW,CAAA,EAAA,EAAK,MAAM,SAAS,CAAA,GAC3D,CAAC,IAAI,MAAM,CAAA,eAAA,CAAA,EAAmB,KAAK,MAAM,CAAA,OAAA,CAAA,EAAW,CAAA,KAAA,EAAQ,MAAM,CAAA,IAAA,CAAM,CAAA;AAE5E,UAAA,IAAI,kBAAA,GAAqB,CAAA;AACzB,UAAA,KAAA,MAAW,eAAe,OAAA,EAAS;AACjC,YAAA,MAAM,aAAA,GAAgB,MAAM,SAAA,CAAU,WAAA,EAAa,CAAC,CAAA;AACpD,YAAA,kBAAA,IAAsB,aAAA,CAAc,MAAA;AAEpC,YAAA,KAAA,MAAW,KAAK,aAAA,EAAe;AAC7B,cAAA,MAAM,WAAW,CAAA,EAAG,CAAA,CAAE,KAAK,CAAA,CAAA,EAAI,EAAE,OAAO,CAAA,CAAA;AACxC,cAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,oBAAA,CAAqB,QAAQ,CAAC,CAAA;AACjE,cAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,KAAA,CAAM,WAAW,KAAK,EAAC;AACrD,cAAA,KAAA,MAAW,KAAK,aAAA,EAAe;AAC7B,gBAAA,MAAM,KAAA,GAAQ,EAAE,WAAA,EAAY;AAC5B,gBAAA,MAAM,aAAa,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,MAAA;AAC3C,gBAAA,IAAI,KAAA,CAAM,QAAA,CAAS,UAAU,CAAA,IAAK,CAAC,oBAAA,CAAqB,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,CAAK,KAAK,CAAC,CAAA,EAAG;AAChF,kBAAA,SAAA,CAAU,IAAI,KAAK,CAAA;AAAA,gBACrB;AAAA,cACF;AAEA,cAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,KAAA,CAAM,cAAc,KAAK,EAAC;AACxD,cAAA,KAAA,MAAW,KAAK,aAAA,EAAe;AAC7B,gBAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AACxC,gBAAA,IAAI,KAAA,CAAM,MAAA,IAAU,EAAA,IAAM,KAAA,CAAM,MAAA,IAAU,IAAI,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAA;AAAA,cACtE;AAEA,cAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,CAAM,cAAc,KAAK,EAAC;AACpD,cAAA,KAAA,MAAW,CAAA,IAAK,WAAW,WAAA,CAAY,GAAA,CAAI,EAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA;AAAA,YACjE;AACA,YAAA,IAAI,SAAA,CAAU,OAAO,CAAA,EAAG;AAAA,UAC1B;AACA,UAAA,UAAA,GAAa,MAAM,kBAAkB,CAAA,eAAA,CAAA;AAAA,QACvC,CAAA,CAAA,MAAQ;AAAE,UAAA,UAAA,GAAa,kBAAA;AAAA,QAAoB;AAAA,MAC7C;AAEA,MAAA,MAAM,WAAA,GAAc,CAAC,GAAG,SAAS,CAAA;AACjC,MAAA,MAAM,eAAA,GAAkB,0HAAA;AACxB,MAAA,MAAM,gBAAgB,WAAA,CAAY,MAAA,CAAO,OAAK,eAAA,CAAgB,IAAA,CAAK,CAAC,CAAC,CAAA;AACrE,MAAA,MAAM,cAAA,GAAiB,YAAY,MAAA,CAAO,CAAA,CAAA,KAAK,CAAC,eAAA,CAAgB,IAAA,CAAK,CAAC,CAAC,CAAA;AAEvE,MAAA,MAAM,OAAA,GAAU,kBAAkB,MAAM,CAAA;AACxC,MAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAC,SAAA,CAAU,GAAA,CAAI,CAAC,CAAC,CAAA;AAExD,MAAA,MAAM,KAAA,GAAQ;AAAA,QACZ,qBAAqB,MAAM,CAAA,IAAA,CAAA;AAAA,QAC3B,CAAA,eAAA,EAAkB,YAAA,CAAa,MAAM,CAAA,EAAG,UAAU,CAAA,CAAA;AAAA,QAClD;AAAA,OACF;AAEA,MAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC1B,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,WAAA,CAAY,MAAM,CAAA,EAAA,CAAI,CAAA;AAClD,QAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC5B,UAAA,KAAA,CAAM,KAAK,YAAY,CAAA;AACvB,UAAA,KAAA,MAAW,KAAK,aAAA,EAAe,KAAA,CAAM,IAAA,CAAK,CAAA,MAAA,EAAS,CAAC,CAAA,CAAE,CAAA;AAAA,QACxD;AACA,QAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,UAAA,KAAA,CAAM,KAAK,wBAAwB,CAAA;AACnC,UAAA,KAAA,MAAW,KAAK,cAAA,EAAgB,KAAA,CAAM,IAAA,CAAK,CAAA,MAAA,EAAS,CAAC,CAAA,CAAE,CAAA;AAAA,QACzD;AAAA,MACF,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,KAAK,+BAA+B,CAAA;AAC1C,QAAA,KAAA,CAAM,KAAK,wDAAwD,CAAA;AACnE,QAAA,KAAA,MAAW,KAAK,UAAA,EAAY,KAAA,CAAM,IAAA,CAAK,CAAA,MAAA,EAAS,CAAC,CAAA,CAAE,CAAA;AAAA,MACrD;AAEA,MAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,MAAA,IAAI,CAAC,GAAG,SAAS,CAAA,CAAE,SAAS,CAAA,EAAG;AAC7B,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,eAAA,EAAkB,SAAA,CAAU,IAAI,CAAA,EAAA,CAAI,CAAA;AAC/C,QAAA,KAAA,MAAW,KAAK,SAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAO,CAAC,CAAA,CAAE,CAAA;AAAA,MAClD,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,KAAK,2BAA2B,CAAA;AAAA,MACxC;AAEA,MAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,MAAA,IAAI,CAAC,GAAG,WAAW,CAAA,CAAE,SAAS,CAAA,EAAG;AAC/B,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,UAAA,EAAa,WAAA,CAAY,IAAI,CAAA,EAAA,CAAI,CAAA;AAC5C,QAAA,KAAA,MAAW,KAAK,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAO,CAAC,CAAA,CAAE,CAAA;AAAA,MACpD;AAEA,MAAA,KAAA,CAAM,IAAA,CAAK,IAAI,gBAAgB,CAAA;AAC/B,MAAA,KAAA,MAAW,KAAK,YAAA,EAAc,KAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAU,CAAC,CAAA,CAAE,CAAA;AACtD,MAAA,MAAM,WAAA,GAAc,aAAa,MAAA,CAAO,CAAA,CAAA,KAAK,CAAC,YAAA,CAAa,QAAA,CAAS,CAAC,CAAC,CAAA;AACtE,MAAA,KAAA,MAAW,KAAK,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAU,CAAC,CAAA,CAAE,CAAA;AAErD,MAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,IAC/D;AAAA,IAEA;AACE,MAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA;AAE1E;ACnnBA,IAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAEjC,SAASQ,QAAO,IAAA,EAAkC;AAChD,EAAA,OAAO,KAAK,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,CAAW,KAAK,IAAI,CAAA,CAAA,CAAG,CAAC,CAAA,EAAG,MAAM,GAAG,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AACjF;AAOA,IAAM,QAAA,GAAWA,OAAAA,CAAO,WAAW,CAAA,IAAK,QAAQ,GAAA,CAAI,sBAAA;AACpD,IAAI,QAAA,EAAU;AACZ,EAAA,MAAM,EAAE,YAAA,EAAAC,aAAAA,EAAa,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,eAAA,EAAA,EAAA,kBAAA,CAAA,CAAA;AAC/B,EAAA,MAAMA,cAAa,IAAI,CAAA;AAEvB,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAEA,IAAM,MAAA,GAASD,OAAAA,CAAO,SAAS,CAAA,IAAK,QAAQ,GAAA,CAAI,oBAAA;AAChD,IAAM,UAAA,GAAaA,OAAAA,CAAO,SAAS,CAAA,IAAK,QAAQ,GAAA,CAAI,oBAAA;AACpD,IAAM,WAAA,GAAcA,OAAAA,CAAO,cAAc,CAAA,IAAK,QAAQ,GAAA,CAAI,YAAA;AAC1D,IAAM,WAAA,GAAcA,OAAAA,CAAO,cAAc,CAAA,IAAK,QAAQ,GAAA,CAAI,yBAAA;AAC1D,IAAM,aAAA,GAAgBA,OAAAA,CAAO,gBAAgB,CAAA,IAAK,QAAQ,GAAA,CAAI,cAAA;AAC9D,IAAM,cAAA,GAAiBA,OAAAA,CAAO,kBAAkB,CAAA,IAAK,QAAQ,GAAA,CAAI,gBAAA;AACjE,IAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AACvC,IAAM,QAAA,GAAW,MAAA,CAAOA,OAAAA,CAAO,MAAM,CAAC,CAAA,IAAK,IAAA;AAE3C,IAAI,CAAC,MAAA,IAAU,CAAC,UAAA,EAAY;AAC1B,EAAA,OAAA,CAAQ,MAAM,uKAAuK,CAAA;AACrL,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAEA,IAAI,CAAC,WAAA,IAAe,CAAC,WAAA,EAAa;AAChC,EAAA,OAAA,CAAQ,MAAM,wHAAwH,CAAA;AACtI,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAEA,IAAM,QAAA,GAAW,YAAA,CAAa,WAAA,EAAa,WAAW,CAAA;AAWtD,IAAM,cAAN,MAAkB;AAAA,EACR,OAAA,uBAAc,GAAA,EAA4B;AAAA,EACjC,WAAA;AAAA,EACA,QAAA;AAAA,EAEjB,WAAA,CAAY,aAAqB,QAAA,EAAkB;AACjD,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,GAAA,EAA4E;AAChF,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAElC,IAAA,IAAI,CAAC,KAAA,IAAS,GAAA,IAAO,KAAA,CAAM,OAAA,EAAS;AAClC,MAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,EAAE,KAAA,EAAO,GAAG,OAAA,EAAS,GAAA,GAAM,IAAA,CAAK,QAAA,EAAU,CAAA;AAChE,MAAA,OAAO,EAAE,SAAS,IAAA,EAAM,SAAA,EAAW,KAAK,WAAA,GAAc,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,IAC3E;AAEA,IAAA,KAAA,CAAM,KAAA,EAAA;AAEN,IAAA,IAAI,KAAA,CAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,EAAa;AAClC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,SAAA,EAAW,CAAA;AAAA,QACX,YAAA,EAAc,MAAM,OAAA,GAAU;AAAA,OAChC;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW,IAAA,CAAK,WAAA,GAAc,KAAA,CAAM,KAAA;AAAA,MACpC,YAAA,EAAc;AAAA,KAChB;AAAA,EACF;AAAA;AAAA,EAGA,OAAA,GAAgB;AACd,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,KAAK,OAAA,EAAS;AACvC,MAAA,IAAI,OAAO,KAAA,CAAM,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,OAAO,GAAG,CAAA;AAAA,IACnD;AAAA,EACF;AACF,CAAA;AAEA,IAAM,kBAAkB,IAAI,WAAA,CAAY,CAAA,EAAG,EAAA,GAAK,KAAK,GAAI,CAAA;AAGzD,WAAA,CAAY,MAAM;AAChB,EAAA,eAAA,CAAgB,OAAA,EAAQ;AAC1B,CAAA,EAAG,CAAA,GAAI,EAAA,GAAK,GAAI,CAAA,CAAE,KAAA,EAAM;AAYxB,IAAM,cAAA,mBAAiB,IAAI,GAAA,CAAI,CAAC,UAAA,EAAY,aAAA,EAAe,YAAA,EAAc,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,SAAA,EAAW,aAAa,CAAC,CAAA;AAE5H,SAAS,oBAAoBR,KAAAA,EAAwD;AACnF,EAAA,MAAM,WAAoC,EAAC;AAC3C,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQA,KAAI,CAAA,EAAG;AACzC,IAAA,IAAI,cAAA,CAAe,GAAA,CAAI,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG;AACvC,MAAA,QAAA,CAAS,CAAC,CAAA,GAAI,YAAA;AAAA,IAChB,WAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,CAAE,SAAS,GAAA,EAAK;AAClD,MAAA,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,gBAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA;AAAA,IAChB;AAAA,EACF;AACA,EAAA,OAAO,QAAA;AACT;AAEA,eAAe,cAAc,KAAA,EAQX;AAChB,EAAA,IAAI,CAAC,WAAA,EAAa;AAClB,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,CAAS,IAAA,CAAK,eAAe,CAAA,CAAE,MAAA,CAAO;AAAA,MAC1C,YAAY,WAAA,CAAY,QAAA;AAAA,MACxB,SAAS,WAAA,CAAY,MAAA;AAAA,MACrB,WAAW,KAAA,CAAM,QAAA;AAAA,MACjB,WAAW,KAAA,CAAM,SAAA,GAAY,mBAAA,CAAoB,KAAA,CAAM,SAAS,CAAA,GAAI,IAAA;AAAA,MACpE,UAAA,EAAY,MAAM,SAAA,IAAa,IAAA;AAAA,MAC/B,SAAA,EAAW,MAAM,QAAA,IAAY,IAAA;AAAA,MAC7B,eAAe,KAAA,CAAM,YAAA;AAAA,MACrB,eAAe,KAAA,CAAM,YAAA,EAAc,KAAA,CAAM,CAAA,EAAG,GAAI,CAAA,IAAK,IAAA;AAAA,MACrD,WAAA,EAAa,MAAM,UAAA,IAAc;AAAA,KAClC,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,MAAM,oCAAA,EAAsC,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,GAAG,CAAA;AAAA,EAC9F;AACF;AAMA,IAAM,WAAA,GAAc;AAAA,EAClB,OAAA;AAAA,EAAS,aAAA;AAAA,EAAe,UAAA;AAAA,EACxB,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,SAAA;AAAA,EACjB,UAAA;AAAA,EAAY;AACd,CAAA;AA0BA,IAAM,gBAAA,GAAoC;AAAA,EACxC,OAAA,EAAS,MAAA,CAAO,WAAA,CAAY,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,IAAI,CAAC,CAAC,CAAA;AAAA,EAC7D,SAAA,EAAW,EAAE,WAAA,EAAa,CAAC,GAAG,CAAA,EAAG,kBAAA,EAAoB,CAAC,GAAG,CAAA;AAC3D,CAAA;AAEA,SAAS,iBAAiB,GAAA,EAA+C;AACvE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,IAAA;AAC5C,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,kBAAA,CACP,QAAA,EACA,YAAA,EACA,aAAA,EACiB;AACjB,EAAA,IAAI,QAAA,KAAa,cAAc,OAAO,gBAAA;AAEtC,EAAA,MAAM,IAAA,GAAO,iBAAiB,YAAY,CAAA;AAC1C,EAAA,MAAM,SAAA,GAAY,iBAAiB,aAAa,CAAA;AAEhD,EAAA,MAAM,UAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,OAAO,WAAA,EAAa;AAC7B,IAAA,MAAM,OAAA,GAAU,SAAA,EAAW,OAAA,GAAU,GAAG,CAAA;AACxC,IAAA,MAAM,OAAA,GAAU,IAAA,EAAM,OAAA,GAAU,GAAG,CAAA;AACnC,IAAC,OAAA,CAAoC,GAAG,CAAA,GACtC,OAAA,KAAY,SAAY,OAAA,GAAU,OAAA,KAAY,SAAY,OAAA,GAAU,KAAA;AAAA,EACxE;AAEA,EAAA,MAAM,SAAA,GAAiC;AAAA,IACrC,aAAa,SAAA,EAAW,SAAA,EAAW,eAAe,IAAA,EAAM,SAAA,EAAW,eAAe,EAAC;AAAA,IACnF,oBAAoB,SAAA,EAAW,SAAA,EAAW,sBAAsB,IAAA,EAAM,SAAA,EAAW,sBAAsB;AAAC,GAC1G;AAEA,EAAA,OAAO,EAAE,SAAS,SAAA,EAAU;AAC9B;AAMA,SAAS,qBAAA,CACP,cACA,mBAAA,EACiB;AACjB,EAAA,MAAM,oBAAoB,YAAA,KAAiB,IAAA;AAC3C,EAAA,MAAM,YAAA,GAAe,mBAAA,CAAoB,QAAA,CAAS,GAAG,CAAA;AACrD,EAAA,MAAM,SAAA,GAAY,oBAAoB,MAAA,KAAW,CAAA;AAEjD,EAAA,IAAI,CAAC,iBAAA,IAAqB,YAAA,EAAc,OAAO,IAAA;AAC/C,EAAA,IAAI,CAAC,iBAAA,IAAqB,SAAA,EAAW,OAAO,EAAC;AAC7C,EAAA,IAAI,CAAC,mBAAmB,OAAO,mBAAA;AAC/B,EAAA,IAAI,cAAc,OAAO,YAAA;AACzB,EAAA,IAAI,SAAA,SAAkB,EAAC;AACvB,EAAA,OAAO,aAAa,MAAA,CAAO,CAAC,OAAO,mBAAA,CAAoB,QAAA,CAAS,EAAE,CAAC,CAAA;AACrE;AAGA,IAAM,eAAA,GAAsD;AAAA,EAC1D,cAAA,EAAgB,aAAA;AAAA,EAChB,aAAA,EAAe,aAAA;AAAA,EACf,WAAA,EAAa,aAAA;AAAA,EACb,WAAA,EAAa,aAAA;AAAA,EACb,YAAA,EAAc,aAAA;AAAA,EACd,aAAA,EAAe,aAAA;AAAA,EACf,aAAA,EAAe,aAAA;AAAA,EACf,aAAA,EAAe,aAAA;AAAA,EACf,aAAA,EAAe,aAAA;AAAA,EACf,gBAAA,EAAkB,aAAA;AAAA,EAClB,aAAA,EAAe,aAAA;AAAA,EACf,WAAA,EAAa,aAAA;AAAA,EACb,aAAA,EAAe,aAAA;AAAA,EACf,UAAA,EAAY,aAAA;AAAA,EACZ,aAAA,EAAe,aAAA;AAAA,EACf,UAAA,EAAY,OAAA;AAAA,EACZ,SAAA,EAAW,OAAA;AAAA,EACX,WAAA,EAAa,OAAA;AAAA,EACb,aAAA,EAAe,SAAA;AAAA,EACf,UAAA,EAAY,SAAA;AAAA,EACZ,YAAA,EAAc,SAAA;AAAA,EACd,YAAA,EAAc,SAAA;AAAA,EACd,YAAA,EAAc,SAAA;AAAA,EACd,GAAG,uBAAA;AAAA,EACH,GAAG;AACL,CAAA;AAeA,IAAI,WAAA,GAAkC,IAAA;AAEtC,eAAe,eAAe,GAAA,EAA0C;AACtE,EAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,KAAK,CAAA,IAAK,GAAA,CAAI,WAAW,EAAA,EAAI;AAC/C,IAAA,OAAA,CAAQ,MAAM,sDAAsD,CAAA;AACpE,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,WAAW,QAAQ,CAAA,CAAE,OAAO,GAAG,CAAA,CAAE,OAAO,KAAK,CAAA;AAE7D,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,KAAA,CAAM,OAAO,CAAA;AAC/C,EAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,eAAe,GAAM,CAAA;AAC1D,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,sDAAA,EAAyD,QAAQ,CAAA,WAAA,CAAa,CAAA;AAC5F,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,QAAA,CAC3B,IAAA,CAAK,uBAAuB,CAAA,CAC5B,MAAA,CAAO,iEAAiE,CAAA,CACxE,EAAA,CAAG,gBAAgB,OAAO,CAAA,CAC1B,GAAG,WAAA,EAAa,IAAI,EACpB,MAAA,EAAO;AAEV,EAAA,IAAI,KAAA,IAAS,CAAC,IAAA,EAAM;AAClB,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,+BAAA,EAAkC,SAAA,CAAU,SAAS,CAAA,oBAAA,CAAsB,CAAA;AACzF,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,CAAK,cAAc,IAAI,IAAA,CAAK,KAAK,UAAU,CAAA,mBAAI,IAAI,IAAA,EAAK,EAAG;AAC7D,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,qBAAA,EAAwB,SAAA,CAAU,SAAS,CAAA,oBAAA,CAAsB,CAAA;AAC/E,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,OAAO,SAAA,EAAU,GAAI,MAAM,QAAA,CAChD,IAAA,CAAK,MAAM,CAAA,CACX,MAAA,CAAO,2DAA2D,CAAA,CAClE,EAAA,CAAG,MAAM,IAAA,CAAK,UAAU,EACxB,MAAA,EAAO;AAEV,EAAA,IAAI,SAAA,IAAa,CAAC,QAAA,EAAU;AAC1B,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,oCAAA,EAAuC,IAAA,CAAK,UAAU,CAAA,CAAE,CAAA;AACtE,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAY,QAAA,CAAS,IAAA,EAA4B,IAAA,IAAQ,MAAA;AAC/D,EAAA,MAAM,YAAA,GAAgB,QAAA,CAAS,IAAA,EAA4C,mBAAA,IAAuB,EAAC;AACnG,EAAA,MAAM,aAAA,GAAgB,SAAS,WAAA,IAAe,IAAA;AAC9C,EAAA,MAAM,WAAA,GAAc,kBAAA,CAAmB,QAAA,EAAU,YAAA,EAAc,aAAa,CAAA;AAE5E,EAAA,MAAM,gBAAA,GAAmB,qBAAA;AAAA,IACvB,IAAA,CAAK,kBAAA;AAAA,IACL,YAAY,SAAA,CAAU;AAAA,GACxB;AAEA,EAAA,MAAM,SACH,IAAA,CAAK,uBAAuB,CAAA,CAC5B,MAAA,CAAO,EAAE,YAAA,EAAA,iBAAc,IAAI,IAAA,EAAK,EAAE,aAAY,EAAG,EACjD,EAAA,CAAG,IAAA,EAAM,KAAK,EAAE,CAAA;AAEnB,EAAA,MAAM,WAAA,GAAc,YAAY,MAAA,CAAO,CAAC,MAAM,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAE,MAAA;AACtE,EAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,sBAAA,EAAyB,IAAA,CAAK,UAAU,CAAA,QAAA,EAAW,QAAQ,CAAA,WAAA,EAAc,WAAW,CAAA,CAAA,EAAI,WAAA,CAAY,MAAM,CAAA,CAAA,CAAG,CAAA;AAE3H,EAAA,OAAO;AAAA,IACL,UAAU,IAAA,CAAK,EAAA;AAAA,IACf,UAAA,EAAY,KAAK,IAAA,IAAQ,SAAA;AAAA,IACzB,QAAQ,IAAA,CAAK,UAAA;AAAA,IACb,gBAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AACF;AAOA,SAASU,WAAAA,CACP,OAAA,EACA,IAAA,EACA,OAAA,GAA4C,EAAC,EACc;AAC3D,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,KAAA,GAAQC,KAAAA,CAAM,OAAA,EAAS,IAAA,EAAM,EAAE,GAAA,EAAK,OAAA,CAAQ,GAAA,EAAK,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM,GAAG,CAAA;AACxF,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAM;AAAE,MAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,IAAG,CAAC,CAAA;AAC1D,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAM;AAAE,MAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,IAAG,CAAC,CAAA;AAC1D,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,OAAA,CAAQ,EAAE,QAAQ,MAAA,EAAQ,MAAA,GAAS,OAAO,GAAG,CAAA,EAAG,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,IAC5D,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAA,IAAQ,IAAI,CAAA;AAAA,IAC9C,CAAC,CAAA;AACD,IAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW;AAC/B,MAAA,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA;AAC/B,MAAA,KAAA,CAAM,MAAM,GAAA,EAAI;AAAA,IAClB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,MAAM,GAAA,EAAI;AAAA,IAClB;AAAA,EACF,CAAC,CAAA;AACH;AASA,eAAe,kBAAkB,KAAA,EAA8D;AAC7F,EAAA,MAAM,SAAS,CAAC,CAAA,KAAc,EAAE,UAAA,CAAW,GAAG,IAC1CC,IAAAA,CAAK,OAAA,CAAQ,IAAI,IAAA,IAAQ,OAAA,CAAQ,IAAI,WAAA,IAAe,EAAA,EAAI,EAAE,KAAA,CAAM,CAAC,CAAC,CAAA,GAClE,CAAA;AACJ,EAAA,MAAM,SAAA,GAAY,OAAO,KAAK,CAAA;AAC9B,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAA,GAAU,SAAA;AAAA,EACZ,CAAA,MAAA,IAAWC,UAAAA,CAAW,CAAA,EAAG,SAAS,MAAM,CAAA,EAAG;AACzC,IAAA,OAAA,GAAU,GAAG,SAAS,CAAA,IAAA,CAAA;AAAA,EACxB,CAAA,MAAA,IAAWA,UAAAA,CAAW,SAAS,CAAA,EAAG;AAEhC,IAAA,OAAA,GAAU,SAAA;AAAA,EACZ,CAAA,MAAO;AACL,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,SAAS,CAAA,aAAA,EAAgB,SAAS,CAAA,KAAA,CAAO,CAAA;AAAA,EACtF;AACA,EAAA,MAAM,WAAW,MAAM,QAAA,CAAS,OAAA,EAAS,MAAM,GAAG,IAAA,EAAK;AACvD,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,OAAO,CAAA,CAAE,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC5B;AAOA,SAAS,0BAA0B,UAAA,EAA4B;AAC7D,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AAC3C,EAAA,IAAI,MAAM,MAAA,GAAS,CAAA,IAAK,CAAC,KAAA,CAAM,CAAC,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,MAAM,oEAAoE,CAAA;AAAA,EACtF;AACA,EAAA,MAAM,YAAY,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,CAAC,GAAG,QAAQ,CAAA;AAChD,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,SAAS,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACtF,EAAA,OAAO,UAAU,IAAI,CAAA,CAAA;AACvB;AAQA,eAAe,aAAA,CAAc,UAAA,EAAoB,SAAA,EAAmB,SAAA,EAAoC;AACtG,EAAA,MAAM,SAAS,MAAMH,WAAAA;AAAA,IACnB,YAAA;AAAA,IACA,CAAC,IAAA,EAAM,MAAA,EAAQ,MAAM,UAAA,EAAY,IAAA,EAAM,WAAW,IAAI,CAAA;AAAA,IACtD,EAAE,OAAO,SAAA;AAAU,GACrB;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,OAAO,IAAI,CAAA,kJAAA,EAGhC,OAAO,MAAA,CAAO,IAAA,MAAU,SAAS,CAAA;AAAA,KAC9C;AAAA,EACF;AACA,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,qBAAqB,CAAA,EAAG;AAClD,IAAA,MAAM,IAAI,MAAM,CAAA,+CAAA,EAAkD,MAAA,CAAO,OAAO,IAAA,EAAK,IAAK,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,EACxG;AACA,EAAA,OAAO,MAAA,CAAO,MAAA;AAChB;AAMA,eAAe,eAAA,CACb,UAAA,EACA,SAAA,EACA,SAAA,EACA,SAAA,EACkB;AAClB,EAAA,MAAM,MAAM,MAAM,OAAA,CAAQE,KAAK,MAAA,EAAO,EAAG,iBAAiB,CAAC,CAAA;AAC3D,EAAA,IAAI;AACF,IAAA,MAAM,cAAA,GAAiB,CAAA,UAAA,EAAa,UAAA,CAAW,IAAA,EAAM;AAAA,CAAA;AACrD,IAAA,MAAM,WAAA,GAAcA,IAAAA,CAAK,GAAA,EAAK,iBAAiB,CAAA;AAC/C,IAAA,MAAM,OAAA,GAAUA,IAAAA,CAAK,GAAA,EAAK,KAAK,CAAA;AAC/B,IAAA,MAAM,SAAA,CAAU,WAAA,EAAa,cAAA,EAAgB,MAAM,CAAA;AACnD,IAAA,MAAM,SAAA,CAAU,OAAA,EAAS,SAAA,EAAW,MAAM,CAAA;AAC1C,IAAA,MAAM,SAAS,MAAMF,WAAAA;AAAA,MACnB,YAAA;AAAA,MACA,CAAC,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,OAAA,EAAS,IAAI,CAAA;AAAA,MAC3F,EAAE,OAAO,SAAA;AAAU,KACrB;AACA,IAAA,OAAO,OAAO,IAAA,KAAS,CAAA;AAAA,EACzB,CAAA,SAAE;AACA,IAAA,MAAM,EAAA,CAAG,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EACvE;AACF;AAkBA,eAAe,cAAA,CACb,iBACA,gBAAA,EAC6B;AAC7B,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,CAAkB,eAAe,CAAA;AACxD,IAAA,OAAA,GAAU,QAAA,CAAS,OAAA;AACnB,IAAA,OAAA,GAAU,QAAA,CAAS,OAAA;AAAA,EACrB,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,kBAAkB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAClF,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI;AACF,IAAA,WAAA,GAAc,0BAA0B,OAAO,CAAA;AAAA,EACjD,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,kBAAkB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAClF,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,KAAA,CAAM,WAAW,CAAA;AACnD,EAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,eAAe,GAAM,CAAA;AAC1D,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,8DAAA,EAAiE,QAAQ,CAAA,WAAA,CAAa,CAAA;AACpG,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,GAAA,CAAI,4BAAA,KAAiC,GAAA;AAChE,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAY,WAAA,CAAY,EAAE,CAAA,CAAE,SAAS,KAAK,CAAA;AAChD,MAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc,OAAA,EAAS,WAAW,kBAAkB,CAAA;AAC5E,MAAA,MAAM,WAAW,MAAM,eAAA,CAAgB,OAAA,EAAS,SAAA,EAAW,WAAW,kBAAkB,CAAA;AACxF,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAA,CAAQ,MAAM,4FAA4F,CAAA;AAC1G,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,6BAA6B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC7F,MAAA,OAAA,CAAQ,MAAM,yHAAyH,CAAA;AACvI,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,MAAM,MAAA,EAAQ,KAAA,EAAO,QAAO,GAAI,MAAM,QAAA,CAC3C,IAAA,CAAK,uBAAuB,CAAA,CAC5B,OAAO,iCAAiC,CAAA,CACxC,GAAG,oBAAA,EAAsB,WAAW,EACpC,EAAA,CAAG,WAAA,EAAa,IAAI,CAAA,CACpB,WAAA,EAAY;AAEf,EAAA,IAAI,MAAA,IAAU,CAAC,MAAA,EAAQ;AACrB,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,CAAA,oCAAA,EAAuC,WAAW,CAAA,EAAA,EAAK,SAAA,CAAU,SAAS,CAAA,iFAAA;AAAA,KAE5E;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,eAAe,gBAAA,EAAkB;AAC1C,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,CAAA,SAAA,EAAY,OAAO,IAAI,CAAA,uIAAA;AAAA,KAEzB;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,MAAM,MAAA,EAAQ,KAAA,EAAO,QAAO,GAAI,MAAM,QAAA,CAC3C,IAAA,CAAK,uBAAuB,CAAA,CAC5B,OAAO,iEAAiE,CAAA,CACxE,EAAA,CAAG,IAAA,EAAM,MAAA,CAAO,UAAU,EAC1B,EAAA,CAAG,WAAA,EAAa,IAAI,CAAA,CACpB,WAAA,EAAY;AAEf,EAAA,IAAI,MAAA,IAAU,CAAC,MAAA,EAAQ;AACrB,IAAA,OAAA,CAAQ,MAAM,gEAAgE,CAAA;AAC9E,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,cAAc,IAAI,IAAA,CAAK,OAAO,UAAU,CAAA,mBAAI,IAAI,IAAA,EAAK,EAAG;AACjE,IAAA,OAAA,CAAQ,MAAM,uCAAuC,CAAA;AACrD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,OAAO,SAAA,EAAU,GAAI,MAAM,QAAA,CAChD,IAAA,CAAK,MAAM,CAAA,CACX,MAAA,CAAO,2DAA2D,CAAA,CAClE,EAAA,CAAG,MAAM,MAAA,CAAO,UAAU,EAC1B,MAAA,EAAO;AAEV,EAAA,IAAI,SAAA,IAAa,CAAC,QAAA,EAAU;AAC1B,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,oCAAA,EAAuC,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAY,QAAA,CAAS,IAAA,EAA4B,IAAA,IAAQ,MAAA;AAC/D,EAAA,MAAM,YAAA,GAAgB,QAAA,CAAS,IAAA,EAA4C,mBAAA,IAAuB,EAAC;AACnG,EAAA,MAAM,aAAA,GAAgB,SAAS,WAAA,IAAe,IAAA;AAC9C,EAAA,MAAM,WAAA,GAAc,kBAAA,CAAmB,QAAA,EAAU,YAAA,EAAc,aAAa,CAAA;AAE5E,EAAA,MAAM,gBAAA,GAAmB,qBAAA;AAAA,IACvB,MAAA,CAAO,kBAAA;AAAA,IACP,YAAY,SAAA,CAAU;AAAA,GACxB;AAEA,EAAA,MAAM,MAAA,GAAA,iBAAS,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACtC,EAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChB,QAAA,CAAS,IAAA,CAAK,uBAAuB,CAAA,CAAE,MAAA,CAAO,EAAE,YAAA,EAAc,MAAA,EAAQ,CAAA,CAAE,EAAA,CAAG,IAAA,EAAM,OAAO,EAAE,CAAA;AAAA,IAC1F,QAAA,CAAS,IAAA,CAAK,uBAAuB,CAAA,CAAE,MAAA,CAAO,EAAE,YAAA,EAAc,MAAA,EAAQ,CAAA,CAAE,EAAA,CAAG,IAAA,EAAM,OAAO,EAAE;AAAA,GAC3F,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,YAAY,MAAA,CAAO,CAAC,MAAM,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAE,MAAA;AACtE,EAAA,OAAA,CAAQ,KAAA;AAAA,IACN,8BAA8B,MAAA,CAAO,IAAI,SAAS,WAAA,CAAY,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,aAAA,EAC/D,MAAA,CAAO,UAAU,CAAA,QAAA,EAAW,QAAQ,cAAc,WAAW,CAAA,CAAA,EAAI,YAAY,MAAM,CAAA,CAAA;AAAA,GAChG;AAEA,EAAA,OAAO;AAAA,IACL,UAAU,MAAA,CAAO,EAAA;AAAA,IACjB,YAAY,CAAA,EAAG,MAAA,CAAO,QAAQ,SAAS,CAAA,OAAA,EAAU,OAAO,IAAI,CAAA,CAAA,CAAA;AAAA,IAC5D,QAAQ,MAAA,CAAO,UAAA;AAAA,IACf,gBAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AACF;AAMA,SAAS,mBAAmB,QAAA,EAAwB;AAClD,EAAA,IAAI,CAAC,WAAA,EAAa,MAAM,IAAI,MAAM,mBAAmB,CAAA;AACrD,EAAA,IAAI,WAAA,CAAY,qBAAqB,IAAA,EAAM;AAC3C,EAAA,IAAI,CAAC,WAAA,CAAY,gBAAA,CAAiB,QAAA,CAAS,QAAQ,CAAA,EAAG;AACpD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qDAAA,EAAwD,QAAQ,CAAA,CAAE,CAAA;AAAA,EACpF;AACF;AAUA,eAAe,8BACb,WAAA,EACoD;AACpD,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAM,GAAI,MAAM,QAAA,CACpC,IAAA,CAAK,iBAAiB,CAAA,CACtB,OAAO,UAAU,CAAA,CACjB,MAAM,MAAA,EAAQ,WAAW,EACzB,WAAA,EAAY;AAEf,EAAA,IAAI,OAAO,MAAM,IAAI,MAAM,CAAA,mCAAA,EAAsC,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAEhF,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAI,GAAI,MAAM,QAAA,CACzB,IAAA,CAAK,iBAAiB,CAAA,CACtB,MAAA,CAAO,MAAM,CAAA,CACb,MAAM,MAAM,CAAA;AACf,IAAA,MAAM,KAAA,GAAA,CAAS,GAAA,IAAO,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACtD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iBAAA,EAAoB,WAAW,CAAA,iCAAA,EAAoC,KAAA,IAAS,QAAQ,CAAA;AAAA,KACtF;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,QAAA,KAAa,MAAM,QAAA,CAC7C,IAAA,CAAK,uBAAuB,EAC5B,MAAA,CAAO,IAAI,EACX,EAAA,CAAG,oBAAA,EAAsB,QAAQ,EAAE,CAAA;AAEtC,EAAA,IAAI,UAAU,MAAM,IAAI,MAAM,CAAA,0BAAA,EAA6B,QAAA,CAAS,OAAO,CAAA,CAAE,CAAA;AAC7E,EAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,OAAA,CAAQ,IAAI,CAAA,0BAAA,CAA4B,CAAA;AAAA,EAC9E;AAEA,EAAA,OAAO,EAAE,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA,EAAG,SAAA,EAAW,OAAA,CAAQ,EAAA,EAAG;AACpE;AAMA,eAAe,2BACb,QAAA,EACiC;AACjC,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAEnC,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,MAAM,QAAA,CAC5B,IAAA,CAAK,uBAAuB,CAAA,CAC5B,MAAA,CAAO,wBAAwB,CAAA,CAC/B,EAAA,CAAG,MAAM,QAAQ,CAAA;AAEpB,EAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,MAAA,KAAW,CAAA,SAAU,EAAC;AAE5C,EAAA,MAAM,UAAA,GAAa,CAAC,GAAG,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,kBAAkB,CAAC,CAAC,CAAA;AACvE,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,MAAM,QAAA,CAC9B,IAAA,CAAK,iBAAiB,CAAA,CACtB,MAAA,CAAO,UAAU,CAAA,CACjB,EAAA,CAAG,MAAM,UAAU,CAAA;AAEtB,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AAEvB,EAAA,MAAM,aAAqC,EAAC;AAC5C,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU,UAAA,CAAW,CAAA,CAAE,EAAE,IAAI,CAAA,CAAE,IAAA;AAE/C,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAA,CAAO,EAAE,EAAE,CAAA,GAAI,UAAA,CAAW,CAAA,CAAE,kBAAkB,CAAA,IAAK,SAAA;AAAA,EACrD;AACA,EAAA,OAAO,MAAA;AACT;AAMA,IAAM,aAAA,GAAgB,aAAA;AACtB,IAAM,aAAA,GAAgB,EAAA;AACtB,IAAM,cAAA,GAAiB,EAAA;AAEvB,SAAS,gBAAA,GAA2B;AAClC,EAAA,IAAI,CAAC,aAAA,EAAe,MAAM,IAAI,MAAM,+CAA+C,CAAA;AACnF,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,aAAA,EAAe,KAAK,CAAA;AAC5C,EAAA,IAAI,IAAI,MAAA,KAAW,EAAA,EAAI,MAAM,IAAI,MAAM,kDAAkD,CAAA;AACzF,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,QAAQ,IAAA,EAAsB;AACrC,EAAA,MAAM,MAAM,gBAAA,EAAiB;AAC7B,EAAA,MAAM,EAAA,GAAK,YAAY,aAAa,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,aAAA,EAAe,IAAI,UAAA,CAAW,GAAG,CAAA,EAAG,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AACpF,EAAA,IAAI,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,QAAQ,KAAK,CAAA;AACjD,EAAA,SAAA,IAAa,MAAA,CAAO,MAAM,KAAK,CAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,OAAO,UAAA,EAAW;AAClC,EAAA,OAAO,OAAO,MAAA,CAAO;AAAA,IACnB,IAAI,WAAW,EAAE,CAAA;AAAA,IACjB,IAAI,WAAW,OAAO,CAAA;AAAA,IACtB,IAAI,UAAA,CAAW,MAAA,CAAO,IAAA,CAAK,SAAA,EAAW,KAAK,CAAC;AAAA,GAC7C,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA;AACtB;AAEA,SAAS,QAAQ,OAAA,EAAyB;AACxC,EAAA,MAAM,MAAM,gBAAA,EAAiB;AAC7B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,QAAQ,CAAA;AACzC,EAAA,MAAM,EAAA,GAAK,GAAA,CAAI,QAAA,CAAS,CAAA,EAAG,aAAa,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,QAAA,CAAS,aAAA,EAAe,gBAAgB,cAAc,CAAA;AAC1E,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,QAAA,CAAS,aAAA,GAAgB,cAAc,CAAA;AAC7D,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,aAAA,EAAe,IAAI,UAAA,CAAW,GAAG,CAAA,EAAG,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AACxF,EAAA,QAAA,CAAS,UAAA,CAAW,IAAI,UAAA,CAAW,OAAO,CAAC,CAAA;AAC3C,EAAA,IAAI,SAAA,GAAY,SAAS,MAAA,CAAO,SAAA,CAAU,SAAS,KAAK,CAAA,EAAG,OAAO,MAAM,CAAA;AACxE,EAAA,SAAA,IAAa,QAAA,CAAS,MAAM,MAAM,CAAA;AAClC,EAAA,OAAO,SAAA;AACT;AAMA,IAAM,UAAA,GAAa,wBAAA;AAMnB,SAAS,gBAAgB,OAAA,EAAyC;AAChE,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA,EAAG;AACtC,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AACzC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACjC,IAAA,IAAI,UAAU,EAAA,EAAI;AAClB,IAAA,MAAM,MAAM,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,KAAK,EAAE,IAAA,EAAK;AACzC,IAAA,IAAI,QAAQ,OAAA,CAAQ,KAAA,CAAM,KAAA,GAAQ,CAAC,EAAE,IAAA,EAAK;AAC1C,IAAA,IACG,KAAA,CAAM,UAAA,CAAW,GAAG,CAAA,IAAK,MAAM,QAAA,CAAS,GAAG,CAAA,IAC3C,KAAA,CAAM,WAAW,GAAG,CAAA,IAAK,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA,EAC5C;AACA,MAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,IAC3B;AACA,IAAA,IAAI,GAAA,EAAK,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,EACzB;AACA,EAAA,OAAO,MAAA;AACT;AAsBA,SAAS,oBAAA,CACP,WACA,WAAA,EAC4F;AAC5F,EAAA,IAAI,cAAc,MAAA,EAAQ,OAAO,EAAE,MAAA,EAAQ,CAAC,YAAY,CAAA,EAAE;AAC1D,EAAA,IAAI,aAAa,OAAO,EAAE,oBAAA,EAAsB,CAAC,WAAW,CAAA,EAAE;AAC9D,EAAA,OAAO,EAAE,MAAA,EAAQ,CAAC,SAAS,CAAA,EAAE;AAC/B;AAGA,SAAS,0BAAA,CACP,WACA,WAAA,EACmG;AACnG,EAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,SAAA,EAAW,WAAW,CAAA;AAC3D,EAAA,IAAI,SAAA,KAAc,KAAA,EAAO,OAAO,CAAC,OAAO,CAAA;AACxC,EAAA,OAAO,CAAC,OAAA,EAAS,EAAE,QAAQ,CAAC,aAAa,GAAG,CAAA;AAC9C;AAKA,eAAe,mBAAA,CACb,KAAA,EACA,SAAA,EACA,OAAA,EACoD;AACpD,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG,OAAO,EAAE,OAAA,EAAS,CAAA,EAAG,OAAO,IAAA,EAAK;AAE3D,EAAA,MAAM,MAAM,MAAM,KAAA;AAAA,IAChB,CAAA,EAAG,UAAU,CAAA,cAAA,EAAiB,kBAAA,CAAmB,SAAS,CAAC,CAAA,gBAAA,CAAA;AAAA,IAC3D;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA;AAAA,QAC9B,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA;AAC9B,GACF;AAEA,EAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,IAAA,MAAM,OAAO,MAAM,GAAA,CAAI,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AAC5C,IAAA,OAAO,EAAE,SAAS,CAAA,EAAG,KAAA,EAAO,cAAc,GAAA,CAAI,MAAM,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAG;AAAA,EAClE;AAEA,EAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AAC9C,EAAA,OAAO,EAAE,SAAU,IAAA,EAAc,OAAA,EAAS,UAAU,OAAA,CAAQ,MAAA,EAAQ,OAAO,IAAA,EAAK;AAClF;AASA,eAAe,iBAAA,CAAkB,OAAA,EAAiB,WAAA,EAAqB,YAAA,EAAwC;AAC7G,EAAA,IAAI;AAEF,IAAA,IAAI,OAAA,GAAU,YAAA;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,MAAM,SAC5B,IAAA,CAAK,YAAY,CAAA,CACjB,MAAA,CAAO,0BAA0B,CAAA,CACjC,GAAG,UAAA,EAAY,OAAO,CAAA,CACtB,GAAA,CAAI,0BAAA,EAA4B,IAAA,EAAM,IAAI,CAAA,CAC1C,KAAA,CAAM,CAAC,CAAA,CACP,MAAA,EAAO;AAEV,MAAA,OAAA,GAAU,MAAA,EAAQ,wBAAA;AAAA,IACpB;AACA,IAAA,IAAI,CAAC,SAAS,OAAO,0CAAA;AAGrB,IAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,MAAM,QAAA,CAC9B,IAAA,CAAK,aAAa,CAAA,CAClB,MAAA,CAAO,wBAAwB,CAAA,CAC/B,WAAA,EAAY;AAEf,IAAA,IAAI,CAAC,QAAA,EAAU,sBAAA,EAAwB,OAAO,iDAAA;AAE9C,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,OAAA,CAAQ,SAAS,sBAAsB,CAAA;AAAA,IACjD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,oDAAA;AAAA,IACT;AAGA,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,SAC3B,IAAA,CAAK,uBAAuB,CAAA,CAC5B,MAAA,CAAO,uBAAuB,CAAA,CAC9B,EAAA,CAAG,IAAA,EAAM,OAAO,EAChB,MAAA,EAAO;AAEV,IAAA,IAAI,CAAC,OAAO,OAAO,sCAAA;AAEnB,IAAA,MAAM,YAAY,KAAA,CAAM,KAAA;AACxB,IAAA,MAAM,SAAA,GAAyB,KAAA,CAAM,UAAA,IAA6B,EAAC;AACnE,IAAA,MAAM,aAAa,SAAA,CAAU,MAAA;AAAA,MAC3B,CAAC,CAAA,KAAM,CAAA,CAAE,iBAAiB,QAAA,IAAY,CAAA,CAAE,WAAW,CAAA,CAAE;AAAA,KACvD;AAEA,IAAA,IAAI,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG,OAAO,8CAAA;AAGpC,IAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAW,GAAI,MAAM,QAAA,CAChC,IAAA,CAAK,YAAY,CAAA,CACjB,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,4BAA4B,OAAO,CAAA;AAEzC,IAAA,IAAI,CAAC,UAAA,IAAc,UAAA,CAAW,MAAA,KAAW,GAAG,OAAO,+CAAA;AAEnD,IAAA,MAAM,UAAA,GAAqC;AAAA,MACzC,GAAA,EAAK,aAAA;AAAA,MACL,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM;AAAA,KACR;AACA,IAAA,MAAM,eAAA,GAAkB,UAAA,CAAW,SAAS,CAAA,IAAK,SAAA;AAGjD,IAAA,MAAM,cAAwB,EAAC;AAC/B,IAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,IAAA,CAAK,OAAA,CAAQ,SAAS,EAAE,CAAA;AACzC,MAAA,MAAM,SAAS,UAAA,CAAW,IAAA;AAAA,QACxB,CAAC,CAAA,KAAW,CAAA,CAAE,QAAA,KAAa,IAAA,IAAQ,EAAE,OAAA,KAAY;AAAA,OACnD;AAEA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,WAAA,CAAY,KAAK,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,kCAAA,EAAqC,eAAe,CAAA,EAAA,CAAI,CAAA;AACrF,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI;AACF,QAAA,UAAA,GAAa,OAAA,CAAS,OAAe,kBAAkB,CAAA;AAAA,MACzD,CAAA,CAAA,MAAQ;AACN,QAAA,WAAA,CAAY,IAAA,CAAK,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,gBAAA,CAAkB,CAAA;AAC/C,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,KAAA,GAAQ,gBAAgB,UAAU,CAAA;AACxC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAC9B,MAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,QAAA,WAAA,CAAY,IAAA,CAAK,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,cAAA,CAAgB,CAAA;AAC7C,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAA,GAAa,0BAAA,CAA2B,SAAA,EAAW,GAAA,CAAI,iBAAiB,CAAA;AAC9E,MAAA,IAAI,YAAA,GAAe,CAAA;AACnB,MAAA,IAAI,OAAA,GAAyB,IAAA;AAE7B,MAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,QAAA,MAAM,OAAA,GAA0B,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,UACjD,GAAA;AAAA,UACA,KAAA,EAAO,MAAM,GAAG,CAAA;AAAA,UAChB,IAAA,EAAM,WAAA;AAAA,UACN,GAAG;AAAA,SACL,CAAE,CAAA;AAEF,QAAA,MAAM,EAAE,SAAS,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,KAAA,EAAO,GAAA,CAAI,eAAA,EAAkB,OAAO,CAAA;AACzF,QAAA,IAAI,OAAO,OAAA,GAAU,KAAA;AAAA,aAChB,YAAA,IAAgB,OAAA;AAAA,MACvB;AAEA,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,WAAA,CAAY,KAAK,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,WAAA,EAAc,OAAO,CAAA,CAAE,CAAA;AAAA,MACtD,CAAA,MAAO;AACL,QAAA,WAAA,CAAY,KAAK,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,EAAA,EAAK,YAAY,CAAA,qBAAA,CAAuB,CAAA;AAAA,MACvE;AAAA,IACF;AAEA,IAAA,OAAO,CAAA,aAAA,EAAgB,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,EAC/C,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,IAAA,OAAO,sBAAsB,GAAG,CAAA,CAAA;AAAA,EAClC;AACF;AAiBA,SAAS,WAAW,GAAA,EAAqB;AACvC,EAAA,IAAI,GAAA,KAAQ,IAAI,OAAO,IAAA;AACvB,EAAA,IAAI,2BAAA,CAA4B,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AAClD,EAAA,OAAO,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,GAAI,GAAA;AAC5C;AAOA,SAAS,iBAAA,CAAkB,SAAiBV,KAAAA,EAAwB;AAClE,EAAA,MAAM,UAAU,uBAAA,CAAwB,IAAA,CAAK,OAAO,CAAA,GAAI,OAAA,GAAU,WAAW,OAAO,CAAA;AACpF,EAAA,IAAIA,KAAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,OAAA;AAC9B,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAIA,KAAAA,CAAK,IAAI,UAAU,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AACrD;AAQA,SAAS,6BAAA,CAA8B,SAAiBA,KAAAA,EAAwB;AAC9E,EAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,KAAc,GAAA,GAAM,EAAE,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAA,GAAI,GAAA;AACnE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAIA,KAAAA,CAAK,WAAW,CAAA,EAAG;AACrB,IAAA,IAAA,GAAO,OAAA;AAAA,EACT,CAAA,MAAO;AACL,IAAA,IAAA,GAAO,CAAA,EAAA,EAAK,aAAA,CAAc,OAAO,CAAC,CAAA,CAAA,EAAIA,KAAAA,CAAK,GAAA,CAAI,aAAa,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,EACzE;AAGA,EAAA,MAAM,MAAA,GAAS,2CAA2C,IAAI,CAAA,CAAA;AAC9D,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,SAAS,CAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA;AAInC,EAAA,OAAO,4GAA4G,GAAG,CAAA,CAAA;AACxH;AAkBA,IAAM,mBAAA,GAAsB,sCAAA;AAC5B,IAAI,eAAA,GAA+C,IAAA;AAEnD,eAAe,kBAAA,GAAoD;AACjE,EAAA,IAAI,iBAAiB,OAAO,eAAA;AAE5B,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,SAC3B,IAAA,CAAK,YAAY,CAAA,CACjB,MAAA,CAAO,+FAA+F,CAAA,CACtG,EAAA,CAAG,IAAA,EAAM,mBAAmB,EAC5B,MAAA,EAAO;AAEV,EAAA,IAAI,SAAS,CAAC,IAAA,EAAM,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAC5E,EAAA,IAAI,CAAC,aAAA,EAAe,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAE3F,EAAA,eAAA,GAAkB;AAAA,IAChB,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAA;AAAA,IACnB,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,UAAU,IAAA,CAAK,kBAAA,GAAqB,OAAA,CAAQ,IAAA,CAAK,kBAAkB,CAAA,GAAI,MAAA;AAAA,IACvE,YAAY,IAAA,CAAK,iBAAA,GAAoB,OAAA,CAAQ,IAAA,CAAK,iBAAiB,CAAA,GAAI,MAAA;AAAA,IACvE,YAAY,IAAA,CAAK,4BAAA,GAA+B,OAAA,CAAQ,IAAA,CAAK,4BAA4B,CAAA,GAAI;AAAA,GAC/F;AACA,EAAA,OAAO,eAAA;AACT;AAWA,eAAe,oBACb,QAAA,EACqF;AACrF,EAAA,kBAAA,CAAmB,QAAQ,CAAA;AAE3B,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,SAC3B,IAAA,CAAK,YAAY,CAAA,CACjB,MAAA,CAAO,yHAAyH,CAAA,CAChI,EAAA,CAAG,IAAA,EAAM,QAAQ,EACjB,MAAA,EAAO;AAEV,EAAA,IAAI,KAAA,IAAS,CAAC,IAAA,EAAM,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,QAAQ,CAAA,CAAE,CAAA;AACnE,EAAA,IAAI,CAAC,aAAA,EAAe,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAE3F,EAAA,MAAM,IAAA,GAA6B;AAAA,IACjC,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAA;AAAA,IACnB,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,UAAU,IAAA,CAAK,kBAAA,GAAqB,OAAA,CAAQ,IAAA,CAAK,kBAAkB,CAAA,GAAI,MAAA;AAAA,IACvE,YAAY,IAAA,CAAK,iBAAA,GAAoB,OAAA,CAAQ,IAAA,CAAK,iBAAiB,CAAA,GAAI,MAAA;AAAA,IACvE,YAAY,IAAA,CAAK,4BAAA,GAA+B,OAAA,CAAQ,IAAA,CAAK,4BAA4B,CAAA,GAAI;AAAA,GAC/F;AAEA,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,eAAA,KAAoB,IAAA,IAAQ,QAAA,KAAa,mBAAA;AACjE,EAAA,MAAM,KAAA,GAAQ,UAAA,GAAa,MAAM,kBAAA,EAAmB,GAAI,MAAA;AACxD,EAAA,MAAM,EAAA,GAAgB,IAAA,CAA8B,OAAA,KAAY,SAAA,GAAY,SAAA,GAAY,OAAA;AAExF,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,EAAA,EAAG;AAC3B;AAUA,eAAe,OAAA,CACb,IAAA,EACA,OAAA,EACA,KAAA,EACA,OAAA,EACoB;AACpB,EAAA,IAAI,OAAO,OAAO,eAAA,CAAgB,KAAA,EAAO,IAAA,EAAM,SAAS,OAAO,CAAA;AAE/D,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,GAAA,GAAM,IAAIc,MAAA,EAAU;AAC1B,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,IAAA,GAAO,KAAA;AACX,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,IAAW,GAAA;AAEhC,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,IAAI,CAAC,IAAA,EAAM;AAAE,QAAA,IAAA,GAAO,IAAA;AAAM,QAAA,GAAA,CAAI,GAAA,EAAI;AAAG,QAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAI,CAAA;AAAA,MAAG;AAAA,IAClF,GAAG,OAAO,CAAA;AAEV,IAAA,GAAA,CAAI,EAAA,CAAG,SAAS,MAAM;AAKpB,MAAA,MAAM,WAAW,OAAA,EAAS,GAAA,GAAM,EAAE,GAAA,EAAK,IAAA,KAAS,EAAC;AACjD,MAAA,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS,QAAA,EAAU,CAAC,KAAK,MAAA,KAAW;AAC3C,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,IAAI,CAAC,IAAA,EAAM;AAAE,YAAA,IAAA,GAAO,IAAA;AAAM,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,GAAA,CAAI,GAAA,EAAI;AAAG,YAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAI,CAAA;AAAA,UAAG;AACrG,UAAA;AAAA,QACF;AACA,QAAA,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,UAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,QAAG,CAAC,CAAA;AAC5D,QAAA,MAAA,CAAO,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,UAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,QAAG,CAAC,CAAA;AACnE,QAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAwB;AAC1C,UAAA,IAAI,CAAC,IAAA,EAAM;AAAE,YAAA,IAAA,GAAO,IAAA;AAAM,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,GAAA,CAAI,GAAA,EAAI;AAAG,YAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAA,IAAQ,GAAG,CAAA;AAAA,UAAG;AAAA,QAC9G,CAAC,CAAA;AACD,QAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAW;AAChC,UAAA,MAAA,CAAO,GAAA,CAAI,QAAQ,KAAK,CAAA;AAAA,QAC1B;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACvB,MAAA,IAAI,CAAC,IAAA,EAAM;AAAE,QAAA,IAAA,GAAO,IAAA;AAAM,QAAA,YAAA,CAAa,KAAK,CAAA;AAAG,QAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAI,OAAA,EAAS,QAAA,EAAU,IAAI,CAAA;AAAA,MAAG;AAAA,IACzG,CAAC,CAAA;AAED,IAAA,GAAA,CAAI,OAAA,CAAQ;AAAA,MACV,MAAM,IAAA,CAAK,QAAA;AAAA,MAAU,MAAM,IAAA,CAAK,IAAA;AAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AAAA,MACrD,UAAU,IAAA,CAAK,QAAA;AAAA,MAAU,YAAY,IAAA,CAAK,UAAA;AAAA,MAAY,YAAY,IAAA,CAAK,UAAA;AAAA,MACvE,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAEA,SAAS,eAAA,CACP,SAAA,EACA,UAAA,EACA,OAAA,EACA,OAAA,EACoB;AACpB,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,WAAA,GAAc,IAAIA,MAAA,EAAU;AAClC,IAAA,IAAI,IAAA,GAAO,KAAA;AACX,IAAA,MAAM,OAAA,GAAU,WAAW,OAAA,IAAW,GAAA;AAEtC,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,IAAI,CAAC,IAAA,EAAM;AAAE,QAAA,IAAA,GAAO,IAAA;AAAM,QAAA,WAAA,CAAY,GAAA,EAAI;AAAG,QAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,EAAA,EAAI,QAAQ,2BAAA,EAA6B,QAAA,EAAU,IAAI,CAAA;AAAA,MAAG;AAAA,IAC3H,GAAG,OAAO,CAAA;AAEV,IAAA,MAAM,UAAU,MAAM;AAAE,MAAA,YAAA,CAAa,KAAK,CAAA;AAAG,MAAA,WAAA,CAAY,GAAA,EAAI;AAAA,IAAG,CAAA;AAEhE,IAAA,WAAA,CAAY,EAAA,CAAG,SAAS,MAAM;AAC5B,MAAA,WAAA,CAAY,UAAA,CAAW,aAAa,CAAA,EAAG,UAAA,CAAW,UAAU,UAAA,CAAW,IAAA,EAAM,CAAC,GAAA,EAAK,MAAA,KAAW;AAC5F,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,IAAI,CAAC,IAAA,EAAM;AAAE,YAAA,IAAA,GAAO,IAAA;AAAM,YAAA,OAAA,EAAQ;AAAG,YAAA,OAAA,CAAQ,EAAE,QAAQ,EAAA,EAAI,MAAA,EAAQ,IAAI,OAAA,EAAS,QAAA,EAAU,IAAI,CAAA;AAAA,UAAG;AACjG,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,YAAA,GAAe,IAAIA,MAAA,EAAU;AACnC,QAAA,IAAI,MAAA,GAAS,EAAA;AACb,QAAA,IAAI,MAAA,GAAS,EAAA;AAEb,QAAA,YAAA,CAAa,EAAA,CAAG,SAAS,MAAM;AAC7B,UAAA,MAAM,WAAW,OAAA,EAAS,GAAA,GAAM,EAAE,GAAA,EAAK,IAAA,KAAS,EAAC;AACjD,UAAA,YAAA,CAAa,IAAA,CAAK,OAAA,EAAS,QAAA,EAAU,CAAC,SAAS,MAAA,KAAW;AACxD,YAAA,IAAI,OAAA,EAAS;AACX,cAAA,IAAI,CAAC,IAAA,EAAM;AAAE,gBAAA,IAAA,GAAO,IAAA;AAAM,gBAAA,YAAA,CAAa,GAAA,EAAI;AAAG,gBAAA,OAAA,EAAQ;AAAG,gBAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAI,CAAA;AAAA,cAAG;AACpG,cAAA;AAAA,YACF;AACA,YAAA,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,cAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,YAAG,CAAC,CAAA;AAC5D,YAAA,MAAA,CAAO,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,cAAA,MAAA,IAAU,EAAE,QAAA,EAAS;AAAA,YAAG,CAAC,CAAA;AACnE,YAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAwB;AAC1C,cAAA,IAAI,CAAC,IAAA,EAAM;AAAE,gBAAA,IAAA,GAAO,IAAA;AAAM,gBAAA,YAAA,CAAa,GAAA,EAAI;AAAG,gBAAA,OAAA,EAAQ;AAAG,gBAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAA,IAAQ,GAAG,CAAA;AAAA,cAAG;AAAA,YAC7G,CAAC,CAAA;AACD,YAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAW;AAChC,cAAA,MAAA,CAAO,GAAA,CAAI,QAAQ,KAAK,CAAA;AAAA,YAC1B;AAAA,UACF,CAAC,CAAA;AAAA,QACH,CAAC,CAAA;AAED,QAAA,YAAA,CAAa,EAAA,CAAG,OAAA,EAAS,CAAC,SAAA,KAAc;AACtC,UAAA,IAAI,CAAC,IAAA,EAAM;AAAE,YAAA,IAAA,GAAO,IAAA;AAAM,YAAA,YAAA,CAAa,GAAA,EAAI;AAAG,YAAA,OAAA,EAAQ;AAAG,YAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,UAAU,OAAA,EAAS,QAAA,EAAU,IAAI,CAAA;AAAA,UAAG;AAAA,QACzH,CAAC,CAAA;AAED,QAAA,YAAA,CAAa,OAAA,CAAQ;AAAA,UACnB,IAAA,EAAM,MAAA;AAAA,UACN,UAAU,UAAA,CAAW,QAAA;AAAA,UAAU,UAAU,UAAA,CAAW,QAAA;AAAA,UACpD,YAAY,UAAA,CAAW,UAAA;AAAA,UAAY,YAAY,UAAA,CAAW,UAAA;AAAA,UAC1D,YAAA,EAAc;AAAA,SACf,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,WAAA,CAAY,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAC/B,MAAA,IAAI,CAAC,IAAA,EAAM;AAAE,QAAA,IAAA,GAAO,IAAA;AAAM,QAAA,OAAA,EAAQ;AAAG,QAAA,OAAA,CAAQ,EAAE,QAAQ,EAAA,EAAI,MAAA,EAAQ,IAAI,OAAA,EAAS,QAAA,EAAU,IAAI,CAAA;AAAA,MAAG;AAAA,IACnG,CAAC,CAAA;AAED,IAAA,WAAA,CAAY,OAAA,CAAQ;AAAA,MAClB,MAAM,SAAA,CAAU,QAAA;AAAA,MAAU,MAAM,SAAA,CAAU,IAAA;AAAA,MAAM,UAAU,SAAA,CAAU,QAAA;AAAA,MACpE,UAAU,SAAA,CAAU,QAAA;AAAA,MAAU,YAAY,SAAA,CAAU,UAAA;AAAA,MAAY,YAAY,SAAA,CAAU,UAAA;AAAA,MACtF,YAAA,EAAc,UAAU,OAAA,IAAW;AAAA,KACpC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAMA,SAAS,gBAAA,CACP,IAAA,EACA,KAAA,EACA,YAAA,GAAe,KACf,YAAA,EACqD;AACrD,EAAA,MAAM,WAAW,YAAA,EAAc,QAAA;AAC/B,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,GAAA,GAAM,IAAIA,MAAA,EAAU;AAC1B,MAAA,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAS,MAAM,GAAA,CAAI,GAAA,EAAI,EAAG,CAAC,CAAA;AACxE,MAAA,GAAA,CAAI,GAAG,OAAA,EAAS,CAAC,CAAA,KAAM,MAAA,CAAO,CAAC,CAAC,CAAA;AAChC,MAAA,GAAA,CAAI,OAAA,CAAQ;AAAA,QACV,MAAM,IAAA,CAAK,QAAA;AAAA,QAAU,MAAM,IAAA,CAAK,IAAA;AAAA,QAAM,UAAU,IAAA,CAAK,QAAA;AAAA,QACrD,UAAU,IAAA,CAAK,QAAA;AAAA,QAAU,YAAY,IAAA,CAAK,UAAA;AAAA,QAAY,YAAY,IAAA,CAAK,UAAA;AAAA,QACvE,YAAA;AAAA,QACA,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,OAChC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,WAAA,GAAc,IAAIA,MAAA,EAAU;AAElC,IAAA,WAAA,CAAY,EAAA,CAAG,SAAS,MAAM;AAC5B,MAAA,WAAA,CAAY,UAAA,CAAW,aAAa,CAAA,EAAG,IAAA,CAAK,UAAU,IAAA,CAAK,IAAA,EAAM,CAAC,GAAA,EAAK,MAAA,KAAW;AAChF,QAAA,IAAI,GAAA,EAAK;AAAE,UAAA,WAAA,CAAY,GAAA,EAAI;AAAG,UAAA,MAAA,CAAO,GAAG,CAAA;AAAG,UAAA;AAAA,QAAQ;AAEnD,QAAA,MAAM,YAAA,GAAe,IAAIA,MAAA,EAAU;AACnC,QAAA,YAAA,CAAa,EAAA;AAAA,UAAG,OAAA;AAAA,UAAS,MACvB,OAAA,CAAQ;AAAA,YACN,MAAA,EAAQ,YAAA;AAAA,YACR,SAAS,MAAM;AAAE,cAAA,YAAA,CAAa,GAAA,EAAI;AAAG,cAAA,WAAA,CAAY,GAAA,EAAI;AAAA,YAAG;AAAA,WACzD;AAAA,SACH;AACA,QAAA,YAAA,CAAa,EAAA,CAAG,OAAA,EAAS,CAAC,CAAA,KAAM;AAAE,UAAA,WAAA,CAAY,GAAA,EAAI;AAAG,UAAA,MAAA,CAAO,CAAC,CAAA;AAAA,QAAG,CAAC,CAAA;AACjE,QAAA,YAAA,CAAa,OAAA,CAAQ;AAAA,UACnB,IAAA,EAAM,MAAA;AAAA,UACN,UAAU,IAAA,CAAK,QAAA;AAAA,UAAU,UAAU,IAAA,CAAK,QAAA;AAAA,UACxC,YAAY,IAAA,CAAK,UAAA;AAAA,UAAY,YAAY,IAAA,CAAK,UAAA;AAAA,UAC9C,YAAA;AAAA,UACA,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,SAChC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,WAAA,CAAY,GAAG,OAAA,EAAS,CAAC,CAAA,KAAM,MAAA,CAAO,CAAC,CAAC,CAAA;AACxC,IAAA,WAAA,CAAY,OAAA,CAAQ;AAAA,MAClB,MAAM,KAAA,CAAM,QAAA;AAAA,MAAU,MAAM,KAAA,CAAM,IAAA;AAAA,MAAM,UAAU,KAAA,CAAM,QAAA;AAAA,MACxD,UAAU,KAAA,CAAM,QAAA;AAAA,MAAU,YAAY,KAAA,CAAM,UAAA;AAAA,MAAY,YAAY,KAAA,CAAM,UAAA;AAAA,MAC1E,YAAA,EAAc,MAAM,OAAA,IAAW;AAAA,KAChC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AA4BA,IAAI,SAAA,GAA6B,IAAA;AAEjC,SAAS,WAAA,GAAwB;AAC/B,EAAA,IAAI,WAAW,OAAO,SAAA;AACtB,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,WAAA;AAC7B,EAAA,MAAM,WAAA,GAAc,QAAQ,GAAA,CAAI,gBAAA;AAChC,EAAA,MAAM,eAAA,GAAkB,QAAQ,GAAA,CAAI,oBAAA;AACpC,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,WAAA,IAAe,CAAC,eAAA,EAAiB;AACjD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,SAAA,GAAY,IAAI,QAAA,CAAS,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,WAAA,EAAa,EAAE,WAAA,EAAa,eAAA,EAAgB,EAAG,CAAA;AACpG,EAAA,OAAO,SAAA;AACT;AAIA,SAAS,MAAM,IAAA,EAAsB;AACnC,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAChC;AASA,eAAe,MAAA,CACb,MAAA,EACA,MAAA,EACA,OAAA,EACwB;AACxB,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,MAAM,UAAyB,EAAC;AAChC,EAAA,IAAI,iBAAA;AAGJ,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,GAAY,MAAA,GAAY,GAAA;AAElD,EAAA,GAAG;AACD,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,oBAAA,CAAqB;AAAA,MACxD,MAAA,EAAQ,MAAA;AAAA,MACR,QAAQ,MAAA,IAAU,MAAA;AAAA,MAClB,SAAA,EAAW,SAAA;AAAA,MACX,iBAAA,EAAmB,iBAAA;AAAA,MACnB,SAAS,IAAA,CAAK,GAAA,CAAI,KAAM,OAAA,CAAQ,UAAA,GAAa,QAAQ,MAAM;AAAA,KAC5D,CAAC,CAAA;AAEF,IAAA,KAAA,MAAW,EAAA,IAAO,MAAA,CAAO,cAAA,IAAkB,EAAC,EAAsB;AAChE,MAAA,IAAI,EAAA,CAAG,MAAA,EAAQ,OAAA,CAAQ,IAAA,CAAK,EAAE,GAAA,EAAK,EAAA,CAAG,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAG,KAAA,EAAO,EAAA,EAAI,QAAA,EAAU,MAAM,CAAA;AAClF,MAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,UAAA,EAAY;AAAA,IAC5C;AACA,IAAA,KAAA,MAAW,GAAA,IAAQ,MAAA,CAAO,QAAA,IAAY,EAAC,EAAiB;AACtD,MAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,UAAA,EAAY;AAC1C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,GAAA,EAAK,IAAI,GAAA,IAAO,EAAA;AAAA,QAChB,IAAA,EAAM,IAAI,IAAA,IAAQ,CAAA;AAAA,QAClB,OAAO,GAAA,CAAI,YAAA,GAAe,GAAA,CAAI,YAAA,CAAa,aAAY,GAAI,EAAA;AAAA,QAC3D,QAAA,EAAU;AAAA,OACX,CAAA;AAAA,IACH;AACA,IAAA,iBAAA,GAAoB,MAAA,CAAO,WAAA,GAAc,MAAA,CAAO,qBAAA,GAAwB,MAAA;AAAA,EAC1E,CAAA,QAAS,iBAAA,IAAqB,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,UAAA;AAEvD,EAAA,OAAO,OAAA;AACT;AAEA,eAAe,WAAA,CAAY,MAAA,EAAgB,GAAA,EAAa,QAAA,EAAmC;AACzF,EAAA,MAAM,SAAS,WAAA,EAAY;AAE3B,EAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AAClF,EAAA,MAAM,IAAA,GAAO,KAAK,aAAA,IAAiB,CAAA;AACnC,EAAA,IAAI,OAAO,QAAA,EAAU;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,IAAI,CAAA,YAAA,EAAe,QAAQ,CAAA,yHAAA,CAA2H,CAAA;AAAA,EAC7L;AACA,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,gBAAA,CAAiB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AACnF,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,EAAA,IAAI,CAAC,IAAA,EAAM,iBAAA,EAAmB,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAC5E,EAAA,OAAO,KAAK,iBAAA,EAAkB;AAChC;AAEA,eAAe,gBAAA,CACb,MAAA,EACA,GAAA,EACA,KAAA,EACiB;AACjB,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AAClF,EAAA,MAAM,IAAA,GAAO,KAAK,aAAA,IAAiB,CAAA;AACnC,EAAA,IAAI,KAAA,CAAM,MAAA,IAAU,IAAA,IAAQ,IAAA,GAAO,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,OAAA,EAAU,KAAA,CAAM,MAAM,CAAA,6BAAA,EAAgC,IAAI,CAAA,CAAA,CAAG,CAAA;AACnH,EAAA,MAAM,GAAA,GAAM,OAAA;AACZ,EAAA,MAAM,YAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,GAAO,MAAM,MAAM,CAAA;AACjD,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,MAAA,KAAW,MAAA,GAAY,KAAK,GAAA,CAAI,KAAA,CAAM,MAAA,EAAQ,SAAA,EAAW,GAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,WAAW,GAAG,CAAA;AAClH,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,MAAA,GAAS,YAAA,GAAe,CAAA;AAE1C,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,gBAAA,CAAiB;AAAA,IACpD,MAAA,EAAQ,MAAA;AAAA,IACR,GAAA,EAAK,GAAA;AAAA,IACL,KAAA,EAAO,CAAA,MAAA,EAAS,KAAA,CAAM,MAAM,IAAI,GAAG,CAAA;AAAA,GACpC,CAAC,CAAA;AACF,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,EAAA,IAAI,CAAC,IAAA,EAAM,iBAAA,EAAmB,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAC5E,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,iBAAA,EAAkB;AAC1C,EAAA,MAAM,MAAA,GAAS,kBAAkB,KAAA,CAAM,MAAM,IAAI,GAAG,CAAA,IAAA,EAAO,IAAI,CAAA,EAAA,EAAK,YAAY,CAAA,OAAA,CAAA;AAChF,EAAA,OAAO,GAAG,MAAM;AAAA,EAAK,IAAI,CAAA,CAAA;AAC3B;AAEA,eAAe,WAAA,CAAY,MAAA,EAAgB,GAAA,EAAa,IAAA,EAAyB,aAAA,EAAuC;AACtH,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,gBAAA,CAAiB;AAAA,IACrC,MAAA,EAAQ,MAAA;AAAA,IACR,GAAA,EAAK,GAAA;AAAA,IACL,IAAA,EAAM,IAAA;AAAA,IACN,aAAA,EAAe,aAAA;AAAA,IACf,WAAA,EAAa;AAAA,GACd,CAAC,CAAA;AACJ;AAEA,eAAe,cAAA,CAAe,QAAgB,GAAA,EAA4B;AACxE,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,mBAAA,CAAoB,EAAE,QAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AACzE;AAIA,eAAe,cAAA,CAAe,QAAgB,MAAA,EAAiC;AAC7E,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,iBAAA;AACJ,EAAA,GAAG;AACD,IAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,oBAAA,CAAqB;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,MAAA,EAAQ,MAAA;AAAA,MACR,iBAAA,EAAmB,iBAAA;AAAA,MACnB,OAAA,EAAS;AAAA,KACV,CAAC,CAAA;AACF,IAAA,MAAM,IAAA,GAAA,CAAQ,IAAA,CAAK,QAAA,IAAY,IAAI,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,GAAG,EAAE,MAAA,CAAO,CAAC,CAAA,KAAmB,CAAC,CAAC,CAAC,CAAA;AACjF,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACvB,IAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,oBAAA,CAAqB;AAAA,MACzC,MAAA,EAAQ,MAAA;AAAA,MACR,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,CAAA,MAAM,EAAE,GAAA,EAAK,CAAA,EAAE,CAAE,CAAA,EAAG,KAAA,EAAO,IAAA;AAAK,KAC7D,CAAC,CAAA;AACF,IAAA,OAAA,IAAW,IAAA,CAAK,MAAA;AAChB,IAAA,iBAAA,GAAoB,IAAA,CAAK,WAAA,GAAc,IAAA,CAAK,qBAAA,GAAwB,MAAA;AAAA,EACtE,CAAA,QAAS,iBAAA;AACT,EAAA,OAAO,OAAA;AACT;AAIA,IAAM,sBAAA,GAAyB,GAAA,GAAM,IAAA,GAAO,IAAA,GAAO,IAAA;AACnD,IAAM,sBAAA,GAAyB,MAAM,IAAA,GAAO,IAAA;AAE5C,eAAe,oBAAA,CACb,MAAA,EACA,GAAA,EACA,SAAA,EACA,YACA,UAAA,EACe;AACf,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,4BAAA,CAA6B,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AAC/F,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AACxB,EAAA,IAAI,CAAC,QAAA,EAAU,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAE7E,EAAA,MAAM,QAAgD,EAAC;AACvD,EAAA,IAAI;AACF,IAAA,IAAI,UAAA,GAAa,CAAA;AACjB,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,OAAO,SAAS,UAAA,EAAY;AAC1B,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,wBAAwB,UAAU,CAAA;AAIhE,MAAA,MAAM,QAAQ,MAAM,IAAI,OAAA,CAAgB,CAAC,SAAS,MAAA,KAAW;AAC3D,QAAA,MAAM,SAAmB,EAAC;AAC1B,QAAA,MAAM,EAAA,GAAK,iBAAiB,SAAA,EAAW,EAAE,OAAO,MAAA,EAAQ,GAAA,EAAK,GAAA,GAAM,CAAA,EAAG,CAAA;AACtE,QAAA,EAAA,CAAG,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAuB;AAAE,UAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,KAAM,QAAA,GAAW,OAAO,IAAA,CAAK,CAAC,IAAI,CAAC,CAAA;AAAA,QAAG,CAAC,CAAA;AAClG,QAAA,EAAA,CAAG,EAAA,CAAG,KAAA,EAAO,MAAM,OAAA,CAAQ,OAAO,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK,IAAI,UAAA,CAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7E,QAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM,CAAA;AAAA,MACvB,CAAC,CAAA;AACD,MAAA,MAAM,UAAA,GAAa,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB;AAAA,QACzD,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU,QAAA;AAAA,QACV,UAAA,EAAY,UAAA;AAAA,QACZ,IAAA,EAAM,KAAA;AAAA,QACN,eAAe,KAAA,CAAM;AAAA,OACtB,CAAC,CAAA;AACF,MAAA,IAAI,CAAC,WAAW,IAAA,EAAM,MAAM,IAAI,KAAA,CAAM,CAAA,KAAA,EAAQ,UAAU,CAAA,iBAAA,CAAmB,CAAA;AAC3E,MAAA,KAAA,CAAM,KAAK,EAAE,UAAA,EAAY,YAAY,IAAA,EAAM,UAAA,CAAW,MAAM,CAAA;AAC5D,MAAA,QAAA,IAAY,KAAA,CAAM,MAAA;AAClB,MAAA,UAAA,GAAa,QAAQ,CAAA;AACrB,MAAA,MAAA,GAAS,GAAA;AACT,MAAA,UAAA,EAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,8BAAA,CAA+B;AAAA,MACnD,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,QAAA,EAAU,QAAA;AAAA,MACV,eAAA,EAAiB,EAAE,KAAA,EAAO,KAAA;AAAM,KACjC,CAAC,CAAA;AAAA,EACJ,SAAS,CAAA,EAAG;AAEV,IAAA,IAAI;AAAE,MAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,2BAAA,CAA4B,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAAe;AACnI,IAAA,MAAM,CAAA;AAAA,EACR;AACF;AAMA,SAAS,aAAa,IAAA,EAAsB;AAC1C,EAAA,IAAI,UAAA,GAAa,KAAK,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC3D,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA;AAClC,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,SAAS,IAAA,EAAM;AAAE,MAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,IAAK,QAAA,CAAS,QAAA,CAAS,SAAS,CAAC,CAAA,KAAM,EAAA,EAAI,QAAA,CAAS,GAAA,EAAI;AAAA,IAAG,WAC7F,IAAA,KAAS,GAAA,IAAO,SAAS,EAAA,EAAI,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,EAC1D;AACA,EAAA,OAAO,GAAA,GAAM,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAChC;AAEA,IAAM,eAAA,GAAkB,CAAC,OAAA,EAAS,QAAA,EAAU,SAAS,OAAA,EAAS,QAAA,EAAU,SAAS,SAAS,CAAA;AAE1F,SAAS,mBAAmB,IAAA,EAAoB;AAC9C,EAAA,MAAM,IAAA,GAAO,aAAa,IAAI,CAAA;AAC9B,EAAA,KAAA,MAAW,KAAK,eAAA,EAAiB;AAC/B,IAAA,IAAI,IAAA,KAAS,EAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,IAAK,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,EAAG;AACjD,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uCAAA,EAA0C,IAAI,CAAA,CAAE,CAAA;AAAA,IAClE;AAAA,EACF;AACF;AAIA,SAAS,aAAa,OAAA,EAAyB;AAC7C,EAAA,IAAI,EAAA,GAAK,EAAA;AACT,EAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,IAAA,IAAI,CAAA,KAAM,KAAK,EAAA,IAAM,IAAA;AAAA,SAAA,IACZ,CAAA,KAAM,KAAK,EAAA,IAAM,GAAA;AAAA,SAAA,IACjB,kBAAA,CAAmB,IAAA,CAAK,CAAC,CAAA,QAAS,IAAA,GAAO,CAAA;AAAA,SAC7C,EAAA,IAAM,CAAA;AAAA,EACb;AACA,EAAA,OAAO,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,CAAG,CAAA;AAC7B;AAUA,eAAe,WAAA,CACb,IAAA,EACA,OAAA,EACA,KAAA,EACA,OAAA,EACuE;AACvE,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,KAAc,IAAA;AACzC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,EAAA,EAAI,OAAA,EAAS,QAAA,IAAY,CAAC,CAAC,CAAA;AACjE,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,GAAA,EAAQ,OAAA,EAAS,UAAA,IAAc,GAAK,CAAC,CAAA;AAC7E,EAAA,MAAM,UAAU,OAAA,EAAS,OAAA,GAAU,YAAA,CAAa,OAAA,CAAQ,OAAO,CAAA,GAAI,IAAA;AACnE,EAAA,MAAM,QAAA,GAAW,aAAa,OAAO,CAAA;AAErC,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,QAAQ,OAAA,EAAS,CAAA,KAAM,MAAM,gBAAA,CAAiB,IAAA,EAAM,KAAA,EAAO,GAAM,CAAA;AACzE,IAAA,OAAA,GAAU,CAAA;AACV,IAAA,OAAO,MAAM,IAAI,OAAA,CAAsE,CAAC,OAAA,KAAY;AAClG,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAAE,QAAA,OAAA,IAAU;AAAG,QAAA,OAAA,CAAQ,EAAE,SAAS,EAAC,EAAG,WAAW,KAAA,EAAO,KAAA,EAAO,WAAW,CAAA;AAAG,QAAA,OAAA,GAAU,KAAA,CAAA;AAAA,MAAW,GAAG,GAAM,CAAA;AAE1I,MAAA,MAAA,CAAO,IAAA,CAAK,CAAC,GAAA,EAAK,IAAA,KAAS;AACzB,QAAA,IAAI,GAAA,EAAK;AAAE,UAAA,YAAA,CAAa,KAAK,CAAA;AAAG,UAAA,OAAA,IAAU;AAAG,UAAA,OAAA,GAAU,KAAA,CAAA;AAAW,UAAA,OAAA,CAAQ,EAAE,SAAS,EAAC,EAAG,WAAW,KAAA,EAAO,KAAA,EAAO,GAAA,CAAI,OAAA,EAAS,CAAA;AAAG,UAAA;AAAA,QAAQ;AAE1I,QAAA,MAAM,UAAuB,EAAC;AAC9B,QAAA,IAAI,SAAA,GAAY,KAAA;AAChB,QAAA,MAAM,SAAmB,EAAC;AAE1B,QAAA,MAAM,UAAU,CAAC,IAAA,EAAc,UAC7B,IAAI,OAAA,CAAQ,CAAC,UAAA,KAAe;AAC1B,UAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,CAAC,IAAA,EAAM,IAAA,KAAS;AACjC,YAAA,IAAI,IAAA,EAAM;AACR,cAAA,MAAA,CAAO,KAAK,CAAA,cAAA,EAAiB,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AACpD,cAAA,OAAO,UAAA,EAAW;AAAA,YACpB;AACA,YAAA,MAAM,UAAoB,EAAC;AAC3B,YAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,cAAA,IAAI,OAAA,CAAQ,UAAU,UAAA,EAAY;AAAE,gBAAA,SAAA,GAAY,IAAA;AAAM,gBAAA;AAAA,cAAO;AAC7D,cAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,IAAQ,CAAA;AAChC,cAAA,MAAM,KAAA,GAAA,CAAS,OAAO,KAAA,MAAc,KAAA;AACpC,cAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,IAAQ,CAAA;AAChC,cAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,QAAQ,GAAA,GAAO,CAAA;AAC7D,cAAA,MAAM,QAAQ,OAAA,GAAU,IAAI,KAAK,OAAO,CAAA,CAAE,aAAY,GAAI,EAAA;AAC1D,cAAA,MAAM,QAAA,GAAW,IAAA,KAAS,GAAA,GAAM,CAAA,CAAA,EAAI,IAAA,CAAK,QAAQ,CAAA,CAAA,GAAK,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,QAAQ,CAAA,CAAA;AAC9E,cAAA,MAAM,UAAU,CAAC,OAAA,IAAW,OAAA,CAAQ,IAAA,CAAK,KAAK,QAAQ,CAAA;AACtD,cAAA,IAAI,OAAA,EAAS;AACX,gBAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,GAAQ,MAAM,GAAA,EAAK,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,SAAA,GAAY,QAAA,GAAW,IAAA,CAAK,UAAU,CAAA;AAAA,cAC5G;AACA,cAAA,IAAI,SAAS,SAAA,IAAa,KAAA,GAAQ,QAAA,EAAU,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,YACnE;AACA,YAAA,IAAI,SAAA,IAAa,OAAA,CAAQ,MAAA,KAAW,CAAA,SAAU,UAAA,EAAW;AAEzD,YAAA,CAAC,YAAY;AACX,cAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,gBAAA,IAAI,SAAA,EAAW;AACf,gBAAA,MAAM,OAAA,CAAQ,GAAA,EAAK,KAAA,GAAQ,CAAC,CAAA;AAAA,cAC9B;AACA,cAAA,UAAA,EAAW;AAAA,YACb,CAAA,GAAG;AAAA,UACL,CAAC,CAAA;AAAA,QACH,CAAC,CAAA;AAEH,QAAA,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAA,CAAE,IAAA,CAAK,MAAM;AAC9B,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAA,OAAA,IAAU;AAAG,UAAA,OAAA,GAAU,KAAA,CAAA;AACvB,UAAA,OAAA,CAAQ,EAAE,OAAA,EAAS,SAAA,EAAW,KAAA,EAAO,MAAA,CAAO,MAAA,GAAS,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,GAAI,KAAA,CAAA,EAAW,CAAA;AAAA,QACtF,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,SAAS,CAAA,EAAQ;AACf,IAAA,OAAA,IAAU;AACV,IAAA,OAAO,EAAE,SAAS,EAAC,EAAG,WAAW,KAAA,EAAO,KAAA,EAAO,EAAE,OAAA,EAAQ;AAAA,EAC3D;AACF;AAEA,eAAe,QAAA,CACb,IAAA,EACA,QAAA,EACA,KAAA,EACA,OAAA,EACiB;AACjB,EAAA,MAAM,IAAA,GAAO,aAAa,QAAQ,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,EAAS,MAAA,IAAU,CAAC,CAAC,CAAA;AAG3D,EAAA,MAAM,GAAA,GAAM,OAAA;AACZ,EAAA,MAAM,YAAA,GAAe,OAAA,EAAS,MAAA,KAAW,MAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAC,CAAA,GAAI,MAAA;AAE/F,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,QAAQ,OAAA,EAAS,CAAA,KAAM,MAAM,gBAAA,CAAiB,IAAA,EAAM,KAAA,EAAO,GAAM,CAAA;AACzE,IAAA,OAAA,GAAU,CAAA;AACV,IAAA,OAAO,MAAM,IAAI,OAAA,CAAgB,CAAC,OAAA,KAAY;AAC5C,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAAE,QAAA,OAAA,IAAU;AAAG,QAAA,OAAA,CAAQ,gBAAgB,CAAA;AAAG,QAAA,OAAA,GAAU,KAAA,CAAA;AAAA,MAAW,GAAG,GAAM,CAAA;AACvG,MAAA,MAAA,CAAO,IAAA,CAAK,CAAC,GAAA,EAAK,IAAA,KAAS;AACzB,QAAA,IAAI,GAAA,EAAK;AAAE,UAAA,YAAA,CAAa,KAAK,CAAA;AAAG,UAAA,OAAA,IAAU;AAAG,UAAA,OAAA,GAAU,KAAA,CAAA;AAAW,UAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAG,UAAA;AAAA,QAAQ;AAC5G,QAAA,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,CAAC,IAAA,EAAM,KAAA,KAAU;AAC/B,UAAA,IAAI,IAAA,EAAM;AAAE,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAAW,YAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AAAG,YAAA;AAAA,UAAQ;AAC9G,UAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,IAAQ,CAAA;AAC5B,UAAA,IAAI,MAAA,IAAU,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG;AAChC,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,YAAA,OAAA,CAAQ,CAAA,cAAA,EAAiB,MAAM,CAAA,2BAAA,EAA8B,KAAK,CAAA,CAAA,CAAG,CAAA;AACrE,YAAA;AAAA,UACF;AACA,UAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,MAAM,CAAA;AAI5C,UAAA,MAAM,YAAA,GAAe,YAAA,KAAiB,KAAA,CAAA,GAClC,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,SAAA,EAAW,GAAG,CAAA,GACrC,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,GAAG,CAAA;AAC3B,UAAA,MAAM,kBAAA,GAAqB,OAAA,KAAY,KAAA,CAAA,IAAc,MAAA,KAAW,KAAK,YAAA,KAAiB,KAAA,CAAA;AACtF,UAAA,IAAI,kBAAA,IAAsB,QAAQ,GAAA,EAAK;AACrC,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,YAAA,OAAA,CAAQ,CAAA,uBAAA,EAA0B,KAAK,CAAA,YAAA,EAAe,GAAG,CAAA,2CAAA,CAA6C,CAAA;AACtG,YAAA;AAAA,UACF;AACA,UAAA,MAAM,SAAmB,EAAC;AAE1B,UAAA,MAAM,EAAA,GAAK,IAAA,CAAK,gBAAA,CAAiB,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,MAAA,GAAS,YAAA,GAAe,CAAA,EAAG,CAAA;AACxF,UAAA,EAAA,CAAG,GAAG,MAAA,EAAQ,CAAC,OAAe,MAAA,CAAO,IAAA,CAAK,EAAE,CAAC,CAAA;AAC7C,UAAA,EAAA,CAAG,EAAA,CAAG,OAAO,MAAM;AACjB,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,YAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAA,EAAA,KAAM,IAAI,UAAA,CAAW,EAAE,CAAC,CAAC,CAAA,CAAE,SAAS,OAAO,CAAA;AAGjF,YAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,cAAA,MAAM,MAAA,GAAS,CAAA,eAAA,EAAkB,MAAM,CAAA,CAAA,EAAI,MAAA,GAAS,eAAe,CAAC,CAAA,IAAA,EAAO,KAAK,CAAA,EAAA,EAAK,YAAY,CAAA,OAAA,CAAA;AACjG,cAAA,OAAA,CAAQ,GAAG,MAAM;AAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AAAA,YAC9B,CAAA,MAAO;AACL,cAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,YACd;AAAA,UACF,CAAC,CAAA;AACD,UAAA,EAAA,CAAG,EAAA,CAAG,OAAA,EAAS,CAAC,CAAA,KAAa;AAAE,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAAW,YAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA;AAAA,UAAG,CAAC,CAAA;AAAA,QACzH,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,SAAS,CAAA,EAAQ;AACf,IAAA,OAAA,IAAU;AACV,IAAA,OAAO,CAAA,OAAA,EAAU,EAAE,OAAO,CAAA,CAAA;AAAA,EAC5B;AACF;AAMA,IAAM,wBAAA,GAA2B,EAAA;AACjC,IAAM,uBAAA,GAA0B,KAAA;AAIhC,IAAM,oBAAA,GAAuB,IAAA;AAE7B,IAAM,sBAAA,GAAyB,GAAA;AAC/B,IAAM,uBAAA,GAA0B,KAAK,IAAA,GAAO,IAAA;AAM5C,SAAS,YAAY,KAAA,EAAuB;AAC1C,EAAA,IAAI,KAAA,GAAQ,IAAA,EAAM,OAAO,CAAA,EAAG,KAAK,CAAA,EAAA,CAAA;AACjC,EAAA,IAAI,KAAA,GAAQ,OAAO,IAAA,EAAM,OAAO,IAAI,KAAA,GAAQ,IAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AAC5D,EAAA,IAAI,KAAA,GAAQ,IAAA,GAAO,IAAA,GAAO,IAAA,EAAM,OAAO,CAAA,EAAA,CAAI,KAAA,IAAS,IAAA,GAAO,IAAA,CAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AAC5E,EAAA,OAAO,IAAI,KAAA,IAAS,IAAA,GAAO,OAAO,IAAA,CAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AACrD;AAEA,eAAe,SAAA,CACb,IAAA,EACA,QAAA,EACA,KAAA,EACA,OACA,IAAA,EACiB;AACjB,EAAA,MAAM,IAAA,GAAO,aAAa,QAAQ,CAAA;AAClC,EAAA,kBAAA,CAAmB,IAAI,CAAA;AAIvB,EAAA,MAAM,WAAW,IAAA,EAAM,QAAA,KAAa,MAAA,GAAa,IAAA,CAAK,WAAW,IAAA,GAAU,GAAA;AAG3E,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,aAAA,GAAgB,CAAA;AAEpB,EAAA,IAAI,SAAA,IAAa,KAAA,IAAS,OAAO,KAAA,CAAM,YAAY,QAAA,EAAU;AAC3D,IAAA,IAAA,GAAO,SAAA;AACP,IAAA,YAAA,GAAe,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,OAAA,EAAS,OAAO,CAAA;AACjD,IAAA,aAAA,GAAgB,YAAA,CAAa,MAAA;AAAA,EAC/B,WAAW,YAAA,IAAgB,KAAA,IAAS,OAAO,KAAA,CAAM,eAAe,QAAA,EAAU;AACxE,IAAA,IAAA,GAAO,YAAA;AACP,IAAA,SAAA,GAAY,KAAA,CAAM,UAAA;AAClB,IAAA,IAAI,CAAC,UAAA,CAAW,SAAS,CAAA,EAAG,OAAO,+CAA+C,SAAS,CAAA,CAAA;AAC3F,IAAA,IAAI,CAACD,UAAAA,CAAW,SAAS,CAAA,EAAG,OAAO,qCAAqC,SAAS,CAAA,CAAA;AACjF,IAAA,MAAM,EAAA,GAAK,SAAS,SAAS,CAAA;AAC7B,IAAA,IAAI,CAAC,EAAA,CAAG,MAAA,EAAO,EAAG,OAAO,4CAA4C,SAAS,CAAA,CAAA;AAC9E,IAAA,aAAA,GAAgB,EAAA,CAAG,IAAA;AAAA,EACrB,CAAA,MAAO;AACL,IAAA,OAAO,iGAAA;AAAA,EACT;AAMA,EAAA,MAAM,WAAW,IAAA,KAAS,SAAA;AAC1B,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE,GAAI,MAAM,gBAAA,CAAiB,IAAA,EAAM,KAAA,EAAO,GAAA,EAAQ,EAAE,QAAA,EAAU,CAAA;AACvF,IAAA,OAAA,GAAU,CAAA;AAEV,IAAA,OAAO,MAAM,IAAI,OAAA,CAAgB,CAAC,OAAA,KAAY;AAC5C,MAAA,IAAI,QAAA,GAAW,KAAA;AACf,MAAA,IAAI,YAAA,GAAe,CAAA;AAEnB,MAAA,MAAM,MAAA,GAAS,CAAC,GAAA,KAAgB;AAC9B,QAAA,IAAI,QAAA,EAAU;AACd,QAAA,QAAA,GAAW,IAAA;AACX,QAAA,QAAA,EAAU,MAAA,EAAO;AACjB,QAAA,SAAA,IAAa,aAAa,SAAS,CAAA;AACnC,QAAA,OAAA,IAAU;AACV,QAAA,OAAA,GAAU,KAAA,CAAA;AACV,QAAA,OAAA,CAAQ,GAAG,CAAA;AAAA,MACb,CAAA;AAIA,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI,SAAA;AAEJ,MAAA,IAAI,SAAS,YAAA,EAAc;AACzB,QAAA,MAAM,cAAc,MAAM;AACxB,UAAA,IAAI,KAAA,GAAwB,UAAA;AAAA,YAC1B,MAAM,MAAA,CAAO,CAAA,0CAAA,EAA6C,oBAAA,GAAuB,GAAI,CAAA,SAAA,EAAY,WAAA,CAAY,YAAY,CAAC,CAAA,IAAA,EAAO,WAAA,CAAY,aAAa,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,YAC9J;AAAA,WACF;AACA,UAAA,OAAO;AAAA,YACL,OAAO,MAAM;AAAE,cAAA,YAAA,CAAa,KAAK,CAAA;AAAG,cAAA,KAAA,GAAQ,UAAA;AAAA,gBAC1C,MAAM,MAAA,CAAO,CAAA,0CAAA,EAA6C,oBAAA,GAAuB,GAAI,CAAA,SAAA,EAAY,WAAA,CAAY,YAAY,CAAC,CAAA,IAAA,EAAO,WAAA,CAAY,aAAa,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,gBAC9J;AAAA,eACF;AAAA,YAAG,CAAA;AAAA,YACH,MAAA,EAAQ,MAAM,YAAA,CAAa,KAAK;AAAA,WAClC;AAAA,QACF,CAAA;AACA,QAAA,QAAA,GAAW,WAAA,EAAY;AAAA,MACzB,CAAA,MAAO;AACL,QAAA,SAAA,GAAY,UAAA;AAAA,UACV,MAAM,MAAA,CAAO,CAAA,qBAAA,EAAwB,sBAAA,GAAyB,GAAI,CAAA,CAAA,CAAG,CAAA;AAAA,UACrE;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAA,CAAO,IAAA,CAAK,CAAC,GAAA,EAAK,IAAA,KAAS;AACzB,QAAA,IAAI,KAAK,OAAO,MAAA,CAAO,CAAA,OAAA,EAAU,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAM9C,QAAA,MAAM,UAAA,GAAa,CAAC,IAAA,KAAmC;AACrD,UAAA,IAAI,IAAA,EAAM,OAAA,KAAY,KAAA,CAAA,EAAW,OAAO,KAAK,EAAE,CAAA;AAC/C,UAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,UAAU,GAAI,CAAA;AAC3C,UAAA,IAAA,CAAK,OAAA,CAAQ,MAAM,EAAE,KAAA,EAAO,MAAM,KAAA,EAAO,IAAA,EAAK,EAAG,CAAC,OAAA,KAAY;AAC5D,YAAA,IAAA,CAAK,OAAA,GAAU,CAAA,oBAAA,EAAuB,OAAA,CAAQ,OAAO,CAAA,CAAA,CAAA,GAAM,CAAA,QAAA,EAAW,IAAI,IAAA,CAAK,IAAA,CAAK,OAAQ,CAAA,CAAE,WAAA,EAAa,CAAA,CAAA,CAAG,CAAA;AAAA,UAChH,CAAC,CAAA;AAAA,QACH,CAAA;AAEA,QAAA,IAAI,SAAS,SAAA,EAAW;AACtB,UAAA,MAAM,KAAK,IAAA,CAAK,iBAAA,CAAkB,MAAM,EAAE,IAAA,EAAM,UAAU,CAAA;AAC1D,UAAA,EAAA,CAAG,EAAA,CAAG,SAAS,CAAC,CAAA,KAAa,OAAO,CAAA,OAAA,EAAU,CAAA,CAAE,OAAO,CAAA,CAAE,CAAC,CAAA;AAC1D,UAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM;AACnB,YAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC7B,YAAA,UAAA,CAAW,CAAC,MAAA,KAAW,MAAA,CAAO,CAAA,QAAA,EAAW,aAAa,aAAa,IAAI,CAAA,IAAA,EAAO,OAAO,CAAA,WAAA,EAAc,SAAS,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA,EAAI,MAAM,EAAE,CAAC,CAAA;AAAA,UACtI,CAAC,CAAA;AACD,UAAA,EAAA,CAAG,IAAI,YAAa,CAAA;AACpB,UAAA;AAAA,QACF;AAKA,QAAA,IAAI,eAAA,GAAkB,uBAAA;AACtB,QAAA,IAAA,CAAK,OAAA;AAAA,UACH,SAAA;AAAA,UACA,IAAA;AAAA,UACA;AAAA,YACE,WAAA,EAAa,wBAAA;AAAA,YACb,SAAA,EAAW,uBAAA;AAAA,YACX,IAAA,EAAM,QAAA;AAAA,YACN,QAAA,EAAU,aAAA;AAAA,YACV,IAAA,EAAM,CAAC,WAAA,KAAwB;AAC7B,cAAA,YAAA,GAAe,WAAA;AACf,cAAA,QAAA,EAAU,KAAA,EAAM;AAChB,cAAA,IAAI,eAAe,eAAA,EAAiB;AAClC,gBAAA,OAAA,CAAQ,KAAA;AAAA,kBACN,CAAA,aAAA,EAAgB,YAAY,WAAW,CAAC,MAAM,WAAA,CAAY,aAAa,CAAC,CAAA,QAAA,EAAM,IAAI,CAAA;AAAA,iBACpF;AACA,gBAAA,eAAA,IAAmB,uBAAA;AAAA,cACrB;AAAA,YACF;AAAA,WACF;AAAA,UACA,CAAC,KAAA,KAAU;AACT,YAAA,IAAI,OAAO,OAAO,MAAA,CAAO,CAAA,OAAA,EAAU,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAClD,YAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC7B,YAAA,MAAM,IAAA,GAAO,iBAAiB,IAAA,GAAO,IAAA,CAAA,GAAQ,KAAK,GAAA,CAAI,IAAA,EAAO,UAAU,GAAI,CAAA;AAC3E,YAAA,UAAA,CAAW,CAAC,MAAA,KAAW,MAAA;AAAA,cACrB,CAAA,SAAA,EAAY,WAAA,CAAY,aAAa,CAAC,CAAA,MAAA,EAAS,SAAS,CAAA,IAAA,EAAO,IAAI,CAAA,IAAA,EAAA,CAC5D,OAAA,GAAU,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,cAAA,EAAiB,QAAA,CAAS,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA,EAAI,MAAM,CAAA;AAAA,aACtG,CAAA;AAAA,UACH;AAAA,SACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,SAAS,CAAA,EAAY;AACnB,IAAA,OAAA,IAAU;AACV,IAAA,OAAO,UAAU,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA;AAAA,EAC7D;AACF;AAEA,eAAe,UAAA,CACb,IAAA,EACA,QAAA,EACA,KAAA,EACA,OAAA,EACiB;AACjB,EAAA,MAAM,IAAA,GAAO,aAAa,QAAQ,CAAA;AAClC,EAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,KAAc,IAAA;AACzC,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,QAAQ,OAAA,EAAS,CAAA,KAAM,MAAM,gBAAA,CAAiB,IAAA,EAAM,KAAA,EAAO,GAAM,CAAA;AACzE,IAAA,OAAA,GAAU,CAAA;AACV,IAAA,OAAO,MAAM,IAAI,OAAA,CAAgB,CAAC,OAAA,KAAY;AAC5C,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAAE,QAAA,OAAA,IAAU;AAAG,QAAA,OAAA,CAAQ,gBAAgB,CAAA;AAAG,QAAA,OAAA,GAAU,KAAA,CAAA;AAAA,MAAW,GAAG,GAAM,CAAA;AACvG,MAAA,MAAA,CAAO,IAAA,CAAK,CAAC,GAAA,EAAK,IAAA,KAAS;AACzB,QAAA,IAAI,GAAA,EAAK;AAAE,UAAA,YAAA,CAAa,KAAK,CAAA;AAAG,UAAA,OAAA,IAAU;AAAG,UAAA,OAAA,GAAU,KAAA,CAAA;AAAW,UAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAG,UAAA;AAAA,QAAQ;AAK5G,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,MAAM,UAAA,GAAa,OAAO,MAAA,KAA6D;AACrF,YAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,WAAA,KAAgB;AAClC,cAAA,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAC,OAAA,EAAS,KAAA,KAAU;AACpC,gBAAA,IAAI,OAAA,SAAgB,WAAA,CAAY,EAAE,OAAO,CAAA,EAAG,IAAA,EAAM,GAAG,CAAA;AACrD,gBAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,CAAA;AAC3B,gBAAA,MAAM,KAAA,GAAA,CAAS,OAAO,KAAA,MAAc,KAAA;AACpC,gBAAA,IAAI,CAAC,KAAA,EAAO;AACV,kBAAA,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,MAAM,WAAA,CAAY,EAAE,OAAO,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,CAAC,CAAA;AAC5D,kBAAA;AAAA,gBACF;AACA,gBAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,OAAO,KAAA,EAAO,IAAA,KAAS;AAC1C,kBAAA,IAAI,KAAA,SAAc,WAAA,CAAY,EAAE,OAAO,CAAA,EAAG,IAAA,EAAM,GAAG,CAAA;AACnD,kBAAA,IAAI,KAAA,GAAQ,CAAA;AAAG,kBAAA,IAAI,IAAA,GAAO,CAAA;AAC1B,kBAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,oBAAA,MAAM,KAAA,GAAQ,MAAA,KAAW,GAAA,GAAM,CAAA,CAAA,EAAI,IAAA,CAAK,QAAQ,CAAA,CAAA,GAAK,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,QAAQ,CAAA,CAAA;AAC/E,oBAAA,MAAM,CAAA,GAAI,MAAM,UAAA,CAAW,KAAK,CAAA;AAChC,oBAAA,KAAA,IAAS,CAAA,CAAE,KAAA;AAAO,oBAAA,IAAA,IAAQ,CAAA,CAAE,IAAA;AAAA,kBAC9B;AACA,kBAAA,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,MAAM,WAAA,CAAY,EAAE,OAAO,IAAA,EAAM,IAAA,GAAO,CAAA,EAAG,CAAC,CAAA;AAAA,gBACjE,CAAC,CAAA;AAAA,cACH,CAAC,CAAA;AAAA,YACH,CAAC,CAAA;AAAA,UACH,CAAA;AACA,UAAA,UAAA,CAAW,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,EAAE,KAAA,EAAO,MAAK,KAAM;AACzC,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,YAAA,OAAA,CAAQ,WAAW,IAAI,CAAA,cAAA,EAAiB,KAAK,CAAA,QAAA,EAAW,IAAI,CAAA,aAAA,CAAe,CAAA;AAAA,UAC7E,CAAC,CAAA;AACD,UAAA;AAAA,QACF;AAEA,QAAA,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,CAAC,SAAA,KAAc;AAC/B,UAAA,IAAI,SAAA,EAAW;AACb,YAAA,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAC,QAAA,KAAa;AAC7B,cAAA,YAAA,CAAa,KAAK,CAAA;AAAG,cAAA,OAAA,IAAU;AAAG,cAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,cAAA,OAAA,CAAQ,WAAW,CAAA,OAAA,EAAU,SAAA,CAAU,OAAO,CAAA,CAAA,GAAK,CAAA,kBAAA,EAAqB,IAAI,CAAA,CAAE,CAAA;AAAA,YAChF,CAAC,CAAA;AAAA,UACH,CAAA,MAAO;AACL,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,YAAA,OAAA,CAAQ,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAE,CAAA;AAAA,UAChC;AAAA,QACF,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,SAAS,CAAA,EAAQ;AACf,IAAA,OAAA,IAAU;AACV,IAAA,OAAO,CAAA,OAAA,EAAU,EAAE,OAAO,CAAA,CAAA;AAAA,EAC5B;AACF;AAMA,IAAM,gBAAA,GAAmB;AAAA,EACvB,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,eAAA;AAAA,EAC1C,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,QAAA;AAAA,EAC9B,YAAA;AAAA,EAAc,iBAAA;AAAA,EAAmB;AACnC,CAAA;AAEA,SAAS,kBAAkB,OAAA,EAAuB;AAChD,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,WAAA,EAAY,CAAE,IAAA,EAAK;AACzC,EAAA,KAAA,MAAW,WAAW,gBAAA,EAAkB;AACtC,IAAA,IAAI,KAAA,CAAM,QAAA,CAAS,OAAO,CAAA,EAAG;AAC3B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,IACnE;AAAA,EACF;AACF;AAoBA,eAAe,qBAAA,CAAsB,MAA4B,KAAA,EAAwD;AACvH,EAAA,MAAM,MAAA,GAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAmCf,IAAA,EAAK;AAEL,EAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,QAAQ,KAAK,CAAA;AAChD,EAAA,MAAM,QAAyB,EAAC;AAEhC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,EAAG;AAC5C,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAK,EAAG;AAClB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,IAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AAEtB,IAAA,MAAM,CAAC,MAAM,QAAA,EAAU,QAAA,EAAU,MAAM,QAAA,EAAU,IAAA,EAAM,IAAI,CAAA,GAAI,KAAA;AAC/D,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAQ,CAAC,IAAA,IAAQ,CAAC,QAAA,EAAU;AAE9C,IAAA,MAAM,WAAmC,EAAE,EAAA,EAAI,aAAa,EAAA,EAAI,YAAA,EAAc,KAAK,cAAA,EAAe;AAElG,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,OAAA,EAAS,QAAA,CAAS,IAAI,CAAA,IAAK,IAAA;AAAA,MAC3B,QAAA,EAAU,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAAA,MACpC,QAAA;AAAA,MACA,IAAA;AAAA,MACA,UAAU,QAAA,IAAY,EAAA;AAAA,MACtB,MAAM,IAAA,IAAQ,WAAA;AAAA,MACd,IAAA,EAAM,QAAA,CAAS,IAAA,IAAQ,MAAA,EAAQ,EAAE;AAAA,KAClC,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,iBAAiB,KAAA,EAAuB;AAC/C,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AACpC;AAEA,IAAM,oBAAA,GAAuB;AAAA,EAC3B,sBAAA;AAAA,EACA,mBAAA;AAAA,EACA,mBAAA;AAAA,EACA,eAAA;AAAA,EACA,iCAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,cAAc,KAAA,EAAqB;AAC1C,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,EAAA,KAAA,MAAW,WAAW,oBAAA,EAAsB;AAC1C,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,EAAG;AACzB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iCAAA,EAAoC,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AAAA,IACtE;AAAA,EACF;AACF;AAMA,SAAS,qBAAA,CAAsB,UAAkB,KAAA,EAAuB;AACtE,EAAA,MAAM,WAAW,gBAAA,CAAiB,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA;AAC7D,EAAA,MAAM,SAAA,GAAY,iBAAiB,KAAK,CAAA;AAExC,EAAA,OAAO;AAAA,MAAA,EACD,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yFAAA,EAqC2E,SAAS,CAAA;AAAA,CAAA,CAClG,IAAA,EAAK;AACP;AAMA,eAAe,aAAA,CAAc,IAAA,EAA4B,QAAA,EAAkB,KAAA,EAAe,KAAA,EAA+C;AACvI,EAAA,MAAM,GAAA,GAAM,qBAAA,CAAsB,QAAA,EAAU,KAAK,CAAA;AACjD,EAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC7C,EAAA,MAAM,MAAA,GAAA,CAAU,MAAA,CAAO,MAAA,IAAU,EAAA,EAAI,IAAA,EAAK;AAC1C,EAAA,IAAI,MAAA,CAAO,UAAA,CAAW,iCAAiC,CAAA,EAAG;AACxD,IAAA,MAAM,IAAI,MAAM,MAAM,CAAA;AAAA,EACxB;AACA,EAAA,IAAI,MAAA,CAAO,QAAA,KAAa,CAAA,IAAK,CAAC,MAAA,EAAQ;AACpC,IAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,MAAA,IAAU,sBAAsB,CAAA;AAAA,EACzD;AACA,EAAA,OAAO,MAAA;AACT;AAMA,IAAM,iBAAA,GAAoB,0BAAA;AAQ1B,SAAS,qBAAA,GAAgC;AACvC,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAA,MAAM,IAAI,MAAM,sFAAsF,CAAA;AAAA,EACxG;AACA,EAAA,OAAO,cAAA;AACT;AAEA,eAAe,aAAA,CAAiB,IAAA,EAAc,OAAA,GAAuB,EAAC,EAAoC;AACxG,EAAA,MAAM,MAAM,qBAAA,EAAsB;AAElC,EAAA,MAAM,MAAM,MAAM,KAAA,CAAM,GAAG,iBAAiB,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,IACrD,GAAG,OAAA;AAAA,IACH,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,GAAA;AAAA,MACX,QAAA,EAAU,kBAAA;AAAA,MACV,cAAA,EAAgB,kBAAA;AAAA,MAChB,YAAA,EAAc,wBAAA;AAAA,MACd,GAAK,OAAA,CAAQ,OAAA,IAAsC;AAAC;AACtD,GACD,CAAA;AAED,EAAA,MAAM,IAAA,GAAgB,MAAM,GAAA,CAAI,IAAA,EAAK;AACrC,EAAA,MAAM,IAAA,GAAO,IAAA;AAEb,EAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,IAAA,MAAM,IAAI,KAAA,CAAM,IAAA,EAAM,sBAAsB,CAAA,qBAAA,EAAwB,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAAA,EAClF;AAEA,EAAA,OAAO,IAAA;AACT;AAMA,IAAM,KAAA,GAAQ;AAAA,EACZ;AAAA,IACE,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,EACE,qPAAA;AAAA,IAGF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,YAAA,EAAc,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,sGAAA,EAAuG;AAAA,QACrJ,gBAAA,EAAkB,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,oEAAA,EAAqE;AAAA,QACtH,cAAA,EAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4FAAA;AAA6F;AAC9I;AACF,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,o7BAAA;AAAA,IAOF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4DAAA,EAA6D;AAAA,QACtG,SAAA,EAAW,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS,EAAG,WAAA,EAAa,oGAAA,EAAqG;AAAA,QACzK,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uEAAA,EAAwE;AAAA,QAChH,IAAA,EAAM,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS,EAAG,WAAA,EAAa,2FAAA,EAA4F;AAAA,QAC3J,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,kDAAA,EAAmD;AAAA,QACzF,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+EAAA,EAAgF;AAAA,QACpH,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,MAAA,EAAQ,MAAA,EAAQ,YAAY,CAAA,EAAG,WAAA,EAAa,CAAA,oEAAA,CAAA,EAAwE;AAAA,QACpJ,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yEAAA,EAA0E;AAAA,QACtH,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qDAAA;AAAsD,OAChG;AAAA,MACA,QAAA,EAAU,CAAC,SAAS;AAAA;AACtB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACE,wvBAAA;AAAA,IAIF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yDAAA,EAA0D;AAAA,QACnG,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8DAAA,EAA+D;AAAA,QACtG,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qDAAA,EAAsD;AAAA,QAC3F,SAAA,EAAW,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,+DAAA,EAAgE;AAAA,QAC3G,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yEAAA,EAA0E;AAAA,QACnH,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+DAAA,EAAgE;AAAA,QACxG,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sDAAA,EAAuD;AAAA,QAClG,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,MAAA,EAAQ,MAAA,EAAQ,OAAO,CAAA,EAAG,WAAA,EAAa,kFAAA,EAAmF;AAAA,QAC3J,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,8DAAA,EAA+D;AAAA,QACxG,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,4FAAA;AAA6F;AACxI;AACF,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACE,weAAA;AAAA,IAIF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yDAAA,EAA0D;AAAA,QACnG,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8DAAA,EAA+D;AAAA,QACtG,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,oCAAA,EAAqC;AAAA,QAC1E,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2EAAA,EAA4E;AAAA,QACnH,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4FAAA;AAA6F,OACtI;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA;AACnB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EACE,21BAAA;AAAA,IAOF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yDAAA,EAA0D;AAAA,QACnG,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8DAAA,EAA+D;AAAA,QACtG,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2CAAA,EAA4C;AAAA,QACjF,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gEAAA,EAAiE;AAAA,QACzG,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0GAAA,EAA2G;AAAA,QACtJ,IAAA,EAAM,EAAE,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,QAAA,EAAS,EAAG,EAAE,IAAA,EAAM,QAAA,EAAU,CAAA,EAAG,aAAa,+GAAA,EAAgH;AAAA,QACtL,KAAA,EAAO,EAAE,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,QAAA,EAAS,EAAG,EAAE,IAAA,EAAM,QAAA,EAAU,CAAA,EAAG,aAAa,mFAAA;AAAoF,OAC7J;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA;AACnB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,wnBAAA;AAAA,IAGF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yDAAA,EAA0D;AAAA,QACnG,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8DAAA,EAA+D;AAAA,QACtG,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,mEAAA,EAAoE;AAAA,QACzG,SAAA,EAAW,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,mFAAA;AAAoF,OACjI;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA;AACnB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,gWAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,OAAA,EAAS,MAAM,CAAA,EAAG,WAAA,EAAa,6FAAA,EAA8F;AAAA,QAC9J,WAAA,EAAa,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,gEAAA,EAAiE;AAAA,QAC9G,YAAY,EAAE,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,UAAS,EAAG,EAAE,MAAM,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,IAAY,CAAA,EAAG,aAAa,iIAAA,EAAkI;AAAA,QACxO,cAAA,EAAgB,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,2EAAA;AAA4E,OAC9H;AAAA,MACA,QAAA,EAAU,CAAC,UAAU;AAAA;AACvB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,oZAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,eAAe,EAAE,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,UAAS,EAAG,EAAE,MAAM,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,IAAY,CAAA,EAAG,aAAa,2GAAA,EAA4G;AAAA,QACrN,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yEAAA,EAA0E;AAAA,QAC/G,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6CAAA,EAA8C;AAAA,QACpF,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6EAAA,EAA8E;AAAA,QACpH,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gGAAA,EAAiG;AAAA,QACtI,aAAA,EAAe,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6IAAA;AAA8I,OAC9L;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,eAAe;AAAA;AACxC,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,iYAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,SAAA,EAAW,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sBAAA,EAAuB;AAAA,QACjE,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,kEAAA,EAAmE;AAAA,QAC3G,IAAA,EAAM,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS,EAAG,WAAA,EAAa,oCAAA,EAAqC;AAAA,QACpG,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qDAAA,EAAsD;AAAA,QAC5F,WAAA,EAAa,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,kIAAA,EAA8H;AAAA,QAC3K,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8CAAA,EAA+C;AAAA,QACvF,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2CAAA,EAA4C;AAAA,QACjF,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0CAAA;AAA2C,OACrF;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,WAAA,EAAa,SAAS;AAAA;AAC/C,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,gBAAA;AAAA,IACN,WAAA,EACE,oLAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+DAAA,EAAgE;AAAA,QAC5G,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,MAAM,CAAC,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,QAAQ,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA,EAAG,aAAa,iBAAA,EAAkB;AAAA,QACzH,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,iGAAA,EAAkG;AAAA,QAC1I,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4CAAA,EAA6C;AAAA,QAClF,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2EAAA;AAAuE,OACjH;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,aAAA,EAAe,QAAQ;AAAA;AAChD,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EAAa,oMAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA;AAAyB,OACpE;AAAA,MACA,QAAA,EAAU,CAAC,UAAU;AAAA;AACvB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EAAa,iKAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4CAAA;AAA6C,OACxF;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,UAAU;AAAA;AACnC,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EAAa,kIAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4CAAA,EAA6C;AAAA,QACtF,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,YAAA;AAAa,OACrD;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,UAAA,EAAY,OAAO;AAAA;AAC5C,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,sJAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA,EAAyB;AAAA,QAClE,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4CAAA,EAA6C;AAAA,QACtF,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sBAAA;AAAuB,OAC/D;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,UAAA,EAAY,OAAO;AAAA;AAC5C,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,8EAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,cAAA,EAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qIAAA;AAAsI;AACvL;AACF,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,yEAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8CAAA,EAA+C;AAAA,QACvF,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,YAAA,EAAc,SAAA,EAAW,aAAA,EAAe,OAAO,CAAA,EAAG,WAAA,EAAa,kBAAA,EAAmB;AAAA,QACxH,cAAA,EAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0LAAA;AAA2L,OAC5O;AAAA,MACA,QAAA,EAAU,CAAC,SAAA,EAAW,aAAa;AAAA;AACrC,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EAAa,6EAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,8CAAA,EAA+C;AAAA,QACvF,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,YAAA,EAAc,SAAA,EAAW,aAAA,EAAe,OAAO,CAAA,EAAG,WAAA,EAAa,kBAAA,EAAmB;AAAA,QACxH,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACzE,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sBAAA,EAAuB;AAAA,QACnE,cAAA,EAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0LAAA;AAA2L,OAC5O;AAAA,MACA,QAAA,EAAU,CAAC,SAAA,EAAW,aAAA,EAAe,SAAS;AAAA;AAChD,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EAAa,4OAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,wBAAA;AAAyB,OACpE;AAAA,MACA,QAAA,EAAU,CAAC,UAAU;AAAA;AACvB,GACF;AAAA;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EAAa,8HAAA;AAAA,IACb,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAmB,YAAY,EAAC,EAAG,QAAA,EAAU,EAAC;AAAE,GACvE;AAAA,EACA;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,wHAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA;AAAiC,OAC1E;AAAA,MACA,QAAA,EAAU,CAAC,QAAQ;AAAA;AACrB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EAAa,yFAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACxE,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6DAAA,EAA8D;AAAA,QACnG,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,mCAAA,EAAoC;AAAA,QACzE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0CAAA,EAA2C;AAAA,QACjF,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uCAAA;AAAwC,OAC9E;AAAA,MACA,QAAA,EAAU,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ,OAAO;AAAA;AAC9C,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EAAa,yHAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACxE,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6DAAA,EAA8D;AAAA,QACnG,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,aAAA,EAAc;AAAA,QACnD,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uCAAA,EAAwC;AAAA,QACjF,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0BAAA,EAA2B;AAAA,QACpE,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6BAAA;AAA8B,OACpE;AAAA,MACA,UAAU,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAA,EAAQ,YAAY,UAAU;AAAA;AAC7D,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EAAa,0HAAA;AAAA,IACb,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,QACxE,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uBAAA,EAAwB;AAAA,QAC7D,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,uBAAA,EAAwB;AAAA,QAC7D,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6CAAA;AAA8C,OACtF;AAAA,MACA,QAAA,EAAU,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ,OAAO;AAAA;AAC9C,GACF;AAAA;AAAA,EAEA,GAAG,aAAA;AAAA;AAAA,EAEH,GAAG;AACL,CAAA;AAMA,IAAM,WAAA,GAAc,OAAA;AAEpB,eAAe,eAAA,GAAkB;AAC/B,EAAA,IAAI,CAAC,WAAA,EAAa,OAAO,EAAE,OAAO,KAAA,EAAM;AAExC,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,MAAA,CAAO,CAAC,IAAA,KAAS;AACxC,IAAA,MAAM,cAAA,GAAiB,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA;AAChD,IAAA,IAAI,CAAC,gBAAgB,OAAO,IAAA;AAC5B,IAAA,OAAO,WAAA,CAAa,WAAA,CAAY,OAAA,CAAQ,cAAc,CAAA,KAAM,IAAA;AAAA,EAC9D,CAAC,CAAA;AAED,EAAA,OAAO,EAAE,OAAO,UAAA,EAAW;AAC7B;AAEA,eAAe,eAAe,OAAA,EAA4E;AACxG,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,0BAAA,EAA4B,CAAA,EAAE;AAAA,EACzE;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,QAAA,KAAa,OAAA,CAAQ,MAAA;AAC9C,EAAA,MAAM,CAAA,GAAK,YAAY,EAAC;AAGxB,EAAA,MAAM,cAAA,GAAiB,gBAAgB,IAAI,CAAA;AAC3C,EAAA,IAAI,kBAAkB,WAAA,CAAY,WAAA,CAAY,OAAA,CAAQ,cAAc,MAAM,IAAA,EAAM;AAC9E,IAAA,OAAO;AAAA,MACL,SAAS,CAAC;AAAA,QACR,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EAAM,CAAA,mDAAA,EAAsD,cAAc,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAA;AAAA,OAClG;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,MAAM,QAAA,GAAY,CAAA,CAAE,QAAA,IAAY,CAAA,CAAE,SAAA;AAElC,EAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,IAAA,EAAM,CAAW,CAAA;AACtD,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAChC,EAAA,MAAM,UAAU,MAAA,CAAO,OAAA,GAAU,CAAC,CAAA,EAAG,IAAA,EAAM,WAAW,QAAQ,CAAA;AAC9D,EAAA,KAAK,aAAA,CAAc;AAAA,IACjB,QAAA,EAAU,IAAA;AAAA,IACV,SAAA,EAAW,CAAA;AAAA,IACX,QAAA;AAAA,IACA,YAAA,EAAc,UAAU,OAAA,GAAU,SAAA;AAAA,IAClC,cAAc,OAAA,GAAU,MAAA,CAAO,OAAA,GAAU,CAAC,GAAG,IAAA,GAAO,MAAA;AAAA,IACpD;AAAA,GACD,CAAA;AACD,EAAA,OAAO,MAAA;AACT;AAEA,eAAe,eAAA,CACb,IAAA,EACA,CAAA,EACA,SAAA,EACwD;AACxD,EAAA,MAAM,GAAA,GAAM,WAAA;AAEZ,EAAA,IAAI;AACF,IAAA,QAAQ,IAAA;AAAM;AAAA,MAEZ,KAAK,cAAA,EAAgB;AACnB,QAAA,IAAI,KAAA,GAAQ,SACT,IAAA,CAAK,YAAY,EACjB,MAAA,CAAO,0EAA0E,CAAA,CACjF,KAAA,CAAM,MAAM,CAAA;AAEf,QAAA,IAAI,GAAA,CAAI,qBAAqB,IAAA,EAAM;AACjC,UAAA,KAAA,GAAQ,KAAA,CAAM,EAAA,CAAG,IAAA,EAAM,GAAA,CAAI,gBAAgB,CAAA;AAAA,QAC7C;AAEA,QAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,KAAA;AAC9B,QAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AAExC,QAAA,MAAM,YAAA,GAAe,EAAE,YAAA,KAAiB,IAAA;AACxC,QAAA,MAAM,OAAA,GAAU,QAAQ,EAAC;AAMzB,QAAA,IAAI,aAAA,uBAAwC,GAAA,EAAI;AAChD,QAAA,IAAI,YAAA,IAAgB,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACtC,UAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,MAAA,CAAO,CAAA,CAAE,gBAAgB,CAAA,IAAK,CAAC,CAAC,CAAA;AAC7E,UAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAM,IAAA,CAAK,GAAA,CAAI,GAAA,EAAQ,MAAA,CAAO,CAAA,CAAE,cAAc,CAAA,IAAK,GAAI,CAAC,CAAA;AAKxF,UAAA,MAAM,UAAA,GACJ,CAAA,4HAAA,CAAA;AACF,UAAA,MAAM,YAAA,GAAe;AAAA,YACnB,yCAAA;AAAA,YACA,qDAAA;AAAA,YACA,yEAAA;AAAA,YACA,kIAAA;AAAA,YACA;AAAA,WACF,CAAE,KAAK,GAAG,CAAA;AAEV,UAAA,MAAM,QAAA,GAAW,OAAO,CAAA,KAAwD;AAC9E,YAAA,IAAI;AACF,cAAA,MAAM,EAAE,MAAM,KAAA,EAAO,EAAA,KAAO,MAAM,mBAAA,CAAoB,EAAE,EAAE,CAAA;AAC1D,cAAA,IAAA,CAAK,OAAA,GAAU,cAAA;AACf,cAAA,MAAM,OAAA,GAAU,EAAA,KAAO,SAAA,GACnB,6BAAA,CAA8B,YAAA,EAAc,EAAE,CAAA,GAC9C,CAAA,QAAA,EAAW,UAAA,CAAW,UAAU,CAAC,CAAA,CAAA;AACrC,cAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAS,KAAK,CAAA;AACjD,cAAA,IAAI,MAAA,CAAO,aAAa,CAAA,EAAG;AACzB,gBAAA,OAAO,CAAC,CAAA,CAAE,EAAA,EAAI,EAAE,SAAA,EAAW,KAAA,EAAO,QAAQ,MAAA,CAAO,MAAA,IAAU,MAAA,CAAO,MAAA,IAAU,gBAAgB,IAAA,EAAK,CAAE,MAAM,CAAA,EAAG,GAAG,GAAG,CAAA;AAAA,cACpH;AACA,cAAA,MAAM,QAAQ,MAAA,CAAO,MAAA,CAAO,IAAA,EAAK,CAAE,MAAM,GAAG,CAAA;AAC5C,cAAA,OAAO,CAAC,EAAE,EAAA,EAAI;AAAA,gBACZ,SAAA,EAAW,IAAA;AAAA,gBACX,UAAA,EAAY,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,IAAK,CAAA;AAAA,gBAChC,gBAAgB,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA,EAAI,MAAK,IAAK,KAAA;AAAA,gBAC1C,cAAc,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA,EAAI,MAAK,IAAK;AAAA,eACzC,CAAA;AAAA,YACH,SAAS,GAAA,EAAK;AACZ,cAAA,OAAO,CAAC,EAAE,EAAA,EAAI,EAAE,WAAW,KAAA,EAAO,KAAA,EAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA,EAAG,GAAG,IAAI,MAAA,CAAO,GAAG,EAAE,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA;AAAA,YACzH;AAAA,UACF,CAAA;AAGA,UAAA,MAAM,UAAkC,EAAC;AACzC,UAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,EAAQ,KAAK,WAAA,EAAa;AACpD,YAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,IAAI,WAAW,CAAA;AAC9C,YAAA,MAAM,QAAQ,MAAM,OAAA,CAAQ,IAAI,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAC,CAAA;AACnD,YAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,KAAK,CAAA;AAAA,UACvB;AACA,UAAA,aAAA,GAAgB,IAAI,IAAI,OAAO,CAAA;AAAA,QACjC;AAEA,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK;AAC7B,UAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,IAAK,CAAA,CAAE,IAAA,CAAkB,IAAA,CAAK,IAAI,CAAA,GAAI,EAAA;AACvE,UAAA,MAAM,EAAA,GAAM,EAA8B,OAAA,IAAW,OAAA;AACrD,UAAA,MAAM,IAAA,GAAO,GAAG,CAAA,CAAE,EAAE,KAAK,CAAA,CAAE,IAAI,CAAA,EAAA,EAAK,CAAA,CAAE,QAAQ,CAAA,CAAA,EAAI,EAAE,IAAI,CAAA,EAAA,EAAK,CAAA,CAAE,QAAQ,CAAA,GAAA,EAAM,IAAI,MAAM,CAAA,CAAE,SAAA,IAAa,EAAE,CAAA,KAAA,EAAQ,EAAE,CAAA,CAAA;AAClH,UAAA,IAAI,CAAC,cAAc,OAAO,IAAA;AAC1B,UAAA,MAAM,EAAA,GAAK,aAAA,CAAc,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AACjC,UAAA,IAAI,CAAC,EAAA,EAAI,OAAO,CAAA,EAAG,IAAI,CAAA,eAAA,CAAA;AACvB,UAAA,IAAI,CAAC,GAAG,SAAA,EAAW,OAAO,GAAG,IAAI,CAAA,eAAA,EAAkB,EAAA,CAAG,KAAA,IAAS,SAAS,CAAA,CAAA,CAAA;AACxE,UAAA,OAAO,CAAA,EAAG,IAAI,CAAA,aAAA,EAAgB,EAAA,CAAG,UAAU,eAAe,EAAA,CAAG,aAAa,CAAA,SAAA,EAAY,EAAA,CAAG,WAAW,CAAA,CAAA;AAAA,QACtG,CAAC,CAAA;AAED,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAI,CAAA,GAAI,kBAAA,EAAoB,CAAA,EAAE;AAAA,MACnG;AAAA;AAAA,MAGA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA;AAChC,QAAA,iBAAA,CAAkB,OAAO,CAAA;AACzB,QAAA,MAAMb,KAAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,IAAK,CAAA,CAAE,IAAA,CAAmB,GAAA,CAAI,MAAM,CAAA,GAAI,KAAA,CAAA;AACzE,QAAA,MAAM,QAAQ,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,GAAQ,KAAA,CAAA;AACtD,QAAA,MAAM,gBAAgB,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAY,EAAE,KAAA,GAA2C,MAAA;AAClG,QAAA,MAAM,GAAA,GAAM,OAAO,CAAA,CAAE,GAAA,KAAQ,YAAY,CAAA,CAAE,GAAA,GAAM,EAAE,GAAA,GAAM,KAAA,CAAA;AACzD,QAAA,MAAM,YAAY,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA,GAAI,KAAA,CAAA;AAIlD,QAAA,MAAM,SAAA,GAAsB,MAAM,OAAA,CAAQ,CAAA,CAAE,SAAS,CAAA,IAAK,CAAA,CAAE,SAAA,CAAU,MAAA,GAAS,CAAA,GAC1E,CAAA,CAAE,UAAwB,GAAA,CAAI,MAAM,CAAA,GACrC,CAAA,CAAE,QAAA,GAAW,CAAC,OAAO,CAAA,CAAE,QAAQ,CAAC,CAAA,GAAI,EAAC;AACzC,QAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,gDAAA,EAAkD,CAAA,EAAE;AAAA,QAC/F;AAEA,QAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,MAAA,CAAO,CAAA,CAAE,WAAW,CAAA,IAAK,CAAC,CAAC,CAAA;AAGxE,QAAA,MAAM,MAAA,GAAS,OAAO,QAAA,KAAuI;AAC3J,UAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,IAAG,GAAI,MAAM,oBAAoB,QAAQ,CAAA;AAC9D,UAAA,IAAI,SAAA,OAAgB,OAAA,GAAU,SAAA;AAC9B,UAAA,MAAM,QAAQ,aAAA,KAAkB,MAAA,GAAU,EAAA,KAAO,SAAA,GAAY,eAAe,MAAA,GAAU,aAAA;AAGtF,UAAA,IAAI,IAAA;AACJ,UAAA,IAAIA,KAAAA,IAAQA,KAAAA,CAAK,MAAA,GAAS,CAAA,EAAG;AAC3B,YAAA,IAAA,GAAO,KAAA,KAAU,eACb,6BAAA,CAA8B,OAAA,EAASA,KAAI,CAAA,GAC3C,iBAAA,CAAkB,SAASA,KAAI,CAAA;AAAA,UACrC,CAAA,MAAA,IAAW,UAAU,YAAA,IAAgB,CAAC,iBAAiB,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,CAAA,EAAG;AAE3E,YAAA,IAAA,GAAO,6BAAA,CAA8B,OAAA,EAAS,EAAE,CAAA;AAAA,UAClD,CAAA,MAAO;AACL,YAAA,IAAA,GAAO,OAAA;AAAA,UACT;AAMA,UAAA,IAAI,QAAA,GAAW,IAAA;AACf,UAAA,IAAI,GAAA,EAAK;AACP,YAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,cAAA,QAAA,GAAW,CAAA,GAAA,EAAM,UAAA,CAAW,GAAG,CAAC,OAAO,IAAI,CAAA,CAAA;AAAA,YAC7C,CAAA,MAAO;AAGL,cAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,0BAA0B,CAAA;AACrD,cAAA,IAAI,OAAA,EAAS;AACX,gBAAA,MAAM,OAAA,GAAU,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,EAAa,QAAQ,CAAA,CAAE,QAAA,CAAS,SAAS,CAAA;AAC9E,gBAAA,MAAM,OAAA,GAAU,8BAA8B,GAAA,CAAI,OAAA,CAAQ,MAAM,IAAI,CAAC,MAAM,OAAO,CAAA,CAAA;AAClF,gBAAA,MAAM,YAAY,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA,CAAE,SAAS,QAAQ,CAAA;AACnE,gBAAA,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,wBAAA,EAA0B,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAE,CAAA;AAAA,cAClF;AAAA,YACF;AAAA,UACF;AAEA,UAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,KAAA,KAAU,KAAA,CAAA,GAAY,EAAE,KAAA,EAAM,GAAI,KAAA,CAAS,CAAA;AAE/F,UAAA,IAAI,UAAA,GAAa,QAAA;AACjB,UAAA,IAAI;AACF,YAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,SAAS,IAAA,CAAK,YAAY,CAAA,CAAE,MAAA,CAAO,MAAM,CAAA,CAAE,EAAA,CAAG,IAAA,EAAM,QAAQ,EAAE,MAAA,EAAO;AAC5F,YAAA,IAAI,IAAA,EAAM,IAAA,EAAM,UAAA,GAAa,IAAA,CAAK,IAAA;AAAA,UACpC,CAAA,CAAA,MAAQ;AAAA,UAAwB;AAChC,UAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,EAAA,EAAI,OAAO,MAAA,EAAO;AAAA,QACnD,CAAA;AAGA,QAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,UAAA,MAAM,EAAE,IAAI,KAAA,EAAO,MAAA,KAAW,MAAM,MAAA,CAAO,SAAA,CAAU,CAAC,CAAW,CAAA;AACjE,UAAA,MAAM,MAAA,GAAS,CAAC,CAAA,WAAA,EAAc,MAAA,CAAO,QAAQ,CAAA,MAAA,EAAS,EAAE,CAAA,SAAA,EAAY,KAAK,CAAA,CAAA,CAAG,CAAA;AAC5E,UAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAA;AAAA,EAAmB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACjE,UAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAA;AAAA,EAAmB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACjE,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,QAChE;AAGA,QAAA,MAAM,aAA8F,EAAC;AACrG,QAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,SAAA,CAAU,MAAA,EAAQ,KAAK,WAAA,EAAa;AACtD,UAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,IAAI,WAAW,CAAA;AAChD,UAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA,CAAW,KAAA,CAAM,IAAI,CAAA,EAAA,KAAM,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA;AACpE,UAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AACvC,YAAA,MAAM,CAAA,GAAI,QAAQ,CAAC,CAAA;AACnB,YAAA,IAAI,EAAE,MAAA,KAAW,WAAA,EAAa,UAAA,CAAW,IAAA,CAAK,EAAE,KAAK,CAAA;AAAA,4BACrC,IAAA,CAAK,EAAE,UAAU,KAAA,CAAM,CAAC,GAAa,KAAA,EAAO,CAAA,CAAE,MAAA,YAAkB,KAAA,GAAQ,EAAE,MAAA,CAAO,OAAA,GAAU,OAAO,CAAA,CAAE,MAAM,GAAG,CAAA;AAAA,UAC/H;AAAA,QACF;AAGA,QAAA,MAAM,WAAqB,EAAC;AAC5B,QAAA,IAAI,OAAA,GAAU,CAAA;AACd,QAAA,IAAI,SAAA,GAAY,CAAA;AAChB,QAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,UAAA,IAAI,WAAW,CAAA,EAAG;AAChB,YAAA,SAAA,EAAA;AACA,YAAA,QAAA,CAAS,KAAK,CAAA,IAAA,EAAO,CAAA,CAAE,QAAQ,CAAA,0BAAA,EAA6B,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA;AACrE,YAAA;AAAA,UACF;AACA,UAAA,IAAI,CAAA,CAAE,MAAA,CAAO,QAAA,KAAa,CAAA,EAAG,OAAA,EAAA;AAAA,eAAgB,SAAA,EAAA;AAC7C,UAAA,MAAM,MAAA,GAAS,CAAA,IAAA,EAAO,CAAA,CAAE,UAAU,CAAA,EAAA,EAAK,EAAE,EAAE,CAAA,OAAA,EAAU,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAA,KAAA,CAAA;AACtE,UAAA,MAAM,KAAA,GAAQ,CAAC,MAAM,CAAA;AACrB,UAAA,IAAI,CAAA,CAAE,OAAO,MAAA,EAAQ,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,CAAA;AACzD,UAAA,IAAI,CAAA,CAAE,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,CAAA,SAAA,EAAY,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,CAAA;AACvE,UAAA,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,QAChC;AACA,QAAA,QAAA,CAAS,IAAA,CAAK,CAAA,qBAAA,EAAwB,OAAO,CAAA,MAAA,EAAS,SAAS,kBAAkB,UAAA,CAAW,MAAM,CAAA,sBAAA,EAAyB,WAAW,CAAA,KAAA,CAAO,CAAA;AAC7I,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA,EAAG,CAAA,EAAE;AAAA,MACpE;AAAA;AAAA,MAGA,KAAK,WAAA,EAAa;AAChB,QAAA,MAAM,MAAA,GAAS,OAAO,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,MAAA,GAAS,EAAE,MAAA,GAAS,EAAA;AACrE,QAAA,MAAM,SAAA,GAAY,EAAE,SAAA,KAAc,IAAA;AAClC,QAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,GAAA,EAAQ,MAAA,CAAO,CAAA,CAAE,UAAU,CAAA,IAAK,GAAK,CAAC,CAAA;AAC9E,QAAA,MAAM,UAAU,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,GAAW,EAAE,OAAA,GAAU,EAAA;AAC5D,QAAA,MAAM,OAAA,GAAU,EAAE,OAAA,KAAY,IAAA;AAE9B,QAAA,MAAM,MAAA,GAAU,CAAA,CAAE,MAAA,KAAW,MAAA,IAAU,CAAA,CAAE,MAAA,KAAW,OAAA,IAAW,CAAA,CAAE,MAAA,KAAW,MAAA,GAAU,CAAA,CAAE,MAAA,GAAS,MAAA;AACjG,QAAA,MAAM,OAAA,GAAU,EAAE,OAAA,KAAY,IAAA;AAI9B,QAAA,IAAI,OAAA;AACJ,QAAA,IAAI,SAAA,GAAY,KAAA;AAChB,QAAA,IAAI,OAAA,GAAU,EAAA;AAEd,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,MAAM,SAAS,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,IAAA,IAAQ,EAAE,CAAC,CAAA;AACzC,UAAA,MAAM,OAAA,GAAU,OAAA,GAAU,YAAA,CAAa,OAAO,CAAA,GAAI,IAAA;AAClD,UAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,EAAQ,QAAQ,EAAE,SAAA,EAAW,YAAY,CAAA;AACxE,UAAA,MAAM,WAAW,OAAA,GACb,SAAA,CAAU,MAAA,CAAO,CAAA,CAAA,KAAK,QAAQ,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,MAAS,CAAA,CAAE,GAAG,CAAC,CAAA,GACnE,SAAA;AACJ,UAAA,OAAA,GAAU,QAAA,CAAS,IAAI,CAAA,CAAA,KAAK;AAC1B,YAAA,MAAM,KAAK,CAAA,CAAE,KAAA,GAAQ,KAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA,GAAI,CAAA;AAC3C,YAAA,OAAO;AAAA,cACL,IAAA,EAAM,CAAA,CAAE,QAAA,GAAW,GAAA,GAAe,GAAA;AAAA,cAClC,MAAM,CAAA,CAAE,IAAA;AAAA,cACR,OAAO,CAAA,CAAE,KAAA;AAAA,cACT,OAAA,EAAS,MAAA,CAAO,QAAA,CAAS,EAAE,IAAI,EAAA,GAAK,CAAA;AAAA,cACpC,MAAM,CAAA,CAAE;AAAA,aACV;AAAA,UACF,CAAC,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,UAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,IAAA,EAAM,OAAO,CAAA,CAAE,IAAA,IAAQ,GAAG,CAAA,EAAG,KAAA,EAAO;AAAA,YACnE,SAAA;AAAA,YACA,UAAU,OAAO,CAAA,CAAE,QAAA,KAAa,QAAA,GAAW,EAAE,QAAA,GAAW,KAAA,CAAA;AAAA,YACxD,SAAS,OAAA,IAAW,KAAA,CAAA;AAAA,YACpB;AAAA,WACD,CAAA;AACD,UAAA,IAAI,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC/C,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,MAAA,CAAO,KAAK,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UACvE;AACA,UAAA,OAAA,GAAU,MAAA,CAAO,OAAA;AACjB,UAAA,SAAA,GAAY,MAAA,CAAO,SAAA;AACnB,UAAA,IAAI,MAAA,CAAO,KAAA,EAAO,OAAA,GAAU,MAAA,CAAO,KAAA;AAAA,QACrC;AAGA,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,MAAM,QAAQ,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,GAAG,CAAA;AAChD,UAAA,MAAM,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,GAAG,CAAA;AAC/C,UAAA,MAAM,SAAA,GAAY,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,EAAK,MAAM,GAAA,IAAO,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAA,EAAI,CAAC,CAAA;AACjE,UAAA,MAAMe,MAAAA,GAAQ;AAAA,YACZ,CAAA,cAAA,EAAiB,MAAM,MAAM,CAAA,CAAA;AAAA,YAC7B,CAAA,cAAA,EAAiB,KAAK,MAAM,CAAA,CAAA;AAAA,YAC5B,CAAA,cAAA,EAAiB,SAAS,CAAA,QAAA,EAAA,CAAY,SAAA,IAAa,OAAO,IAAA,CAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,IAAA;AAAA,WAC7E;AACA,UAAA,IAAI,WAAWA,MAAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,UAAU,CAAA,wBAAA,CAA0B,CAAA;AAC/E,UAAA,IAAI,SAASA,MAAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,OAAO,CAAA,CAAA,CAAG,CAAA;AAChD,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAMA,MAAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,QAC/D;AAKA,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACrB,UAAA,IAAI,CAAA,CAAE,SAAS,CAAA,CAAE,IAAA,SAAa,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,CAAA,GAAK,CAAA;AACpD,UAAA,IAAI,GAAA,GAAM,CAAA;AACV,UAAA,IAAI,MAAA,KAAW,MAAA,EAAQ,GAAA,GAAM,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA;AAAA,eAAA,IAC/B,MAAA,KAAW,OAAA,EAAS,GAAA,GAAM,CAAA,CAAE,UAAU,CAAA,CAAE,OAAA;AAAA,eAC5C,GAAA,GAAM,CAAA,CAAE,IAAA,CAAK,aAAA,CAAc,EAAE,IAAI,CAAA;AACtC,UAAA,OAAO,OAAA,GAAU,CAAC,GAAA,GAAM,GAAA;AAAA,QAC1B,CAAC,CAAA;AAED,QAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,YAAA,EAAc,CAAA,EAAE;AACnF,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK;AAC7B,UAAA,MAAM,OAAA,GAAU,EAAE,IAAA,KAAS,GAAA,IAAO,SAAS,UAAA,GAAa,MAAA,CAAO,EAAE,IAAI,CAAA;AACrE,UAAA,OAAO,GAAG,CAAA,CAAE,IAAI,CAAA,CAAA,EAAI,OAAA,CAAQ,SAAS,EAAE,CAAC,CAAA,CAAA,EAAA,CAAK,CAAA,CAAE,SAAS,EAAA,EAAI,MAAA,CAAO,EAAE,CAAC,CAAA,CAAA,EAAI,EAAE,IAAI,CAAA,CAAA;AAAA,QAClF,CAAC,CAAA;AACD,QAAA,IAAI,SAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,kBAAA,EAAqB,UAAU,CAAA,kDAAA,CAAoD,CAAA;AAC7G,QAAA,IAAI,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AACtC,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,MAC/D;AAAA,MAEA,KAAK,WAAA,EAAa;AAChB,QAAA,MAAM,MAAA,GAAS,OAAO,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,MAAA,GAAS,EAAE,MAAA,GAAS,EAAA;AACrE,QAAA,MAAM,MAAA,GAAS,CAAA,CAAE,MAAA,KAAW,KAAA,CAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,MAAM,CAAC,CAAA,GAAI,KAAA,CAAA;AACxE,QAAA,MAAM,MAAA,GAAS,CAAA,CAAE,MAAA,KAAW,KAAA,CAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,MAAM,CAAC,CAAA,GAAI,KAAA,CAAA;AACxE,QAAA,MAAM,QAAA,GAAW,MAAA,KAAW,KAAA,CAAA,IAAa,MAAA,KAAW,KAAA,CAAA;AAEpD,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,MAAM,GAAA,GAAM,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA;AAChC,UAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,yBAAA,EAA2B,CAAA,EAAE;AAChF,UAAA,IAAI;AACF,YAAA,IAAI,QAAA,EAAU;AACZ,cAAA,MAAMC,QAAAA,GAAU,MAAM,gBAAA,CAAiB,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,MAAA,IAAU,CAAA,EAAG,MAAA,EAAQ,CAAA;AACnF,cAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAMA,QAAAA,EAAS,CAAA,EAAE;AAAA,YACtD;AACA,YAAA,MAAMA,QAAAA,GAAU,MAAM,WAAA,CAAY,MAAA,EAAQ,KAAK,OAAS,CAAA;AACxD,YAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAMA,QAAAA,EAAS,CAAA,EAAE;AAAA,UACtD,SAAS,CAAA,EAAG;AACV,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UACrG;AAAA,QACF;AACA,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAM,OAAO,CAAA,CAAE,IAAI,CAAA,EAAG,KAAA,EAAO,QAAA,GAAW,EAAE,MAAA,EAAQ,MAAA,KAAW,KAAA,CAAS,CAAA;AACrG,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,CAAA,EAAE;AAAA,MACtD;AAAA,MAEA,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,MAAA,GAAS,OAAO,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,MAAA,GAAS,EAAE,MAAA,GAAS,EAAA;AAIrE,QAAA,IAAI,QAAA;AACJ,QAAA,IAAI,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,EAAG,QAAA,GAAW,CAAA,CAAE,IAAA,GAAO,IAAA;AAAA,aAAA,IACtE,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,EAAE,IAAA,EAAM;AAC7C,UAAA,MAAM,OAAA,GAAU,CAAA,CAAE,IAAA,CAAK,OAAA,CAAQ,SAAS,EAAE,CAAA;AAC1C,UAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,EAAS,CAAC,CAAA;AAClC,UAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,aAAc,MAAA,GAAS,IAAA;AAAA,QACjD;AACA,QAAA,IAAI,OAAA;AACJ,QAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,IAAY,MAAA,CAAO,SAAS,CAAA,CAAE,KAAK,CAAA,EAAG,OAAA,GAAU,CAAA,CAAE,KAAA;AAAA,aAAA,IAChE,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,IAAY,EAAE,KAAA,EAAO;AAC/C,UAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA;AACjC,UAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,MAAM,GAAG,OAAA,GAAU,MAAA;AAAA,QACvC;AAEA,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,MAAM,GAAA,GAAM,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA;AAChC,UAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,yBAAA,EAA2B,CAAA,EAAE;AAChF,UAAA,IAAI,QAAA,KAAa,KAAA,CAAA,IAAa,OAAA,KAAY,KAAA,CAAA,EAAW;AAAA,UAIrD;AACA,UAAA,IAAI;AACF,YAAA,IAAI,OAAO,CAAA,CAAE,UAAA,KAAe,YAAY,CAAA,CAAE,UAAA,CAAW,SAAS,CAAA,EAAG;AAC/D,cAAA,MAAM,QAAQ,CAAA,CAAE,UAAA;AAChB,cAAA,IAAI,CAAC,UAAA,CAAW,KAAK,CAAA,EAAG,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,4CAAA,EAA+C,KAAK,CAAA,CAAA,EAAI,CAAA,EAAE;AAC3H,cAAA,IAAI,CAACH,UAAAA,CAAW,KAAK,CAAA,EAAG,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,kCAAA,EAAqC,KAAK,CAAA,CAAA,EAAI,CAAA,EAAE;AACjH,cAAA,MAAM,EAAA,GAAK,SAAS,KAAK,CAAA;AACzB,cAAA,IAAI,CAAC,EAAA,CAAG,MAAA,EAAO,EAAG,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,yCAAA,EAA4C,KAAK,CAAA,CAAA,EAAI,CAAA,EAAE;AAClH,cAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,cAAA,IAAI,EAAA,CAAG,OAAO,sBAAA,EAAwB;AAGpC,gBAAA,IAAI,OAAA,GAAU,CAAA;AACd,gBAAA,MAAM,qBAAqB,MAAA,EAAQ,GAAA,EAAK,OAAO,EAAA,CAAG,IAAA,EAAM,CAAC,QAAA,KAAa;AACpE,kBAAA,IAAI,QAAA,GAAW,OAAA,IAAW,GAAA,GAAM,IAAA,GAAO,IAAA,EAAM;AAC3C,oBAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,WAAA,EAAc,WAAA,CAAY,QAAQ,CAAC,CAAA,GAAA,EAAM,WAAA,CAAY,EAAA,CAAG,IAAI,CAAC,CAAA,aAAA,EAAW,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AACrG,oBAAA,OAAA,GAAU,QAAA;AAAA,kBACZ;AAAA,gBACF,CAAC,CAAA;AACD,gBAAA,MAAMI,QAAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC7B,gBAAA,MAAM,IAAA,GAAO,GAAG,IAAA,IAAQ,IAAA,GAAO,QAAQ,IAAA,CAAK,GAAA,CAAI,IAAA,EAAOA,QAAAA,GAAU,GAAI,CAAA;AACrE,gBAAA,MAAM,YAAsB,EAAC;AAC7B,gBAAA,IAAI,QAAA,KAAa,KAAA,CAAA,EAAW,SAAA,CAAU,IAAA,CAAK,mBAAmB,CAAA;AAC9D,gBAAA,IAAI,OAAA,KAAY,KAAA,CAAA,EAAW,SAAA,CAAU,IAAA,CAAK,oBAAoB,CAAA;AAC9D,gBAAA,MAAM,IAAA,GAAO,UAAU,MAAA,GAAS,CAAA,EAAA,EAAK,UAAU,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA,GAAM,EAAA;AAC/D,gBAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,SAAA,EAAY,WAAA,CAAY,EAAA,CAAG,IAAI,CAAC,CAAA,MAAA,EAAS,KAAK,CAAA,SAAA,EAAY,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,kBAAA,EAAA,CAAsBA,QAAAA,GAAU,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,cAC1M;AACA,cAAA,MAAM,MAAA,GAAS,iBAAiB,KAAK,CAAA;AACrC,cAAA,MAAM,WAAA,CAAY,MAAA,EAAQ,GAAA,EAAK,MAAA,EAAQ,GAAG,IAAI,CAAA;AAC9C,cAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC7B,cAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,YAAY,EAAA,CAAG,IAAI,eAAe,KAAK,CAAA,SAAA,EAAY,MAAM,CAAA,CAAA,EAAI,GAAG,OAAO,OAAO,CAAA,EAAA,CAAA,EAAM,CAAA,EAAE;AAAA,YACjI;AACA,YAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,MAAA,CAAO,EAAE,OAAA,IAAW,EAAE,GAAG,OAAO,CAAA;AACxD,YAAA,MAAM,WAAA,CAAY,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,IAAI,MAAM,CAAA;AAC9C,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,MAAA,EAAS,GAAA,CAAI,MAAM,kBAAkB,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UACnG,SAAS,CAAA,EAAG;AACV,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UACrG;AAAA,QACF;AAEA,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,KAAA,GACJ,OAAO,CAAA,CAAE,UAAA,KAAe,YAAY,CAAA,CAAE,UAAA,CAAW,SAAS,CAAA,GACtD,EAAE,YAAY,CAAA,CAAE,UAAA,KAChB,EAAE,OAAA,EAAS,OAAO,CAAA,CAAE,OAAA,IAAW,EAAE,CAAA,EAAE;AACzC,QAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,IAAA,EAAM,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA,EAAG,KAAA,EAAO,KAAA,EAAO,EAAE,QAAA,EAAU,SAAS,CAAA;AACxF,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,CAAA,EAAE;AAAA,MACrD;AAAA,MAEA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,MAAA,GAAS,OAAO,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,MAAA,GAAS,EAAE,MAAA,GAAS,EAAA;AACrE,QAAA,MAAM,SAAA,GAAY,EAAE,SAAA,KAAc,IAAA;AAClC,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,MAAM,GAAA,GAAM,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA;AAChC,UAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,yBAAA,EAA2B,CAAA,EAAE;AAChF,UAAA,IAAI;AACF,YAAA,IAAI,SAAA,EAAW;AAGb,cAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,MAAA,EAAQ,GAAG,CAAA;AAChD,cAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,QAAA,EAAW,OAAO,yBAAyB,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,YACzG;AACA,YAAA,MAAM,cAAA,CAAe,QAAQ,GAAG,CAAA;AAChC,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,aAAA,EAAgB,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UAC9E,SAAS,CAAA,EAAG;AACV,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UACrG;AAAA,QACF;AACA,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,IAAA,EAAM,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA,EAAG,KAAA,EAAO,EAAE,SAAA,EAAW,CAAA;AAC1E,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,CAAA,EAAE;AAAA,MACrD;AAAA;AAAA,MAGA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,MAAA,GAAS,CAAA,CAAE,MAAA,KAAW,MAAA,GAAS,MAAA,GAAS,OAAA;AAC9C,QAAA,MAAM,WAAA,GAAc,EAAE,WAAA,KAAgB,IAAA;AACtC,QAAA,MAAM,cAAA,GAAiB,EAAE,cAAA,KAAmB,IAAA;AAI5C,QAAA,MAAM,cAAA,GAA2B,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,UAAU,CAAA,GACtD,CAAA,CAAE,UAAA,CAAyB,GAAA,CAAI,CAAA,CAAA,KAAK,MAAA,CAAO,CAAC,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,GACpE,OAAO,CAAA,CAAE,UAAA,KAAe,YAAY,CAAA,CAAE,UAAA,CAAW,IAAA,EAAK,GAAI,CAAC,CAAA,CAAE,UAAA,CAAW,IAAA,EAAM,IAAI,EAAC;AAIxF,QAAA,MAAM,SAAA,GAAY,cAAc,CAAA,4CAAA,CAAA,GAAiD,EAAA;AACjF,QAAA,MAAM,GAAA,GAAM,eAAe,SAAS,CAAA,sBAAA,CAAA;AACpC,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC7C,QAAA,IAAI,MAAA,CAAO,aAAa,CAAA,EAAG;AACzB,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,MAAA,CAAO,MAAA,IAAU,MAAA,CAAO,MAAM,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,QACzF;AAGA,QAAA,MAAM,aAA4B,EAAC;AACnC,QAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,EAAG;AAC5C,UAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,UAAA,IAAI,CAAC,OAAA,EAAS;AACd,UAAA,IAAI;AAAE,YAAA,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,OAAO,CAAgB,CAAA;AAAA,UAAG,CAAA,CAAA,MAAQ;AAAA,UAA8B;AAAA,QACnG;AAKA,QAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,UAAA,MAAM,CAAA,GAAA,CAAK,CAAA,CAAE,MAAA,IAAU,EAAA,EAAI,MAAM,uCAAuC,CAAA;AACxE,UAAA,CAAA,CAAE,OAAA,GAAU,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA;AACvB,UAAA,MAAM,MAAA,GAAS,EAAE,MAAA,IAAU,EAAA;AAC3B,UAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA,IAAK,MAAA,GAAS,WAAA;AAAA,eAAA,IACrC,oCAAA,CAAqC,IAAA,CAAK,MAAM,CAAA,IAAK,MAAA,GAAS,UAAA;AAAA,eAAA,IAC9D,cAAA,CAAe,IAAA,CAAK,MAAM,CAAA,IAAK,MAAA,GAAS,SAAA;AAAA,eAAA,IACxC,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA,IAAK,MAAA,GAAS,UAAA;AAAA,iBACpC,MAAA,GAAS,EAAA;AAAA,QAClB;AAGA,QAAA,IAAI,QAAA,GAAW,UAAA;AACf,QAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,UAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,CAAA,GAAA,KAAO;AACzC,YAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,IAAK,IAAI,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,EAAA,EAAI,YAAA,CAAa,GAAG,CAAA,EAAE;AAClG,YAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAgB,KAAA,EAAO,GAAA,CAAI,aAAY,EAAE;AAAA,UAC1D,CAAC,CAAA;AACD,UAAA,QAAA,GAAW,UAAA,CAAW,OAAO,CAAA,CAAA,KAAK;AAChC,YAAA,MAAMX,KAAAA,GAAO,EAAE,KAAA,IAAS,EAAA;AACxB,YAAA,MAAM,KAAA,GAAQA,MAAK,WAAA,EAAY;AAC/B,YAAA,OAAO,QAAA,CAAS,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,MAAA,GAAS,CAAA,CAAE,EAAA,CAAG,IAAA,CAAKA,KAAI,CAAA,GAAI,KAAA,CAAM,QAAA,CAAS,CAAA,CAAE,KAAK,CAAC,CAAA;AAAA,UACzF,CAAC,CAAA;AAAA,QACH;AAGA,QAAA,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACtB,UAAA,MAAM,EAAA,GAAK,EAAE,OAAA,IAAW,GAAA;AACxB,UAAA,MAAM,EAAA,GAAK,EAAE,OAAA,IAAW,GAAA;AACxB,UAAA,MAAM,CAAA,GAAI,EAAA,CAAG,aAAA,CAAc,EAAE,CAAA;AAC7B,UAAA,OAAO,CAAA,KAAM,IAAI,CAAA,GAAA,CAAK,CAAA,CAAE,SAAS,EAAA,EAAI,aAAA,CAAc,CAAA,CAAE,KAAA,IAAS,EAAE,CAAA;AAAA,QAClE,CAAC,CAAA;AAED,QAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,UAAA,MAAMC,KAAAA,GAAO,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,IAAK,iBAAA;AAChE,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAAA,KAAAA,EAAM,CAAA,EAAE;AAAA,QAC7C;AAIA,QAAA,MAAM,SAAS,CAAC,CAAA,KACd,CAAA,EAAA,CAAI,CAAA,CAAE,SAAS,EAAA,EAAI,MAAA,CAAO,EAAE,CAAC,MAAM,CAAA,CAAE,KAAA,IAAS,EAAA,EAAI,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAA,CAAM,CAAA,CAAE,MAAA,IAAU,IAAI,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAA,CAAM,EAAE,MAAA,IAAU,EAAA,EAAI,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAA,CAAM,CAAA,CAAE,SAAS,EAAA,EAAI,MAAA,CAAO,EAAE,CAAC,CAAA,CAAA;AAE7J,QAAA,IAAI,cAAA,EAAgB;AAClB,UAAA,MAAM,MAAA,uBAAa,GAAA,EAA2B;AAC9C,UAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,YAAA,MAAM,GAAA,GAAM,EAAE,OAAA,IAAW,sBAAA;AACzB,YAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC3B,YAAA,IAAI,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAAA,iBAAQ,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,CAAC,CAAC,CAAC,CAAA;AAAA,UAClD;AACA,UAAA,MAAM,MAAgB,EAAC;AACvB,UAAA,KAAA,MAAW,CAAC,OAAA,EAAS,IAAI,CAAA,IAAK,MAAA,EAAQ;AACpC,YAAA,GAAA,CAAI,KAAK,CAAA,IAAA,EAAO,OAAO,CAAA,EAAA,EAAK,IAAA,CAAK,MAAM,CAAA,KAAA,CAAO,CAAA;AAC9C,YAAA,KAAA,MAAW,KAAK,IAAA,EAAM,GAAA,CAAI,KAAK,IAAA,GAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAC/C,YAAA,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,UACb;AACA,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,CAAE,OAAA,EAAQ,IAAK,iBAAA,EAAmB,CAAA,EAAE;AAAA,QAC5F;AAEA,QAAA,MAAM,MAAA,GAAS,CAAA,EAAG,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,SAAS,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,QAAA,CAAS,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAK,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA,SAAA,CAAA;AAClI,QAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAA,IAAW,EAAE,CAAA,CAAE,CAAA;AACjE,QAAA,MAAM,IAAA,GAAO,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,uBAAA,GAA0B,CAAC,MAAA,EAAQ,GAAG,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAC1F,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAE;AAAA,MAC7C;AAAA,MAEA,KAAK,aAAA,EAAe;AAIlB,QAAA,MAAM,QAAA,GAAW,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,aAAa,CAAA,GACzC,CAAA,CAAE,aAAA,CAA4B,GAAA,CAAI,MAAM,CAAA,GACzC,CAAC,MAAA,CAAO,CAAA,CAAE,aAAa,CAAC,CAAA;AAC5B,QAAA,MAAM,UAAA,GAAa,QAAA,CAChB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAC,CAAA,CAC1C,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAA;AAC3B,QAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,wCAAA,EAA0C,CAAA,EAAE;AAAA,QACvF;AAIA,QAAA,MAAM,OAAO,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA,GAAI,CAAA,GAAI,OAAO,CAAA,CAAE,IAAI,CAAA,GAAK,MAAA,CAAO,EAAE,KAAK,CAAA,GAAI,IAAI,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA,GAAI,GAAA;AAC5F,QAAA,MAAM,QAAA,GAAW,OAAO,CAAA,CAAE,KAAA,KAAU,WAAW,CAAA,CAAE,KAAA,CAAM,MAAK,GAAI,EAAA;AAChE,QAAA,MAAM,UAAU,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,GAAW,EAAE,IAAA,GAAO,EAAA;AAItD,QAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,MAAA,CAAO,CAAA,CAAE,aAAa,CAAA,IAAK,CAAC,CAAC,CAAA;AAG7E,QAAA,IAAI,QAAA,IAAY,CAAC,cAAA,CAAe,IAAA,CAAK,QAAQ,KAAK,CAAC,oBAAA,CAAqB,IAAA,CAAK,QAAQ,CAAA,EAAG;AACtF,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,6EAAA,EAA+E,CAAA,EAAE;AAAA,QAC5H;AACA,QAAA,MAAM,WAAW,QAAA,GAAW,CAAA,SAAA,EAAY,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAA,GAAK,EAAA;AACjE,QAAA,MAAM,aAAa,OAAA,GAAU,CAAA,cAAA,EAAiB,UAAA,CAAW,OAAO,CAAC,CAAA,gBAAA,CAAA,GAAqB,EAAA;AAGtF,QAAA,MAAM,aAAa,CAAA,CAAE,IAAA,KAAS,UAAa,CAAA,CAAE,KAAA,KAAU,SAAY,IAAA,GAAO,CAAA;AAC1E,QAAA,MAAM,OAAA,GAAU,aAAA,GAAgB,CAAA,GAAI,UAAA,GAAa,IAAA;AAEjD,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AAEpE,QAAA,IAAI,aAAA,GAAgB,CAAA,EAAG,IAAA,CAAK,OAAA,GAAA,CAAW,gBAAgB,EAAA,IAAM,GAAA;AAE7D,QAAA,MAAM,UAAA,GAAa,aAAA,GAAgB,CAAA,GAAI,KAAA,GAAQ,EAAA;AAG/C,QAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,UAAA,MAAM,CAAA,GAAI,WAAW,CAAC,CAAA;AACtB,UAAA,MAAMW,MAAAA,GAAQ,CAAA,WAAA,EAAc,UAAU,CAAA,QAAA,EAAW,OAAO,GAAG,QAAQ,CAAA,CAAA,EAAI,CAAC,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA;AAG1F,UAAA,MAAMC,IAAAA,GAAM,gBAAgB,CAAA,GACxB,CAAA,qBAAA,EAAwB,aAAa,CAAA,OAAA,EAAU,UAAA,CAAWD,MAAK,CAAC,CAAA,CAAA,GAChEA,MAAAA;AACJ,UAAA,MAAME,OAAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAMD,MAAK,KAAK,CAAA;AAC7C,UAAA,MAAME,cAAa,aAAA,GAAgB,CAAA,GAC9BD,OAAAA,CAAO,QAAA,KAAa,KAAKA,OAAAA,CAAO,QAAA,KAAa,GAAA,IAAOA,OAAAA,CAAO,aAAa,GAAA,GACxEA,OAAAA,CAAO,aAAa,CAAA,IAAM,OAAA,IAAWA,QAAO,QAAA,KAAa,CAAA;AAC9D,UAAA,IAAI,CAACC,WAAAA,EAAY;AACf,YAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,YAAA,EAAeD,OAAAA,CAAO,QAAQ,MAAMA,OAAAA,CAAO,MAAA,IAAUA,QAAO,MAAM,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,UACnH;AACA,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAMA,OAAAA,CAAO,MAAA,IAAU,wBAAA,EAA0B,CAAA,EAAE;AAAA,QACxF;AAKA,QAAA,MAAM,SAAA,GAAY,UAAA,CAAW,GAAA,CAAI,CAAA,CAAA,KAAK;AACpC,UAAA,MAAMF,MAAAA,GAAQ,CAAA,WAAA,EAAc,UAAU,CAAA,QAAA,EAAW,OAAO,GAAG,QAAQ,CAAA,CAAA,EAAI,CAAC,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA;AAC1F,UAAA,OAAO,IAAIA,MAAK,CAAA,aAAA,EAAgB,WAAW,CAAA,KAAA,EAAQ,CAAC,KAAK,CAAC,CAAA,CAAA,CAAA;AAAA,QAC5D,CAAC,CAAA;AACD,QAAA,MAAM,KAAA,GAAQ,aAAA,GAAgB,CAAA,GAC1B,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA,GAAI,SAAA,GACxB,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA;AACvB,QAAA,MAAM,GAAA,GAAM,gBAAgB,CAAA,GACxB,CAAA,qBAAA,EAAwB,aAAa,CAAA,OAAA,EAAU,UAAA,CAAW,KAAK,CAAC,CAAA,CAAA,GAChE,KAAA;AACJ,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,KAAK,KAAK,CAAA;AAC7C,QAAA,MAAM,UAAA,GAAa,gBAAgB,CAAA,GAC9B,MAAA,CAAO,aAAa,CAAA,IAAK,MAAA,CAAO,aAAa,GAAA,IAAO,MAAA,CAAO,aAAa,GAAA,IAAO,MAAA,CAAO,aAAa,GAAA,GACnG,MAAA,CAAO,aAAa,CAAA,IAAM,OAAA,IAAW,OAAO,QAAA,KAAa,CAAA;AAC9D,QAAA,IAAI,CAAC,UAAA,EAAY;AACf,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,YAAA,EAAe,MAAA,CAAO,QAAQ,MAAM,MAAA,CAAO,MAAA,IAAU,OAAO,MAAM,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,QACnH;AACA,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,CAAO,MAAA,IAAU,wBAAA,EAA0B,CAAA,EAAE;AAAA,MACxF;AAAA,MAEA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,YAAY,MAAA,CAAO,CAAA,CAAE,SAAS,CAAA,CAAE,OAAA,CAAQ,oBAAoB,EAAE,CAAA;AACpE,QAAA,IAAI,CAAC,SAAA,EAAW,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,+BAAA,EAAiC,CAAA,EAAE;AAC5F,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA;AAChC,QAAA,MAAMlB,KAAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAA,GAAK,CAAA,CAAE,IAAA,CAAmB,GAAA,CAAI,MAAM,CAAA,GAAI,EAAC;AAC1E,QAAA,MAAM,QAAQ,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,GAAQ,KAAA,CAAA;AACtD,QAAA,MAAM,WAAA,GAAc,EAAE,WAAA,KAAgB,IAAA;AACtC,QAAA,MAAM,OAAA,GAAU,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,IAAY,CAAA,CAAE,OAAA,GAAU,CAAC,IAAA,EAAM,CAAA,CAAE,OAAO,CAAA,GAAI,EAAC;AAClF,QAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,GAAO,CAAC,IAAA,EAAM,CAAA,CAAE,IAAI,CAAA,GAAI,EAAC;AAQtE,QAAA,MAAM,QAAkB,EAAC;AACzB,QAAA,IAAI,KAAA,KAAU,KAAA,CAAA,IAAa,WAAA,EAAa,KAAA,CAAM,KAAK,IAAI,CAAA;AACvD,QAAA,IAAI,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAGhC,QAAA,MAAM,UAAA,GAAa,CAAC,GAAG,KAAA,EAAO,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,GAAGA,KAAI,CAAA;AAC9E,QAAA,MAAM,UAAU,iBAAA,CAAkB,QAAA,EAAU,CAAC,MAAA,EAAQ,GAAG,UAAU,CAAC,CAAA;AAEnE,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,IAAI,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,EAAE,OAAO,CAAA;AAG9C,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAS,KAAA,EAAO;AAAA,UACjD,KAAA;AAAA,UACA,GAAA,EAAK;AAAA,SACN,CAAA;AACD,QAAA,MAAM,MAAA,GAAS,CAAC,CAAA,WAAA,EAAc,MAAA,CAAO,QAAQ,CAAA,CAAE,CAAA;AAC/C,QAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAA;AAAA,EAAmB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACjE,QAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAA;AAAA,EAAmB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACjE,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,MAChE;AAAA,MAEA,KAAK,gBAAA,EAAkB;AACrB,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,CAAA,CAAE,WAAW,CAAA;AACxC,QAAA,IAAI,CAAC,WAAA,IAAe,CAAC,WAAA,CAAY,UAAA,CAAW,GAAG,CAAA,EAAG;AAChD,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,6CAAA,EAA+C,CAAA,EAAE;AAAA,QAC5F;AACA,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,EAAM,MAAA,EAAQ,WAAW,MAAA,EAAQ,IAAA,EAAM,QAAQ,OAAO,CAAA;AAC9E,QAAA,IAAI,CAAC,cAAA,CAAe,QAAA,CAAS,MAAuC,CAAA,EAAG;AACrE,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,gCAAA,EAAmC,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA,EAAK,CAAA,EAAE;AAAA,QAC9G;AACA,QAAA,MAAM,OAAA,GAAU,OAAO,CAAA,CAAE,OAAA,KAAY,YAAY,CAAA,CAAE,OAAA,GAAU,EAAE,OAAA,GAAU,EAAA;AACzE,QAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,IAAI,IAAI,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA,GAAI,GAAA;AAEnD,QAAA,IAAI,WAAA;AACJ,QAAA,QAAQ,MAAA;AAAQ,UACd,KAAK,IAAA;AAAM,YAAA,WAAA,GAAc,OAAA,GAAU,CAAC,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA,GAAI,CAAC,MAAM,IAAI,CAAA;AAAG,YAAA;AAAA,UACzE,KAAK,MAAA;AAAQ,YAAA,WAAA,GAAc,UAAU,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,CAAC,MAAM,CAAA;AAAG,YAAA;AAAA,UACnE,KAAK,SAAA;AAAW,YAAA,WAAA,GAAc,UAAU,CAAC,SAAA,EAAW,OAAO,CAAA,GAAI,CAAC,SAAS,CAAA;AAAG,YAAA;AAAA,UAC5E,KAAK,MAAA;AAAQ,YAAA,WAAA,GAAc,OAAA,GAAU,CAAC,MAAA,EAAQ,YAAA,EAAc,UAAU,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,GAAI,CAAC,MAAA,EAAQ,YAAA,EAAc,CAAA,OAAA,EAAU,IAAI,CAAA,CAAE,CAAA;AAAG,YAAA;AAAA,UACnI,KAAK,IAAA;AAAM,YAAA,WAAA,GAAc,UAAU,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,CAAC,IAAI,CAAA;AAAG,YAAA;AAAA,UAC7D,KAAK,MAAA;AAAQ,YAAA,WAAA,GAAc,UAAU,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,CAAC,MAAM,CAAA;AAAG,YAAA;AAAA,UACnE,KAAK,OAAA;AAAS,YAAA,WAAA,GAAc,UAAU,CAAC,OAAA,EAAS,OAAO,CAAA,GAAI,CAAC,OAAO,CAAA;AAAG,YAAA;AAAA,UACtE;AAAS,YAAA,WAAA,GAAc,EAAC;AAAA;AAG1B,QAAA,MAAM,aAAa,iBAAA,CAAkB,QAAA,EAAU,CAAC,SAAA,EAAW,GAAG,WAAW,CAAC,CAAA;AAC1E,QAAA,MAAM,UAAU,CAAA,GAAA,EAAM,UAAA,CAAW,WAAW,CAAC,OAAO,UAAU,CAAA,KAAA,CAAA;AAE9D,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,IAAA,CAAK,OAAA,GAAU,OAAO,CAAA,CAAE,OAAO,IAAI,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA,GAAI,IAAA;AAC3D,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAS,KAAK,CAAA;AACjD,QAAA,MAAM,MAAA,GAAS,CAAC,CAAA,WAAA,EAAc,MAAA,CAAO,QAAQ,CAAA,UAAA,EAAa,MAAM,CAAA,EAAG,OAAA,GAAU,IAAI,OAAO,CAAA,CAAA,GAAK,EAAE,CAAA,GAAA,EAAM,WAAW,CAAA,CAAA,CAAG,CAAA;AACnH,QAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,OAAO,MAAM,CAAA;AAC5C,QAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAA;AAAA,EAAmB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACjE,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,MAChE;AAAA;AAAA,MAGA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,KAAA,GAAQ,MAAM,qBAAA,CAAsB,IAAA,EAAM,KAAK,CAAA;AACrD,QAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,8DAAA,EAAgE,CAAA,EAAE;AAAA,QAC7G;AACA,QAAA,MAAM,QAAQ,KAAA,CAAM,GAAA;AAAA,UAAI,OACtB,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,GAAA,EAAM,CAAA,CAAE,OAAO,CAAA,MAAA,EAAS,CAAA,CAAE,QAAQ,CAAA,OAAA,EAAU,EAAE,IAAI,CAAA,OAAA,EAAU,EAAE,IAAI,CAAA,CAAA,EAAI,EAAE,IAAI,CAAA;AAAA,SAC3F;AACA,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,MAC/D;AAAA,MAEA,KAAK,WAAA,EAAa;AAChB,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,GAAA,GAAM,2LAAA;AACZ,QAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,IAAA,EAAM,OAAO,CAAA,CAAE,QAAQ,CAAA,EAAG,GAAA,EAAK,KAAK,CAAA;AACvE,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,MAAA,IAAU,iBAAA,EAAmB,CAAA,EAAE;AAAA,MAC1E;AAAA,MAEA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,QAAQ,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA,CAAE,OAAA,CAAQ,kBAAkB,EAAE,CAAA;AAC1D,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,SAAS,MAAM,aAAA;AAAA,UAAc,IAAA;AAAA,UAAM,MAAA,CAAO,EAAE,QAAQ,CAAA;AAAA,UACxD,CAAA,WAAA,EAAc,KAAK,CAAA,sBAAA,EAAyB,KAAK,CAAA,EAAA,CAAA;AAAA,UAAM;AAAA,SAAK;AAC9D,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,CAAA,EAAE;AAAA,MACrD;AAAA,MAEA,KAAK,UAAA,EAAY;AACf,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAA,CAAE,KAAK,EAAE,IAAA,EAAK;AACnC,QAAA,aAAA,CAAc,KAAK,CAAA;AACnB,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,IAAA,EAAM,OAAO,CAAA,CAAE,QAAQ,CAAA,EAAG,KAAA,EAAO,KAAK,CAAA;AACzE,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,MAAA,IAAU,yCAAA,EAA2C,CAAA,EAAE;AAAA,MAClG;AAAA;AAAA,MAGA,KAAK,UAAA,EAAY;AACf,QAAA,IAAI,KAAA,GAAQ,QAAA,CACT,IAAA,CAAK,YAAY,CAAA,CACjB,MAAA,CAAO,8EAA8E,CAAA,CACrF,KAAA,CAAM,UAAU,CAAA,CAChB,KAAA,CAAM,aAAa,CAAA;AAEtB,QAAA,IAAI,EAAE,cAAA,EAAgB;AACpB,UAAA,MAAM,EAAE,UAAAsB,SAAAA,EAAS,GAAI,MAAM,6BAAA,CAA8B,MAAA,CAAO,CAAA,CAAE,cAAc,CAAC,CAAA;AACjF,UAAA,KAAA,GAAQ,KAAA,CAAM,EAAA,CAAG,0BAAA,EAA4BA,SAAQ,CAAA;AAAA,QACvD;AAEA,QAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,KAAA;AAC9B,QAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AAExC,QAAA,MAAM,QAAA,GAAA,CAAY,IAAA,IAAQ,EAAC,EACxB,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,wBAAwB,CAAA,CACrC,MAAA,CAAO,OAAO,CAAA;AACjB,QAAA,MAAM,YAAA,GAAe,MAAM,0BAAA,CAA2B,QAAQ,CAAA;AAE9D,QAAA,MAAM,SAAS,IAAA,IAAQ,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM;AACpC,UAAA,MAAM,UAAU,CAAA,CAAE,wBAAA,GACd,aAAa,CAAA,CAAE,wBAAwB,KAAK,SAAA,GAC5C,UAAA;AACJ,UAAA,OAAO,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,CAAA,EAAI,CAAA,CAAE,WAAW,CAAA,GAAA,EAAM,OAAO,CAAA,aAAA,EAAgB,CAAA,CAAE,UAAU,CAAA,CAAA,CAAA;AAAA,QAChF,CAAC,CAAA;AACD,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAI,CAAA,GAAI,+BAAA,EAAiC,CAAA,EAAE;AAAA,MAChH;AAAA,MAEA,KAAK,SAAA,EAAW;AACd,QAAA,IAAI,KAAA,GAAQ,SACT,IAAA,CAAK,YAAY,EACjB,MAAA,CAAO,8CAA8C,EACrD,EAAA,CAAG,UAAA,EAAY,OAAO,CAAA,CAAE,OAAO,CAAC,CAAA,CAChC,EAAA,CAAG,eAAe,MAAA,CAAO,CAAA,CAAE,WAAW,CAAC,CAAA;AAE1C,QAAA,IAAI,EAAE,cAAA,EAAgB;AACpB,UAAA,MAAM,EAAE,UAAS,GAAI,MAAM,8BAA8B,MAAA,CAAO,CAAA,CAAE,cAAc,CAAC,CAAA;AACjF,UAAA,KAAA,GAAQ,KAAA,CAAM,EAAA,CAAG,0BAAA,EAA4B,QAAQ,CAAA;AAAA,QACvD;AAEA,QAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,KAAA;AAE9B,QAAA,IAAI,OAAO,MAAM,IAAI,MAAM,CAAA,yBAAA,EAA4B,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AACtE,QAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAC9B,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,CAAA,CAAE,OAAO,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG,CAAA,CAAE,iBAAiB,CAAA,WAAA,EAAc,CAAA,CAAE,cAAc,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,CAAE,CAAA;AAAA,QACnI;AACA,QAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,UAAA,MAAM,QAAA,GAAW,KACd,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,wBAAwB,CAAA,CACrC,MAAA,CAAO,OAAO,CAAA;AACjB,UAAA,MAAM,YAAA,GAAe,MAAM,0BAAA,CAA2B,QAAQ,CAAA;AAC9D,UAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,IAAI,GAAA,CAAI,MAAA,CAAO,MAAA,CAAO,YAAY,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACjE,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,+BAAA,EAAkC,CAAA,CAAE,OAAO,CAAA,CAAA,EAAI,EAAE,WAAW,CAAA,kBAAA,EAAqB,KAAK,CAAA,qEAAA,EAChB,OAAO,MAAA,CAAO,YAAY,CAAA,CAAE,CAAC,KAAK,KAAK,CAAA,EAAA;AAAA,WAC/G;AAAA,QACF;AAEA,QAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,IAAA,CAAK,CAAC,EAAG,kBAAkB,CAAA;AACrD,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAW,CAAA,EAAE;AAAA,MACxD;AAAA,MAEA,KAAK,WAAA,EAAa;AAChB,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA;AAChC,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,CAAA,CAAE,WAAW,CAAA;AACxC,QAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAE,OAAO,CAAC,CAAA;AAE3C,QAAA,IAAI,gBAAA,GAAoC,IAAA;AACxC,QAAA,IAAI,EAAE,cAAA,EAAgB;AACpB,UAAA,MAAM,EAAE,UAAS,GAAI,MAAM,8BAA8B,MAAA,CAAO,CAAA,CAAE,cAAc,CAAC,CAAA;AACjF,UAAA,gBAAA,GAAmB,QAAA;AAAA,QACrB;AAEA,QAAA,IAAI,UAAA,GAAa,QAAA,CACd,IAAA,CAAK,YAAY,EACjB,MAAA,CAAO,8BAA8B,CAAA,CACrC,EAAA,CAAG,UAAA,EAAY,OAAO,CAAA,CACtB,EAAA,CAAG,eAAe,WAAW,CAAA;AAEhC,QAAA,IAAI,gBAAA,EAAkB;AACpB,UAAA,UAAA,GAAa,UAAA,CAAW,EAAA,CAAG,0BAAA,EAA4B,gBAAgB,CAAA;AAAA,QACzE;AAEA,QAAA,MAAM,EAAE,IAAA,EAAM,YAAA,EAAc,KAAA,EAAO,QAAA,KAAa,MAAM,UAAA;AACtD,QAAA,IAAI,UAAU,MAAM,IAAI,MAAM,CAAA,eAAA,EAAkB,QAAA,CAAS,OAAO,CAAA,CAAE,CAAA;AAElE,QAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,IAAK,CAAC,gBAAA,EAAkB;AAChE,UAAA,MAAM,QAAA,GAAW,aACd,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,wBAAwB,CAAA,CACrC,MAAA,CAAO,OAAO,CAAA;AACjB,UAAA,MAAM,YAAA,GAAe,MAAM,0BAAA,CAA2B,QAAQ,CAAA;AAC9D,UAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,IAAI,GAAA,CAAI,MAAA,CAAO,MAAA,CAAO,YAAY,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACjE,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,+BAAA,EAAkC,OAAO,CAAA,CAAA,EAAI,WAAW,qBAAqB,KAAK,CAAA,8CAAA;AAAA,WAEpF;AAAA,QACF;AAEA,QAAA,MAAM,QAAA,GAAW,YAAA,GAAe,CAAC,CAAA,IAAK,IAAA;AACtC,QAAA,IAAI,OAAA;AACJ,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,EAAE,OAAM,GAAI,MAAM,SACrB,IAAA,CAAK,YAAY,EACjB,MAAA,CAAO;AAAA,YACN,kBAAA,EAAoB,SAAA;AAAA,YACpB,aAAa,CAAA,CAAE,WAAA,GAAc,MAAA,CAAO,CAAA,CAAE,WAAW,CAAA,GAAI,KAAA,CAAA;AAAA,YACrD,YAAY,WAAA,CAAa,MAAA;AAAA,YACzB,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,WACpC,CAAA,CACA,EAAA,CAAG,IAAA,EAAM,SAAS,EAAE,CAAA;AACvB,UAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AACxC,UAAA,OAAA,GAAU,CAAA,oBAAA,EAAuB,OAAO,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAAA,QACzD,CAAA,MAAO;AACL,UAAA,MAAM,UAAA,GAAsC;AAAA,YAC1C,QAAA,EAAU,OAAA;AAAA,YACV,WAAA;AAAA,YACA,kBAAA,EAAoB,SAAA;AAAA,YACpB,aAAa,CAAA,CAAE,WAAA,GAAc,MAAA,CAAO,CAAA,CAAE,WAAW,CAAA,GAAI,IAAA;AAAA,YACrD,YAAY,WAAA,CAAa,MAAA;AAAA,YACzB,YAAY,WAAA,CAAa;AAAA,WAC3B;AACA,UAAA,IAAI,gBAAA,GAAmB,CAAC,CAAA,EAAG;AACzB,YAAA,UAAA,CAAW,wBAAA,GAA2B,iBAAiB,CAAC,CAAA;AAAA,UAC1D;AACA,UAAA,MAAM,EAAE,OAAM,GAAI,MAAM,SAAS,IAAA,CAAK,YAAY,CAAA,CAAE,MAAA,CAAO,UAAU,CAAA;AACrE,UAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AACxC,UAAA,OAAA,GAAU,CAAA,mBAAA,EAAsB,OAAO,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAAA,QACxD;AAEA,QAAA,MAAM,WAAA,GAAc,QAAA,EAAU,wBAAA,IAA4B,gBAAA,GAAmB,CAAC,CAAA;AAC9E,QAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,OAAA,EAAS,aAAa,WAAW,CAAA;AAC9E,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAG,OAAO,CAAA,EAAA,EAAK,YAAY,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MAC5E;AAAA;AAAA,MAGA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,QAAA,MAAM,MAAA,GAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CA8ErB,IAAA,EAAK;AACC,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,QAAQ,KAAK,CAAA;AAChD,QAAA,MAAM,MAAA,GAAA,CAAU,MAAA,CAAO,MAAA,IAAU,EAAA,EAAI,IAAA,EAAK;AAC1C,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,MAAA,IAAU,mCAAA,EAAqC,CAAA,EAAE;AAAA,MAC5F;AAAA;AAAA,MAGA,KAAK,aAAA,EAAe;AAUlB,QAAA,MAAM,GAAA,GAAM,MAAM,aAAA,CAA6C,UAAU,CAAA;AACzE,QAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,OAAA;AAEzB,QAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,UAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,kBAAA,EAAoB,CAAA,EAAE;AAAA,QACjE;AAEA,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK;AAC7B,UAAA,MAAM,IAAA,GAAO,CAAA,CAAE,IAAA,EAAM,MAAA,GAAS,CAAA,EAAA,EAAK,EAAE,IAAA,CAAK,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA,GAAM,EAAA;AAC1D,UAAA,OAAO,CAAA,EAAG,CAAA,CAAE,MAAM,CAAA,SAAA,EAAY,CAAA,CAAE,MAAM,CAAA,UAAA,EAAa,CAAA,CAAE,YAAY,CAAA,EAAG,IAAI,CAAA,CAAA;AAAA,QAC1E,CAAC,CAAA;AAED,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA;;AAAA,EAAkB,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACpG;AAAA,MAEA,KAAK,UAAA,EAAY;AACf,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAIjD,QAAA,MAAM,MAAM,MAAM,aAAA;AAAA,UAChB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA;AAAA,SACxC;AACA,QAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,OAAA;AAEzB,QAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,UAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,yBAAA,EAA4B,MAAM,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,QACnF;AAEA,QAAA,MAAM,MAAA,GAAS,uFAAA;AACf,QAAA,MAAM,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA;AACzB,QAAA,MAAM,QAAQ,OAAA,CAAQ,GAAA;AAAA,UAAI,CAAA,CAAA,KACxB,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,MAAA,CAAO,EAAE,CAAC,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,MAAA,CAAO,EAAE,CAAC,CAAA,EAAG,CAAA,CAAE,KAAA,CAAM,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAA,EAAG,CAAA,CAAE,GAAG,CAAA;AAAA,SACxF;AAEA,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,gBAAA,EAAmB,MAAM,CAAA,EAAA,EAAK,OAAA,CAAQ,MAAM,CAAA;;AAAA,EAAS,MAAM;AAAA,EAAK,GAAG;AAAA,EAAK,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACzI;AAAA,MAEA,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAA,CAAE,IAAI,EAAE,WAAA,EAAY;AACxC,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA;AAC7B,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA;AAC5B,QAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,GAAG,CAAA,IAAK,IAAA;AAE7B,QAAA,IAAI,CAAC,MAAA,IAAU,CAAC,QAAQ,CAAC,OAAA,IAAW,CAAC,KAAA,EAAO;AAC1C,UAAA,MAAM,IAAI,MAAM,4CAA4C,CAAA;AAAA,QAC9D;AAIA,QAAA,MAAM,UAAU,MAAM,aAAA;AAAA,UACpB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA;AAAA,SACxC;AAEA,QAAA,MAAM,OAAA,GAAU,CAAC,GAAG,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,EAAE,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,GAAA,EAAK,CAAA;AAE7E,QAAA,MAAM,aAAA,CAAoB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA,CAAA,EAAQ;AAAA,UACtE,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,SAAS;AAAA,SACjC,CAAA;AAED,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,oBAAA,EAAuB,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,QAAA,EAAM,KAAK,UAAU,GAAG,CAAA,CAAA,CAAA,EAAK,CAAA,EAAE;AAAA,MAChH;AAAA,MAEA,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAA,CAAE,IAAI,EAAE,WAAA,EAAY;AACxC,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA;AAC7B,QAAA,MAAM,QAAA,GAAW,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAA;AAClC,QAAA,MAAM,QAAA,GAAW,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAA;AAClC,QAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,GAAG,CAAA,IAAK,KAAA,CAAA;AAE7B,QAAA,IAAI,CAAC,UAAU,CAAC,IAAA,IAAQ,CAAC,OAAA,IAAW,CAAC,QAAA,IAAY,CAAC,QAAA,EAAU;AAC1D,UAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,QAC3E;AAIA,QAAA,MAAM,UAAU,MAAM,aAAA;AAAA,UACpB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA;AAAA,SACxC;AAEA,QAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,SAAA;AAAA,UAC/B,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,IAAA,IAAQ,EAAE,IAAA,KAAS,OAAA,IAAW,EAAE,KAAA,KAAU;AAAA,SAC5D;AAEA,QAAA,IAAI,QAAQ,CAAA,CAAA,EAAI;AACd,UAAA,MAAM,IAAI,MAAM,CAAA,8BAAA,EAAiC,IAAI,IAAI,OAAO,CAAA,GAAA,EAAM,QAAQ,CAAA,CAAE,CAAA;AAAA,QAClF;AAEA,QAAA,MAAM,OAAA,GAAU,CAAC,GAAG,OAAA,CAAQ,KAAK,OAAO,CAAA;AACxC,QAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,GAAG,CAAA,CAAG,GAAA;AAClC,QAAA,OAAA,CAAQ,GAAG,CAAA,GAAI;AAAA,UACb,IAAA;AAAA,UACA,IAAA,EAAM,OAAA;AAAA,UACN,KAAA,EAAO,QAAA;AAAA,UACP,KAAK,GAAA,IAAO;AAAA,SACd;AAEA,QAAA,MAAM,aAAA,CAAoB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA,CAAA,EAAQ;AAAA,UACtE,MAAA,EAAQ,KAAA;AAAA,UACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAA,EAAS,SAAS;AAAA,SAC1C,CAAA;AAED,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,uBAAuB,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,QAAA,EAAM,QAAQ,GAAG,GAAA,GAAM,CAAA,OAAA,EAAU,GAAG,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MACnI;AAAA,MAEA,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAA,CAAE,IAAI,EAAE,WAAA,EAAY;AACxC,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA;AAC7B,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA;AAE5B,QAAA,IAAI,CAAC,MAAA,IAAU,CAAC,QAAQ,CAAC,OAAA,IAAW,CAAC,KAAA,EAAO;AAC1C,UAAA,MAAM,IAAI,MAAM,4CAA4C,CAAA;AAAA,QAC9D;AAIA,QAAA,MAAM,UAAU,MAAM,aAAA;AAAA,UACpB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA;AAAA,SACxC;AAEA,QAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,MAAA;AACpC,QAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,MAAA;AAAA,UACrC,CAAA,CAAA,KAAK,EAAE,CAAA,CAAE,IAAA,KAAS,QAAQ,CAAA,CAAE,IAAA,KAAS,OAAA,IAAW,CAAA,CAAE,KAAA,KAAU,KAAA;AAAA,SAC9D;AAEA,QAAA,IAAI,SAAA,CAAU,WAAW,MAAA,EAAQ;AAC/B,UAAA,MAAM,IAAI,MAAM,CAAA,8BAAA,EAAiC,IAAI,IAAI,OAAO,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,CAAA;AAAA,QAC/E;AAEA,QAAA,MAAM,aAAA,CAAoB,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,IAAA,CAAA,EAAQ;AAAA,UACtE,MAAA,EAAQ,KAAA;AAAA,UACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAA,EAAS,WAAW;AAAA,SAC5C,CAAA;AAED,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAA,oBAAA,EAAuB,IAAI,CAAA,CAAA,EAAI,OAAO,MAAM,KAAK,CAAA,EAAA,EAAK,UAAU,MAAM,CAAA,mBAAA,CAAA,EAAuB,CAAA,EAAE;AAAA,MAC1I;AAAA,MAEA;AACE,QAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,IAAI,CAAA,EAAG;AAChC,UAAA,OAAO,kBAAkB,IAAA,EAAM,CAAA,EAAG,EAAE,OAAA,EAAS,qBAAqB,CAAA;AAAA,QACpE;AACA,QAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA,EAAG;AAC9B,UAAA,OAAO,eAAA,CAAgB,MAAM,CAAC,CAAA;AAAA,QAChC;AACA,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA;AACxE,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,IAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,EAClE;AACF;AAGA,SAAS,eAAA,GAA0B;AACjC,EAAA,MAAM,IAAI,IAAIC,MAAAA;AAAA,IACZ,EAAE,IAAA,EAAM,kBAAA,EAAoB,OAAA,EAAS,WAAA,EAAY;AAAA,IACjD,EAAE,YAAA,EAAc,EAAE,KAAA,EAAO,IAAG;AAAE,GAChC;AACA,EAAA,CAAA,CAAE,iBAAA,CAAkBC,wBAAwB,eAAe,CAAA;AAC3D,EAAA,CAAA,CAAE,iBAAA,CAAkBC,uBAAuB,cAA2D,CAAA;AACtG,EAAA,OAAO,CAAA;AACT;AAEA,IAAM,SAAS,eAAA,EAAgB;AAM/B,eAAe,IAAA,GAAO;AACpB,EAAA,OAAA,CAAQ,MAAM,qCAAqC,CAAA;AAEnD,EAAA,MAAM,cAAA,GAAiB,MAAM,cAAA,CAAe,MAAO,CAAA;AACnD,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAA,OAAA,CAAQ,MAAM,2BAA2B,CAAA;AACzC,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,WAAA,GAAc,MAAM,cAAA,CAAe,UAAA,EAAa,cAAA,CAAe,QAAQ,CAAA;AACvE,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAA,CAAQ,MAAM,+BAA+B,CAAA;AAC7C,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,MAAM,CAAA,gBAAA,EAAmB,WAAW,CAAA,QAAA,EAAW,WAAA,CAAY,UAAU,CAAA,CAAE,CAAA;AAE/E,EAAA,MAAM,SAAA,GAAY,MAAM,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAI,CAAA,CAAE,KAAK,IAAI,CAAA;AAElD,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,8DAAA,EAAiE,QAAQ,CAAA,GAAA,CAAK,CAAA;AAE5F,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAA2C;AAElE,IAAA,MAAM,aAAA,GAAwC;AAAA,MAC5C,iBAAA,EAAmB,YAAA;AAAA,MACnB,gBAAA,EAAkB;AAAA,KACpB;AAEA,IAAA,MAAM,UAAA,GAAaC,YAAA,CAAiB,OAAO,GAAA,EAAK,GAAA,KAAQ;AACtD,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,GAAA,CAAI,OAAO,GAAA,EAAK,CAAA,iBAAA,EAAoB,QAAQ,CAAA,CAAE,CAAA;AAGlE,MAAA,MAAM,YAAA,GAAe,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA;AAC/C,MAAA,IAAI,YAAA,IAAgB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACzC,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,mBAAA,EAAqB,CAAC,CAAA;AACtD,UAAA;AAAA,QACF;AACA,QAAA,MAAM,cAAA,GAAiB,gBAAgB,YAAY,CAAA;AACnD,QAAA,IAAI,kBAAkB,WAAA,CAAY,WAAA,CAAY,OAAA,CAAQ,cAAc,MAAM,IAAA,EAAM;AAC9E,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,EAAE,OAAO,CAAA,kCAAA,EAAqC,cAAc,CAAA,QAAA,CAAA,EAAY,CAAC,CAAA;AAChG,UAAA;AAAA,QACF;AACA,QAAA,MAAM,SAAmB,EAAC;AAC1B,QAAA,WAAA,MAAiB,KAAA,IAAS,GAAA,EAAK,MAAA,CAAO,IAAA,CAAK,KAAe,CAAA;AAC1D,QAAA,IAAI,QAAA;AACJ,QAAA,IAAI;AACF,UAAA,QAAA,GAAW,KAAK,KAAA,CAAM,MAAA,CAAO,OAAO,MAAM,CAAA,CAAE,UAAU,CAAA;AAAA,QACxD,CAAA,CAAA,MAAQ;AACN,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAC,CAAA;AACjD,UAAA;AAAA,QACF;AACA,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,YAAA,EAAc,QAAQ,CAAA;AAC3D,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,EAAE,IAAI,IAAA,EAAM,MAAA,EAAQ,CAAC,CAAA;AAAA,QAC9C,SAAS,GAAA,EAAK;AACZ,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAA,EAAG,CAAC,CAAA;AAAA,QACrF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,GAAA,CAAI,QAAA,KAAa,YAAA,IAAgB,GAAA,CAAI,WAAW,KAAA,EAAO;AACzD,QAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,QAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,OAAO,IAAA,CAAK,aAAa,CAAA,EAAG,CAAC,CAAA;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,GAAA,CAAI,aAAa,MAAA,EAAQ;AAC3B,QAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,cAAc,CAAA;AACnD,QAAA,GAAA,CAAI,IAAI,WAAW,CAAA;AACnB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,QAAA,GAAA,CAAI,UAAU,GAAA,EAAK;AAAA,UACjB,6BAAA,EAA+B,GAAA;AAAA,UAC/B,8BAAA,EAAgC,4BAAA;AAAA,UAChC,8BAAA,EAAgC,8BAAA;AAAA,UAChC,+BAAA,EAAiC;AAAA,SAClC,CAAA;AACD,QAAA,GAAA,CAAI,GAAA,EAAI;AACR,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,SAAA,CAAU,+BAA+B,GAAG,CAAA;AAChD,MAAA,GAAA,CAAI,SAAA,CAAU,iCAAiC,gBAAgB,CAAA;AAE/D,MAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,CAAQ,gBAAgB,CAAA;AAE9C,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI,GAAA,CAAI,WAAW,MAAA,EAAQ;AACzB,QAAA,MAAM,SAAmB,EAAC;AAC1B,QAAA,WAAA,MAAiB,KAAA,IAAS,GAAA,EAAK,MAAA,CAAO,IAAA,CAAK,KAAe,CAAA;AAC1D,QAAA,IAAI;AACF,UAAA,IAAA,GAAO,KAAK,KAAA,CAAM,MAAA,CAAO,OAAO,MAAM,CAAA,CAAE,UAAU,CAAA;AAAA,QACpD,CAAA,CAAA,MAAQ;AACN,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,cAAc,CAAA;AACnD,UAAA,GAAA,CAAI,IAAI,cAAc,CAAA;AACtB,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,SAAA,IAAa,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA,EAAG;AAC1C,QAAA,MAAM,WAAW,GAAA,CAAI,SAAS,EAAG,aAAA,CAAc,GAAA,EAAK,KAAK,IAAI,CAAA;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,GAAA,CAAI,MAAA,KAAW,MAAA,IAAU,IAAA,KAAS,MAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,mBAAmB,CAAA,GAAI,mBAAA,CAAoB,IAAI,CAAA,CAAA,EAAI;AACvH,QAAA,MAAM,SAAA,GAAY,IAAI,6BAAA,CAA8B;AAAA,UAClD,kBAAA,EAAoB,MAAM,UAAA;AAAW,SACtC,CAAA;AACD,QAAA,SAAA,CAAU,UAAU,MAAM;AACxB,UAAA,IAAI,SAAA,CAAU,SAAA,EAAW,UAAA,CAAW,MAAA,CAAO,UAAU,SAAS,CAAA;AAAA,QAChE,CAAA;AACA,QAAA,MAAM,gBAAgB,eAAA,EAAgB;AACtC,QAAA,MAAM,aAAA,CAAc,QAAQ,SAAS,CAAA;AACrC,QAAA,IAAI,UAAU,SAAA,EAAW,UAAA,CAAW,GAAA,CAAI,SAAA,CAAU,WAAW,SAAS,CAAA;AACtE,QAAA,MAAM,SAAA,CAAU,aAAA,CAAc,GAAA,EAAK,GAAA,EAAK,IAAI,CAAA;AAC5C,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,cAAc,CAAA;AACnD,MAAA,GAAA,CAAI,IAAI,+CAA0C,CAAA;AAAA,IACpD,CAAC,CAAA;AAED,IAAA,UAAA,CAAW,MAAA,CAAO,UAAU,MAAM;AAChC,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,8BAAA,EAAiC,QAAQ,CAAA,SAAA,EAAY,SAAS,CAAA,CAAE,CAAA;AAAA,IAChF,CAAC,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,MAAM,gDAAgD,CAAA;AAC9D,IAAA,MAAM,SAAA,GAAY,IAAIC,oBAAAA,EAAqB;AAC3C,IAAA,MAAM,MAAA,CAAO,QAAQ,SAAS,CAAA;AAC9B,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,yBAAA,EAA4B,SAAS,CAAA,CAAE,CAAA;AAAA,EACvD;AACF;AAEA,IAAA,EAAK,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AACpB,EAAA,OAAA,CAAQ,KAAA,CAAM,gBAAgB,GAAG,CAAA;AACjC,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB,CAAC,CAAA","file":"index.js","sourcesContent":["/**\r\n * Proxy-mode entry point for the MG dashboard MCP package.\r\n *\r\n * Usage:\r\n * npx @mgsoftwarebv/mg-dashboard-mcp \\\r\n * --proxy-url=https://mg-mcp.mgsoftware.nl/v1/{INSTANCE_ID}/mcp \\\r\n * --api-key=pk_xxx \\\r\n * --ssh-key=$HOME/.ssh/id_ed25519\r\n *\r\n * What it does:\r\n * 1. At startup it does an SSH-key challenge handshake against the proxy\r\n * (POST /v1/auth/ssh/challenge → ssh-keygen -Y sign → POST\r\n * /v1/auth/ssh/verify) and obtains a short-lived `pks_xxx` bearer.\r\n * 2. It then runs as a stdio MCP server, transparently forwarding every\r\n * JSON-RPC message to/from the upstream proxy URL using\r\n * `StreamableHTTPClientTransport` with the bearer attached.\r\n * 3. Before the token expires it re-runs the handshake and swaps in the\r\n * fresh bearer without dropping the connection.\r\n *\r\n * This lets a user point Cursor's mcp.json at the local stdio command with\r\n * both factors: a static `pk_` proxy key plus a linked SSH key proof. The\r\n * static key is only sent during the SSH verify step; normal MCP traffic uses\r\n * the short-lived `pks_` session token.\r\n */\r\n\r\nimport { spawn } from \"node:child_process\";\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\r\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\r\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\r\nimport {\r\n CallToolRequestSchema,\r\n CallToolResultSchema,\r\n EmptyResultSchema,\r\n GetPromptRequestSchema,\r\n GetPromptResultSchema,\r\n ListPromptsRequestSchema,\r\n ListPromptsResultSchema,\r\n ListResourcesRequestSchema,\r\n ListResourcesResultSchema,\r\n ListResourceTemplatesRequestSchema,\r\n ListResourceTemplatesResultSchema,\r\n ListToolsRequestSchema,\r\n ListToolsResultSchema,\r\n ReadResourceRequestSchema,\r\n ReadResourceResultSchema,\r\n SubscribeRequestSchema,\r\n UnsubscribeRequestSchema,\r\n} from \"@modelcontextprotocol/sdk/types.js\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// CLI helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction getArg(args: string[], name: string): string | undefined {\r\n return args.find((a) => a.startsWith(`--${name}=`))?.split(\"=\").slice(1).join(\"=\");\r\n}\r\n\r\nfunction expandHome(path: string): string {\r\n if (!path.startsWith(\"~\")) return path;\r\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\r\n return join(home, path.slice(1));\r\n}\r\n\r\nfunction resolvePubkeyPath(input: string): { pubPath: string; pubText: string } {\r\n const candidate = expandHome(input);\r\n let pubPath: string;\r\n if (candidate.endsWith(\".pub\")) {\r\n pubPath = candidate;\r\n } else if (existsSync(`${candidate}.pub`)) {\r\n pubPath = `${candidate}.pub`;\r\n } else if (existsSync(candidate)) {\r\n pubPath = candidate;\r\n } else {\r\n throw new Error(`SSH key file not found: ${candidate} (also tried ${candidate}.pub)`);\r\n }\r\n const pubText = readFileSync(pubPath, \"utf8\").trim();\r\n if (!pubText) throw new Error(`SSH public-key file is empty: ${pubPath}`);\r\n return { pubPath, pubText };\r\n}\r\n\r\nfunction runProcess(\r\n command: string,\r\n argv: string[],\r\n options: { stdin?: string } = {},\r\n): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve) => {\r\n const child = spawn(command, argv, { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n child.stdout.on(\"data\", (d) => {\r\n stdout += d.toString();\r\n });\r\n child.stderr.on(\"data\", (d) => {\r\n stderr += d.toString();\r\n });\r\n child.on(\"error\", (err) => {\r\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\r\n });\r\n child.on(\"close\", (code) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n if (options.stdin !== undefined) {\r\n child.stdin.write(options.stdin);\r\n child.stdin.end();\r\n } else {\r\n child.stdin.end();\r\n }\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH-key handshake against /v1/auth/ssh/challenge + /v1/auth/ssh/verify\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface HandshakeResult {\r\n token: string;\r\n expiresAt: number; // ms epoch\r\n proxyKeyName: string;\r\n}\r\n\r\nfunction deriveAuthBaseUrl(proxyUrl: string): string {\r\n // proxyUrl looks like https://host/v1/{instanceId}/mcp\r\n // We need to call https://host (base) then /v1/auth/ssh/{challenge|verify}.\r\n const u = new URL(proxyUrl);\r\n return `${u.protocol}//${u.host}`;\r\n}\r\n\r\nasync function performHandshake(\r\n proxyUrl: string,\r\n apiKey: string,\r\n pubPath: string,\r\n pubText: string,\r\n): Promise<HandshakeResult> {\r\n const base = deriveAuthBaseUrl(proxyUrl);\r\n\r\n const challengeRes = await fetch(`${base}/v1/auth/ssh/challenge`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: \"{}\",\r\n });\r\n if (!challengeRes.ok) {\r\n const txt = await challengeRes.text().catch(() => \"\");\r\n throw new Error(`Challenge request failed (${challengeRes.status}): ${txt}`);\r\n }\r\n const challenge = (await challengeRes.json()) as {\r\n challenge_id: string;\r\n nonce: string;\r\n namespace: string;\r\n };\r\n\r\n const sign = await runProcess(\r\n \"ssh-keygen\",\r\n [\"-Y\", \"sign\", \"-f\", pubPath, \"-n\", challenge.namespace, \"-q\"],\r\n { stdin: challenge.nonce },\r\n );\r\n if (sign.code !== 0 || !sign.stdout.includes(\"BEGIN SSH SIGNATURE\")) {\r\n throw new Error(\r\n `ssh-keygen sign failed (exit ${sign.code}). Make sure ssh-agent is running ` +\r\n `and has the matching private key loaded. stderr: ${sign.stderr.trim() || \"(empty)\"}`,\r\n );\r\n }\r\n\r\n const verifyRes = await fetch(`${base}/v1/auth/ssh/verify`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n challenge_id: challenge.challenge_id,\r\n api_key: apiKey,\r\n pubkey: pubText,\r\n signature: sign.stdout,\r\n }),\r\n });\r\n if (!verifyRes.ok) {\r\n const txt = await verifyRes.text().catch(() => \"\");\r\n throw new Error(`Verify request failed (${verifyRes.status}): ${txt}`);\r\n }\r\n const verified = (await verifyRes.json()) as {\r\n token: string;\r\n expires_in_seconds: number;\r\n proxy_key_name: string;\r\n };\r\n\r\n return {\r\n token: verified.token,\r\n expiresAt: Date.now() + verified.expires_in_seconds * 1000,\r\n proxyKeyName: verified.proxy_key_name,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Bidirectional message forwarding\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Bridge between a stdio MCP server (talking to e.g. Cursor) and a remote\r\n * Streamable-HTTP MCP server (the proxy). Each incoming JSON-RPC message\r\n * is forwarded verbatim, and responses / notifications stream back.\r\n */\r\nasync function runBridge(handshake: HandshakeResult, proxyUrl: string, refresh: () => Promise<HandshakeResult>) {\r\n let currentToken = handshake.token;\r\n const requestHeaders: Record<string, string> = {\r\n Authorization: `Bearer ${currentToken}`,\r\n };\r\n\r\n const upstreamTransport = new StreamableHTTPClientTransport(new URL(proxyUrl), {\r\n requestInit: { headers: requestHeaders },\r\n });\r\n const upstream = new Client({ name: \"mg-dashboard-mcp-proxy-bridge\", version: \"1.0.0\" });\r\n\r\n // Schedule a refresh 2 minutes before expiry.\r\n const scheduleRefresh = (result: HandshakeResult) => {\r\n const msUntilRefresh = Math.max(30_000, result.expiresAt - Date.now() - 120_000);\r\n setTimeout(async () => {\r\n try {\r\n const fresh = await refresh();\r\n currentToken = fresh.token;\r\n requestHeaders.Authorization = `Bearer ${currentToken}`;\r\n console.error(`[Proxy] Token refreshed (key: ${fresh.proxyKeyName})`);\r\n scheduleRefresh(fresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Token refresh failed: ${err instanceof Error ? err.message : String(err)}`);\r\n // Try again sooner on failure.\r\n setTimeout(() => scheduleRefresh({ ...result, expiresAt: Date.now() + 60_000 }), 30_000);\r\n }\r\n }, msUntilRefresh).unref();\r\n };\r\n scheduleRefresh(handshake);\r\n\r\n // Server-side stdio transport faces Cursor.\r\n const stdioServer = new Server(\r\n { name: \"mg-dashboard-mcp-proxy\", version: \"1.0.0\" },\r\n { capabilities: { tools: {}, prompts: {}, resources: {}, logging: {} } },\r\n );\r\n\r\n const forwardRequest =\r\n (resultSchema: Parameters<typeof upstream.request>[1]) =>\r\n async (request: unknown) =>\r\n upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n resultSchema,\r\n );\r\n\r\n // Explicitly forward first-class MCP methods. The SDK fallback only covers\r\n // truly unknown methods; Cursor's standard discovery calls need registered\r\n // handlers or the client sees an empty server.\r\n stdioServer.setRequestHandler(\r\n ListToolsRequestSchema,\r\n forwardRequest(ListToolsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n CallToolRequestSchema,\r\n forwardRequest(CallToolResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListPromptsRequestSchema,\r\n forwardRequest(ListPromptsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n GetPromptRequestSchema,\r\n forwardRequest(GetPromptResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourcesRequestSchema,\r\n forwardRequest(ListResourcesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ReadResourceRequestSchema,\r\n forwardRequest(ReadResourceResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourceTemplatesRequestSchema,\r\n forwardRequest(ListResourceTemplatesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n SubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n UnsubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n\r\n // Dumb forwarder: any request from Cursor → forward to upstream → return result.\r\n stdioServer.fallbackRequestHandler = async (request: unknown) => {\r\n return await upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n // We don't care about the schema check on the way through — let the\r\n // upstream's actual response flow back unmodified.\r\n undefined as unknown as Parameters<typeof upstream.request>[1],\r\n );\r\n };\r\n // Same for notifications.\r\n stdioServer.fallbackNotificationHandler = async (notification: unknown) => {\r\n await upstream.notification(notification as Parameters<typeof upstream.notification>[0]);\r\n };\r\n\r\n await upstream.connect(upstreamTransport);\r\n\r\n // Forward upstream notifications back to Cursor.\r\n upstream.fallbackNotificationHandler = async (notification: unknown) => {\r\n await stdioServer.notification(notification as Parameters<typeof stdioServer.notification>[0]);\r\n };\r\n\r\n await stdioServer.connect(new StdioServerTransport());\r\n console.error(`[Proxy] Bridge ready. Forwarding stdio → ${proxyUrl}`);\r\n\r\n // In proxy mode this function is the long-lived process. Some SDK transports\r\n // finish their async `connect()` setup without leaving an obvious foreground\r\n // handle behind, which can make Node exit immediately after \"Bridge ready\".\r\n // Keep the process alive until Cursor closes stdin or the process receives a\r\n // termination signal.\r\n await new Promise<void>((resolve) => {\r\n const keepAlive = setInterval(() => undefined, 2_147_483_647);\r\n const done = () => {\r\n clearInterval(keepAlive);\r\n resolve();\r\n };\r\n process.stdin.once(\"close\", done);\r\n process.stdin.once(\"end\", done);\r\n process.once(\"SIGINT\", done);\r\n process.once(\"SIGTERM\", done);\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public entry point\r\n// ---------------------------------------------------------------------------\r\n\r\nexport async function runProxyMode(args: string[]): Promise<void> {\r\n const proxyUrl = getArg(args, \"proxy-url\") || process.env.MG_DASHBOARD_PROXY_URL;\r\n const apiKey = getArg(args, \"api-key\") || process.env.MG_DASHBOARD_API_KEY;\r\n const sshKey = getArg(args, \"ssh-key\") || process.env.MG_DASHBOARD_SSH_KEY;\r\n\r\n if (!proxyUrl) {\r\n console.error(\"--proxy-url is required (or set MG_DASHBOARD_PROXY_URL)\");\r\n process.exit(1);\r\n }\r\n if (!apiKey) {\r\n console.error(\"--api-key is required in proxy mode (or set MG_DASHBOARD_API_KEY)\");\r\n process.exit(1);\r\n }\r\n if (!sshKey) {\r\n console.error(\"--ssh-key is required in proxy mode (or set MG_DASHBOARD_SSH_KEY)\");\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Starting in proxy-bridge mode → ${proxyUrl}`);\r\n\r\n let resolved: { pubPath: string; pubText: string };\r\n try {\r\n resolved = resolvePubkeyPath(sshKey);\r\n } catch (err) {\r\n console.error(`[Proxy] ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n const refresh = () => performHandshake(proxyUrl, apiKey, resolved.pubPath, resolved.pubText);\r\n\r\n let handshake: HandshakeResult;\r\n try {\r\n handshake = await refresh();\r\n } catch (err) {\r\n console.error(`[Proxy] Handshake failed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Authenticated as \"${handshake.proxyKeyName}\"`);\r\n console.error(`[Proxy] Token valid for ${Math.floor((handshake.expiresAt - Date.now()) / 60000)} min`);\r\n\r\n try {\r\n await runBridge(handshake, proxyUrl, refresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Bridge crashed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * Trigger.dev MCP Tools\r\n *\r\n * SSH-based tools for managing Trigger.dev projects. All projects run on a\r\n * single Docker Compose instance. The compose project, server, postgres\r\n * container, and webapp port are auto-discovered — callers only need to\r\n * provide the Trigger.dev project slug (from trigger-list).\r\n *\r\n * @module trigger-tools\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types (mirrored from index.ts to avoid circular imports)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface SshConnectionOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\ninterface SshResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n}\r\n\r\ntype SshExecFn = (\r\n conn: SshConnectionOptions,\r\n command: string,\r\n proxy?: SshConnectionOptions,\r\n) => Promise<SshResult>;\r\n\r\ntype GetServerConnectionFn = (\r\n serverId: string,\r\n) => Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions }>;\r\n\r\ninterface ToolResult {\r\n [key: string]: unknown;\r\n content: { type: string; text: string }[];\r\n}\r\n\r\ninterface TriggerToolDeps {\r\n sshExec: SshExecFn;\r\n getServerConnection: GetServerConnectionFn;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Trigger.dev API response shapes (partial, only fields we display)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerRunItem {\r\n id: string;\r\n status: string;\r\n taskIdentifier: string;\r\n version?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n startedAt?: string;\r\n finishedAt?: string;\r\n durationMs?: number;\r\n isTest?: boolean;\r\n}\r\n\r\ninterface TriggerRunDetail extends TriggerRunItem {\r\n payload?: unknown;\r\n output?: unknown;\r\n attempts?: {\r\n id: string;\r\n status: string;\r\n error?: { message: string; name?: string; stackTrace?: string };\r\n startedAt?: string;\r\n completedAt?: string;\r\n }[];\r\n}\r\n\r\nconst TERMINAL_STATUSES = new Set([\r\n 'COMPLETED', 'FAILED', 'CRASHED', 'CANCELED',\r\n 'SYSTEM_FAILURE', 'INTERRUPTED', 'EXPIRED',\r\n]);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Hardcoded infra constants — single Trigger.dev instance\r\n// ---------------------------------------------------------------------------\r\n\r\n/** SSH server that hosts the Trigger.dev Docker Compose stack. */\r\nconst TRIGGER_SERVER_ID = '03659d55-e194-400d-b82a-bf6457371ded';\r\n\r\n/** Docker Compose project name on the server. */\r\nconst COMPOSE_PROJECT = 'mg-dashboard-supabase-trigger';\r\n\r\nconst PG_CONTAINER = `${COMPOSE_PROJECT}-postgres-1`;\r\nconst WA_CONTAINER = `${COMPOSE_PROJECT}-webapp-1`;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\n/** MCP tool definitions for Trigger.dev (list projects, runs, details, test, replay). */\r\nexport const TRIGGER_TOOLS = [\r\n {\r\n name: 'trigger-list',\r\n description:\r\n 'List all Trigger.dev projects. Returns the project slug and name. ' +\r\n 'Use the slug as the \"project\" parameter in other trigger-* tools.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {},\r\n },\r\n },\r\n {\r\n name: 'trigger-runs',\r\n description:\r\n 'List recent task runs for a Trigger.dev project. ' +\r\n 'Returns run ID, task name, status, duration, and timestamps.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list (e.g. \"mg-dashboard-bHfS\")' },\r\n status: {\r\n type: 'string',\r\n description: 'Comma-separated status filter: QUEUED,EXECUTING,COMPLETED,FAILED,CRASHED,CANCELED,SYSTEM_FAILURE',\r\n },\r\n taskIdentifier: { type: 'string', description: 'Filter by task identifier (e.g. \"hello-world\")' },\r\n limit: { type: 'number', description: 'Max runs to return (default 20, max 100)' },\r\n },\r\n required: ['project'],\r\n },\r\n },\r\n {\r\n name: 'trigger-run-detail',\r\n description:\r\n 'Get full details of a specific run: status, payload, output, and error stack traces. ' +\r\n 'Use after trigger-runs or trigger-test-task to inspect results.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list' },\r\n runId: { type: 'string', description: 'Run ID (e.g. run_xxxxx)' },\r\n },\r\n required: ['project', 'runId'],\r\n },\r\n },\r\n {\r\n name: 'trigger-test-task',\r\n description:\r\n 'Trigger a task run and wait for it to complete. Returns the final status, output, ' +\r\n 'or error with stack trace. The main tool for testing trigger tasks from Cursor.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list' },\r\n taskId: { type: 'string', description: 'Task identifier (e.g. \"hello-world\", \"execute-pipeline\")' },\r\n payload: { type: 'string', description: 'JSON payload string to pass to the task (optional)' },\r\n waitSeconds: { type: 'number', description: 'Max seconds to wait for completion (default 60, max 300)' },\r\n },\r\n required: ['project', 'taskId'],\r\n },\r\n },\r\n {\r\n name: 'trigger-replay-run',\r\n description: 'Replay a previously failed or completed run with the same payload. Returns the new run ID.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list' },\r\n runId: { type: 'string', description: 'Run ID to replay (e.g. run_xxxxx)' },\r\n },\r\n required: ['project', 'runId'],\r\n },\r\n },\r\n];\r\n\r\n/** Set of Trigger.dev MCP tool names for fast membership checks in the main server switch. */\r\nexport const TRIGGER_TOOL_NAMES = new Set(TRIGGER_TOOLS.map((t) => t.name));\r\n\r\n/** Maps each Trigger.dev tool name to the dashboard module key required to use it (`ci_cd`). */\r\nexport const TRIGGER_TOOL_MODULE_MAP: Record<string, string> = {\r\n 'trigger-list': 'ci_cd',\r\n 'trigger-runs': 'ci_cd',\r\n 'trigger-run-detail': 'ci_cd',\r\n 'trigger-test-task': 'ci_cd',\r\n 'trigger-replay-run': 'ci_cd',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerInstance {\r\n port: string;\r\n apiKey: string;\r\n}\r\n\r\n/**\r\n * Discover the webapp port and the production API key for a specific\r\n * Trigger.dev project by querying Docker and the Postgres container.\r\n * The API key is resolved via a JOIN on Project → RuntimeEnvironment.\r\n */\r\nasync function discoverInstance(\r\n projectSlug: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<TriggerInstance> {\r\n const sql = `SELECT re.\\\\\"apiKey\\\\\" FROM \\\\\"RuntimeEnvironment\\\\\" re `\r\n + `JOIN \\\\\"Project\\\\\" p ON re.\\\\\"projectId\\\\\" = p.id `\r\n + `WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;\r\n\r\n const cmd = [\r\n `PORT=$(docker port \"${WA_CONTAINER}\" 3000/tcp 2>/dev/null | head -1 | sed 's/.*://')`,\r\n `KEY=$(docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null | tr -d '[:space:]')`,\r\n 'echo \"$PORT|$KEY\"',\r\n ].join(' && ');\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n const sepIdx = output.indexOf('|');\r\n\r\n const port = sepIdx > 0 ? output.substring(0, sepIdx) : '';\r\n const apiKey = sepIdx > 0 ? output.substring(sepIdx + 1) : '';\r\n\r\n if (!port) {\r\n throw new Error(\r\n `Could not find webapp port for ${WA_CONTAINER}. Is the container running?`,\r\n );\r\n }\r\n if (!apiKey) {\r\n throw new Error(\r\n `Could not get API key for project \"${projectSlug}\". ` +\r\n 'Check if the project slug is correct (use trigger-list).',\r\n );\r\n }\r\n\r\n return { port, apiKey };\r\n}\r\n\r\n/**\r\n * Fetch console/logger output for a run from the TaskEvent table in Postgres.\r\n * Returns formatted log lines sorted by time, filtered to user-relevant levels.\r\n */\r\nasync function fetchRunLogs(\r\n runId: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<string> {\r\n const sql = `SELECT level, message, \\\\\"isError\\\\\", \\\\\"createdAt\\\\\" `\r\n + `FROM \\\\\"TaskEvent\\\\\" `\r\n + `WHERE \\\\\"runId\\\\\" = '${runId}' `\r\n + `AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') `\r\n + `ORDER BY \\\\\"startTime\\\\\" ASC LIMIT 200`;\r\n\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) return '';\r\n\r\n return output.split('\\n').map((line) => {\r\n const parts = line.split('|');\r\n const level = (parts[0] || '').padEnd(5);\r\n const message = parts[1] || '';\r\n const isError = parts[2] === 't';\r\n const ts = parts[3] || '';\r\n const time = ts ? ts.split(' ')[1]?.substring(0, 8) || '' : '';\r\n const prefix = isError ? '!' : ' ';\r\n return `${prefix}${time} [${level}] ${message}`;\r\n }).join('\\n');\r\n}\r\n\r\n/**\r\n * Execute a curl request against the Trigger.dev REST API via SSH.\r\n * Uses -g (globoff) to prevent curl from interpreting brackets in URLs.\r\n */\r\nasync function triggerApi(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n method: string,\r\n path: string,\r\n body?: string,\r\n): Promise<string> {\r\n const parts = ['curl', '-s', '-g', '--max-time', '30'];\r\n if (method !== 'GET') parts.push('-X', method);\r\n parts.push(`\"http://localhost:${instance.port}${path}\"`);\r\n parts.push(`-H \"Authorization: Bearer ${instance.apiKey}\"`);\r\n if (body) {\r\n parts.push('-H \"Content-Type: application/json\"');\r\n parts.push(`-d '${body.replace(/'/g, \"'\\\\''\")}'`);\r\n }\r\n\r\n const result = await sshExec(conn, parts.join(' '), proxy);\r\n if (result.exitCode !== 0 && !result.stdout) {\r\n throw new Error(\r\n `Trigger.dev API call failed (${method} ${path}): ${result.stderr || `exit code ${result.exitCode}`}`,\r\n );\r\n }\r\n return result.stdout;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Output formatters\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction formatRunsTable(runs: TriggerRunItem[]): string {\r\n if (runs.length === 0) return 'No runs found';\r\n\r\n const lines = runs.map((r) => {\r\n const duration = r.durationMs != null ? `${(r.durationMs / 1000).toFixed(1)}s` : '-';\r\n const test = r.isTest ? ' [TEST]' : '';\r\n const created = r.createdAt ? new Date(r.createdAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' }) : '';\r\n return `${r.id} ${r.taskIdentifier.padEnd(35)} ${r.status.padEnd(16)} ${duration.padStart(8)} ${created}${test}`;\r\n });\r\n\r\n return `${'ID'.padEnd(20)} ${'TASK'.padEnd(35)} ${'STATUS'.padEnd(16)} ${'DURATION'.padStart(8)} CREATED\\n` +\r\n '-'.repeat(110) + '\\n' +\r\n lines.join('\\n');\r\n}\r\n\r\nfunction formatRunDetail(run: TriggerRunDetail): string {\r\n const sections: string[] = [];\r\n\r\n sections.push(`=== Run ${run.id} ===`);\r\n sections.push(`Task: ${run.taskIdentifier}`);\r\n sections.push(`Status: ${run.status}`);\r\n sections.push(`Version: ${run.version || '-'}`);\r\n\r\n if (run.startedAt) sections.push(`Started: ${new Date(run.startedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.finishedAt) sections.push(`Finished: ${new Date(run.finishedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.durationMs != null) sections.push(`Duration: ${(run.durationMs / 1000).toFixed(2)}s`);\r\n\r\n if (run.payload !== undefined) {\r\n const payloadStr = typeof run.payload === 'string'\r\n ? run.payload\r\n : JSON.stringify(run.payload, null, 2);\r\n sections.push('', '--- Payload ---', payloadStr);\r\n }\r\n\r\n if (run.output !== undefined) {\r\n const outputStr = typeof run.output === 'string'\r\n ? run.output\r\n : JSON.stringify(run.output, null, 2);\r\n sections.push('', '--- Output ---', outputStr);\r\n }\r\n\r\n if (run.attempts && run.attempts.length > 0) {\r\n for (const attempt of run.attempts) {\r\n if (attempt.error) {\r\n sections.push(\r\n '',\r\n `--- Error (${attempt.id}) ---`,\r\n `${attempt.error.name || 'Error'}: ${attempt.error.message}`,\r\n );\r\n if (attempt.error.stackTrace) {\r\n sections.push('', attempt.error.stackTrace);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main handler\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Executes a Trigger.dev–related MCP tool over SSH against the shared Docker Compose stack.\r\n *\r\n * @param name - Tool name (e.g. `trigger-list`, `trigger-runs`).\r\n * @param args - Arguments from the MCP `callTool` request.\r\n * @param deps - Injected `sshExec` and `getServerConnection` implementations.\r\n * @returns MCP-formatted result with human-readable text content.\r\n * @throws {Error} When a JSON payload for `trigger-test-task` is invalid, or discovery/API calls fail critically.\r\n */\r\nexport async function handleTriggerTool(\r\n name: string,\r\n args: Record<string, unknown>,\r\n deps: TriggerToolDeps,\r\n): Promise<ToolResult> {\r\n const { sshExec, getServerConnection } = deps;\r\n const { conn, proxy } = await getServerConnection(TRIGGER_SERVER_ID);\r\n\r\n switch (name) {\r\n // -----------------------------------------------------------------\r\n case 'trigger-list': {\r\n const sql = 'SELECT slug, name FROM \\\\\"Project\\\\\" ORDER BY name';\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) {\r\n return { content: [{ type: 'text', text: 'No Trigger.dev projects found.' }] };\r\n }\r\n\r\n const header = `${'SLUG'.padEnd(25)} NAME`;\r\n const sep = '-'.repeat(55);\r\n const lines = output.split('\\n').map((line) => {\r\n const [slug, name] = line.split('|');\r\n return `${(slug || '').padEnd(25)} ${name || ''}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: `${header}\\n${sep}\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-runs': {\r\n const project = String(args.project);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 100);\r\n const queryParts = [`page%5Bsize%5D=${limit}`];\r\n if (args.status) queryParts.push(`filter%5Bstatus%5D=${String(args.status)}`);\r\n if (args.taskIdentifier) queryParts.push(`filter%5BtaskIdentifier%5D=${String(args.taskIdentifier)}`);\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v1/runs?${queryParts.join('&')}`,\r\n );\r\n\r\n let parsed: { data?: TriggerRunItem[] };\r\n try {\r\n parsed = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runs = parsed.data || [];\r\n return { content: [{ type: 'text', text: formatRunsTable(runs) }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-run-detail': {\r\n const project = String(args.project);\r\n const runId = String(args.runId);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const [rawJson, logs] = await Promise.all([\r\n triggerApi(conn, proxy, sshExec, instance, 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`),\r\n fetchRunLogs(runId, conn, proxy, sshExec),\r\n ]);\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n let text = formatRunDetail(run);\r\n if (logs) {\r\n text += '\\n\\n--- Logs ---\\n' + logs;\r\n }\r\n\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-test-task': {\r\n const project = String(args.project);\r\n const taskId = String(args.taskId);\r\n const waitSeconds = Math.min(Math.max(Number(args.waitSeconds) || 60, 5), 300);\r\n\r\n conn.timeout = (waitSeconds + 30) * 1000;\r\n\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n let payload = '{}';\r\n if (args.payload) {\r\n try {\r\n JSON.parse(String(args.payload));\r\n payload = String(args.payload);\r\n } catch {\r\n throw new Error(`Invalid JSON payload: ${String(args.payload).substring(0, 200)}`);\r\n }\r\n }\r\n\r\n const triggerBody = JSON.stringify({\r\n payload: JSON.parse(payload),\r\n options: { tags: ['mcp-test'], test: true },\r\n });\r\n\r\n const triggerJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/tasks/${encodeURIComponent(taskId)}/trigger`,\r\n triggerBody,\r\n );\r\n\r\n let triggerResp: { id?: string };\r\n try {\r\n triggerResp = JSON.parse(triggerJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Failed to trigger task. API response:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runId = triggerResp.id;\r\n if (!runId) {\r\n return { content: [{ type: 'text', text: `Trigger API did not return a run ID:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const pollInterval = 3000;\r\n const maxPolls = Math.ceil((waitSeconds * 1000) / pollInterval);\r\n\r\n for (let i = 0; i < maxPolls; i++) {\r\n await new Promise((r) => setTimeout(r, pollInterval));\r\n\r\n const pollJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`,\r\n );\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(pollJson);\r\n } catch {\r\n continue;\r\n }\r\n\r\n if (TERMINAL_STATUSES.has(run.status)) {\r\n let text = formatRunDetail(run);\r\n const logs = await fetchRunLogs(runId, conn, proxy, sshExec);\r\n if (logs) text += '\\n\\n--- Logs ---\\n' + logs;\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n }\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Run ${runId} did not complete within ${waitSeconds}s (still running). Use trigger-run-detail to check later.`,\r\n }],\r\n };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-replay-run': {\r\n const project = String(args.project);\r\n const runId = String(args.runId);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/runs/${encodeURIComponent(runId)}/replay`,\r\n );\r\n\r\n let result: { id?: string };\r\n try {\r\n result = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Replay response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: result.id\r\n ? `Run replayed. New run ID: ${result.id}`\r\n : `Replay response:\\n${rawJson.substring(0, 500)}`,\r\n }],\r\n };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n default:\r\n return { content: [{ type: 'text', text: `Unknown trigger tool: ${name}` }] };\r\n }\r\n}\r\n","/**\r\n * Web Tools for MCP Server\r\n *\r\n * Web search, fetch, and contact extraction tools available to both\r\n * human operators (via Cursor MCP) and automated agent workspaces.\r\n *\r\n * @module agent-tools\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ToolResult {\r\n [key: string]: unknown;\r\n content: { type: string; text: string }[];\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction clamp(val: number, min: number, max: number): number {\r\n return Math.max(min, Math.min(max, val));\r\n}\r\n\r\nfunction sanitizeString(val: unknown, maxLen: number): string {\r\n return String(val ?? '').slice(0, maxLen);\r\n}\r\n\r\nexport const AGENT_TOOLS = [\r\n {\r\n name: 'web-search',\r\n description:\r\n 'Search the web using DuckDuckGo. Returns a list of results with title, URL, and snippet. ' +\r\n 'Use this to find companies, websites, directories, etc.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n query: { type: 'string', description: 'Search query (e.g. \"logistiek bedrijf MKB nederland\")' },\r\n max_results: { type: 'number', description: 'Max results to return (default: 15, max: 30)' },\r\n },\r\n required: ['query'],\r\n },\r\n },\r\n {\r\n name: 'web-fetch',\r\n description:\r\n 'Fetch a web page and return its text content (HTML tags stripped). ' +\r\n 'Automatically extracts emails and phone numbers found on the page. ' +\r\n 'Returns at most 15000 characters of cleaned text.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n url: { type: 'string', description: 'Full URL to fetch (e.g. \"https://example.nl/contact\")' },\r\n extract_links: { type: 'boolean', description: 'Also extract all links from the page (default: false)' },\r\n },\r\n required: ['url'],\r\n },\r\n },\r\n {\r\n name: 'web-find-contacts',\r\n description:\r\n 'POWERFUL contact finder. Crawls a company website (homepage + contact/about/team pages), ' +\r\n 'extracts ALL emails, phone numbers, and LinkedIn URLs via regex + mailto/tel parsing. ' +\r\n 'Also searches Google for the company email as fallback. Returns structured contact data. ' +\r\n 'USE THIS for every lead instead of manually browsing contact pages.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n url: {\r\n type: 'string',\r\n description: 'Company website URL or domain (e.g. \"https://example.nl\" or \"example.nl\")',\r\n },\r\n company_name: {\r\n type: 'string',\r\n description: 'Company name (improves Google search accuracy)',\r\n },\r\n include_search: {\r\n type: 'boolean',\r\n description: 'Also search Google for emails (default: true)',\r\n },\r\n },\r\n required: ['url'],\r\n },\r\n },\r\n];\r\n\r\n/** Set of web tool names for dispatch in the main server. */\r\nexport const AGENT_TOOL_NAMES = new Set(AGENT_TOOLS.map((t) => t.name));\r\n\r\n/** Maps each web tool name to the dashboard permission module. */\r\nexport const AGENT_TOOL_MODULE_MAP: Record<string, string> = {\r\n 'web-search': 'agent_reporting',\r\n 'web-fetch': 'agent_reporting',\r\n 'web-find-contacts': 'agent_reporting',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Web Search & Fetch helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface SearchResult {\r\n title: string;\r\n url: string;\r\n snippet: string;\r\n}\r\n\r\nconst WEB_USER_AGENT =\r\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\n\r\nasync function webSearch(query: string, maxResults: number): Promise<SearchResult[]> {\r\n const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;\r\n\r\n const response = await fetch(url, {\r\n headers: {\r\n 'User-Agent': WEB_USER_AGENT,\r\n 'Accept': 'text/html',\r\n 'Accept-Language': 'nl,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n });\r\n\r\n if (!response.ok) throw new Error(`Search failed: HTTP ${response.status}`);\r\n const html = await response.text();\r\n\r\n const results: SearchResult[] = [];\r\n const resultBlocks = html.split(/class=\"result\\s/);\r\n\r\n for (let i = 1; i < resultBlocks.length && results.length < maxResults; i++) {\r\n const block = resultBlocks[i];\r\n\r\n const titleMatch = block.match(/class=\"result__a\"[^>]*>([^<]+)</);\r\n const hrefMatch = block.match(/class=\"result__a\"\\s+href=\"([^\"]+)\"/);\r\n const snippetMatch = block.match(/class=\"result__snippet\"[^>]*>([\\s\\S]*?)<\\/a>/);\r\n\r\n if (!hrefMatch) continue;\r\n\r\n let href = hrefMatch[1];\r\n if (href.includes('uddg=')) {\r\n const uddg = new URL(href, 'https://duckduckgo.com').searchParams.get('uddg');\r\n if (uddg) href = uddg;\r\n }\r\n\r\n if (!href.startsWith('http')) continue;\r\n\r\n const title = titleMatch\r\n ? titleMatch[1].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, \"'\").replace(/"/g, '\"').trim()\r\n : href;\r\n\r\n const snippet = snippetMatch\r\n ? snippetMatch[1].replace(/<[^>]+>/g, '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, \"'\").replace(/"/g, '\"').replace(/\\s+/g, ' ').trim()\r\n : '';\r\n\r\n results.push({ title, url: href, snippet });\r\n }\r\n\r\n return results;\r\n}\r\n\r\ninterface WebFetchResult {\r\n text: string;\r\n rawHtml: string;\r\n links: { href: string; text: string }[];\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Contact extraction constants & helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst EMAIL_REGEX = /[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}/g;\r\nconst PHONE_NL_REGEX = /(?:\\+31|0)[\\s\\-.]?\\(?\\d{1,3}\\)?[\\s\\-.]?\\d{3,4}[\\s\\-.]?\\d{2,4}/g;\r\nconst LINKEDIN_REGEX = /https?:\\/\\/(?:www\\.)?linkedin\\.com\\/(?:in|company)\\/[a-zA-Z0-9\\-_%]+\\/?/gi;\r\n\r\nconst NOISE_EMAIL_PATTERNS = [\r\n /noreply@/i, /no-reply@/i, /mailer-daemon@/i, /postmaster@/i,\r\n /@example\\./i, /test@/i, /@wix\\.com$/i, /@sentry\\.io$/i,\r\n /@wordpress\\./i, /@gravatar\\.com$/i, /@schema\\.org$/i,\r\n /@w3\\.org$/i, /@facebook\\.com$/i, /@google\\.com$/i, /@twitter\\.com$/i,\r\n /@github\\.com$/i, /@cloudflare\\./i, /@vercel\\./i, /@netlify\\./i,\r\n /@cookiebot\\./i, /@hotjar\\./i, /@hubspot\\./i, /@mailchimp\\./i,\r\n /@googleusercontent/i, /@gstatic/i, /@youtube/i, /@recaptcha/i,\r\n /@privacy/i, /@cookie/i, /@gdpr/i, /@dynamicweb\\./i,\r\n /@placeholder\\./i, /@yourcompany\\./i, /@company\\./i,\r\n /smith@/i, /doe@/i, /demo@/i, /sample@/i,\r\n /naam@/i, /voorbeeld/i, /your-?email/i, /email@/i,\r\n /@domein\\./i, /@bedrijf\\./i, /@domain\\./i,\r\n /@sentry/i, /@wixpress/i, /@lieferkassen/i, /john@/i, /jane@/i,\r\n];\r\n\r\nconst CONTACT_PATH_KEYWORDS = [\r\n 'contact', 'about', 'over-ons', 'over', 'team', 'medewerker',\r\n 'impressum', 'imprint', 'wie-zijn', 'ons-team', 'werknemers',\r\n 'organisatie', 'zakelijk', 'bedrijfsinfo', 'neem-contact', 'footer',\r\n];\r\n\r\nconst CONTACT_PATHS_TO_TRY = [\r\n '/contact', '/over-ons', '/about', '/about-us', '/team',\r\n '/contact-us', '/over', '/wie-zijn-wij', '/ons-team',\r\n '/zakelijk/over-ons', '/medewerkers', '/organisatie',\r\n '/bedrijfsinformatie', '/impressum',\r\n];\r\n\r\nfunction decodeUnicodeEscapes(text: string): string {\r\n return text.replace(/\\\\u([0-9a-fA-F]{4})/g, (_, hex) =>\r\n String.fromCharCode(parseInt(hex, 16)),\r\n );\r\n}\r\n\r\nfunction decodeHtmlEntities(text: string): string {\r\n return text\r\n .replace(/&#(\\d+);/g, (_, num) => String.fromCharCode(parseInt(num)))\r\n .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) =>\r\n String.fromCharCode(parseInt(hex, 16)),\r\n );\r\n}\r\n\r\nfunction extractEmailsFromHtml(html: string): string[] {\r\n const emails = new Set<string>();\r\n\r\n const decoded = decodeHtmlEntities(decodeUnicodeEscapes(html));\r\n\r\n const mailtoRegex = /mailto:([a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,})/gi;\r\n let m: RegExpExecArray | null;\r\n for (const src of [html, decoded]) {\r\n while ((m = mailtoRegex.exec(src)) !== null) emails.add(m[1]!.toLowerCase());\r\n }\r\n\r\n const noStyles = decoded.replace(/<style[\\s\\S]*?<\\/style>/gi, '');\r\n const textEmails = noStyles.match(EMAIL_REGEX) || [];\r\n for (const e of textEmails) {\r\n const lower = e.toLowerCase();\r\n if (!/\\.(png|jpg|jpeg|gif|svg|webp|css|js|woff|ttf|eot|ico)$/i.test(lower)) {\r\n emails.add(lower);\r\n }\r\n }\r\n\r\n return [...emails].filter(e => !NOISE_EMAIL_PATTERNS.some(p => p.test(e)));\r\n}\r\n\r\nfunction extractPhonesFromHtml(html: string): string[] {\r\n const phones = new Set<string>();\r\n const decoded = decodeHtmlEntities(decodeUnicodeEscapes(html));\r\n\r\n const telRegex = /href=\"tel:([^\"]+)\"/gi;\r\n let m: RegExpExecArray | null;\r\n for (const src of [html, decoded]) {\r\n while ((m = telRegex.exec(src)) !== null) {\r\n const clean = m[1]!.replace(/[\\s\\-().]/g, '');\r\n if (clean.length >= 10 && clean.length <= 14) phones.add(m[1]!.trim());\r\n }\r\n }\r\n\r\n const stripped = decoded\r\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\r\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\r\n .replace(/<[^>]+>/g, ' ');\r\n const textPhones = stripped.match(PHONE_NL_REGEX) || [];\r\n for (const p of textPhones) {\r\n const clean = p.replace(/[\\s\\-().]/g, '');\r\n if (clean.length >= 10 && clean.length <= 14) phones.add(p.trim());\r\n }\r\n\r\n return [...phones].slice(0, 10);\r\n}\r\n\r\nfunction extractLinkedInFromHtml(html: string): string[] {\r\n const links = new Set<string>();\r\n const matches = html.match(LINKEDIN_REGEX) || [];\r\n for (const l of matches) links.add(l.replace(/\\/$/, ''));\r\n return [...links];\r\n}\r\n\r\nfunction discoverContactPages(html: string, baseUrl: string): string[] {\r\n let base: URL;\r\n try { base = new URL(baseUrl); } catch { return []; }\r\n\r\n const pages = new Set<string>();\r\n\r\n for (const path of CONTACT_PATHS_TO_TRY) {\r\n pages.add(`${base.origin}${path}`);\r\n }\r\n\r\n const linkRegex = /<a\\s[^>]*href=\"([^\"#]*)\"[^>]*>/gi;\r\n let m: RegExpExecArray | null;\r\n while ((m = linkRegex.exec(html)) !== null) {\r\n try {\r\n const url = new URL(m[1], baseUrl);\r\n if (url.hostname !== base.hostname) continue;\r\n const path = url.pathname.toLowerCase();\r\n if (CONTACT_PATH_KEYWORDS.some(kw => path.includes(kw))) {\r\n pages.add(url.origin + url.pathname);\r\n }\r\n } catch { /* invalid url, skip */ }\r\n }\r\n\r\n pages.delete(base.origin + base.pathname);\r\n return [...pages].slice(0, 10);\r\n}\r\n\r\nfunction guessCommonEmails(domain: string): string[] {\r\n const d = domain.replace(/^www\\./, '');\r\n return [`info@${d}`, `contact@${d}`, `hello@${d}`, `administratie@${d}`, `verkoop@${d}`];\r\n}\r\n\r\nconst BOT_CHALLENGE_INDICATORS = [\r\n 'sgcaptcha', 'challenge-platform', 'cf-browser-verification',\r\n 'Just a moment', 'Checking your browser', 'Enable JavaScript and cookies',\r\n 'Attention Required', 'DDoS protection by',\r\n];\r\n\r\nfunction isBotChallengePage(html: string): boolean {\r\n if (html.length > 2000) return false;\r\n const lower = html.toLowerCase();\r\n return BOT_CHALLENGE_INDICATORS.some(ind => lower.includes(ind.toLowerCase()));\r\n}\r\n\r\nasync function fetchRawHtml(url: string, timeoutMs = 10000): Promise<string | null> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), timeoutMs);\r\n try {\r\n const res = await fetch(url, {\r\n headers: {\r\n 'User-Agent': WEB_USER_AGENT,\r\n 'Accept': 'text/html,application/xhtml+xml',\r\n 'Accept-Language': 'nl,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n const ct = res.headers.get('content-type') || '';\r\n if (!ct.includes('text/html') && !ct.includes('text/plain') && !ct.includes('xhtml')) return null;\r\n if (!res.ok && res.status !== 403) return null;\r\n const html = await res.text();\r\n if (isBotChallengePage(html)) return null;\r\n return html;\r\n } catch {\r\n return null;\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n}\r\n\r\nasync function fetchWaybackHtml(url: string, timeoutMs = 15000): Promise<string | null> {\r\n const cleanUrl = url.replace(/^https?:\\/\\//, '');\r\n const wbUrl = `https://web.archive.org/web/2024/${cleanUrl}`;\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), timeoutMs);\r\n try {\r\n const res = await fetch(wbUrl, {\r\n headers: { 'User-Agent': WEB_USER_AGENT },\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n if (!res.ok) return null;\r\n const html = await res.text();\r\n if (html.length < 500) return null;\r\n return html;\r\n } catch {\r\n return null;\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n}\r\n\r\nasync function webFetch(url: string, extractLinks: boolean): Promise<WebFetchResult> {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), 15000);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n headers: {\r\n 'User-Agent': WEB_USER_AGENT,\r\n 'Accept': 'text/html,application/xhtml+xml',\r\n 'Accept-Language': 'nl,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n\r\n if (!response.ok) throw new Error(`Fetch failed: HTTP ${response.status}`);\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n if (!contentType.includes('text/html') && !contentType.includes('text/plain') && !contentType.includes('application/xhtml')) {\r\n throw new Error(`Unsupported content type: ${contentType}. Only HTML/text pages supported.`);\r\n }\r\n\r\n const html = await response.text();\r\n\r\n const links: { href: string; text: string }[] = [];\r\n if (extractLinks) {\r\n const linkRegex = /<a\\s[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\r\n let match;\r\n while ((match = linkRegex.exec(html)) !== null) {\r\n const href = match[1];\r\n const text = match[2].replace(/<[^>]+>/g, '').trim();\r\n if (href && href.startsWith('http')) {\r\n links.push({ href, text: text.slice(0, 100) });\r\n }\r\n }\r\n }\r\n\r\n let text = html\r\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\r\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\r\n .replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '')\r\n .replace(/<nav[\\s\\S]*?<\\/nav>/gi, ' [NAV] ')\r\n .replace(/<header[\\s\\S]*?<\\/header>/gi, ' [HEADER] ')\r\n .replace(/<footer[\\s\\S]*?<\\/footer>/gi, ' [FOOTER] ')\r\n .replace(/<(br|hr)\\s*\\/?>/gi, '\\n')\r\n .replace(/<\\/(p|div|h[1-6]|li|tr|section|article)>/gi, '\\n')\r\n .replace(/<[^>]+>/g, ' ')\r\n .replace(/ /g, ' ')\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/'/g, \"'\")\r\n .replace(/"/g, '\"')\r\n .replace(/[ \\t]+/g, ' ')\r\n .replace(/\\n\\s*\\n/g, '\\n')\r\n .trim();\r\n\r\n const MAX_TEXT = 15000;\r\n if (text.length > MAX_TEXT) {\r\n text = text.slice(0, MAX_TEXT) + '\\n\\n[... truncated at 15000 chars ...]';\r\n }\r\n\r\n return { text, rawHtml: html, links };\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main handler\r\n// ---------------------------------------------------------------------------\r\n\r\nexport async function handleAgentTool(\r\n name: string,\r\n args: Record<string, unknown>,\r\n): Promise<ToolResult> {\r\n switch (name) {\r\n case 'web-search': {\r\n const query = sanitizeString(args.query, 500);\r\n if (!query) throw new Error('query is required');\r\n const maxResults = clamp(Number(args.max_results) || 15, 1, 30);\r\n\r\n const results = await webSearch(query, maxResults);\r\n\r\n if (results.length === 0) {\r\n return { content: [{ type: 'text', text: `No search results found for: \"${query}\"` }] };\r\n }\r\n\r\n const formatted = results.map((r, i) =>\r\n `${i + 1}. ${r.title}\\n URL: ${r.url}\\n ${r.snippet}`\r\n ).join('\\n\\n');\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Search results for \"${query}\" (${results.length} results):\\n\\n${formatted}`,\r\n }],\r\n };\r\n }\r\n\r\n case 'web-fetch': {\r\n const url = sanitizeString(args.url, 2000);\r\n if (!url) throw new Error('url is required');\r\n if (!/^https?:\\/\\//i.test(url)) throw new Error('url must start with http:// or https://');\r\n\r\n const extractLinks = Boolean(args.extract_links);\r\n const result = await webFetch(url, extractLinks);\r\n\r\n let text = `Content from ${url} (${result.text.length} chars):\\n\\n${result.text}`;\r\n\r\n if (extractLinks && result.links.length > 0) {\r\n const linkList = result.links.slice(0, 50).map(l =>\r\n ` ${l.text ? l.text + ': ' : ''}${l.href}`\r\n ).join('\\n');\r\n text += `\\n\\n--- Links (${result.links.length} found, showing max 50) ---\\n${linkList}`;\r\n }\r\n\r\n const pageEmails = extractEmailsFromHtml(result.rawHtml);\r\n const pagePhones = extractPhonesFromHtml(result.rawHtml);\r\n const pageLinkedIn = extractLinkedInFromHtml(result.rawHtml);\r\n\r\n if (pageEmails.length > 0 || pagePhones.length > 0 || pageLinkedIn.length > 0) {\r\n text += '\\n\\n--- Auto-extracted Contact Info ---';\r\n if (pageEmails.length > 0) text += `\\nEmails: ${pageEmails.join(', ')}`;\r\n if (pagePhones.length > 0) text += `\\nPhones: ${pagePhones.join(', ')}`;\r\n if (pageLinkedIn.length > 0) text += `\\nLinkedIn: ${pageLinkedIn.join(', ')}`;\r\n }\r\n\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n case 'web-find-contacts': {\r\n const inputUrl = sanitizeString(args.url, 2000);\r\n if (!inputUrl) throw new Error('url is required');\r\n const companyName = sanitizeString(args.company_name, 500);\r\n const includeSearch = args.include_search !== false;\r\n\r\n const fullUrl = inputUrl.startsWith('http') ? inputUrl : `https://${inputUrl}`;\r\n let baseUrl: URL;\r\n try { baseUrl = new URL(fullUrl); } catch { throw new Error(`Invalid URL: ${inputUrl}`); }\r\n const domain = baseUrl.hostname.replace(/^www\\./, '');\r\n\r\n const urlsToTry = [fullUrl];\r\n if (!fullUrl.includes('www.')) urlsToTry.push(fullUrl.replace('://', '://www.'));\r\n if (fullUrl.startsWith('https')) {\r\n urlsToTry.push(fullUrl.replace('https', 'http'));\r\n if (!fullUrl.includes('www.')) urlsToTry.push(fullUrl.replace('https://', 'http://www.'));\r\n }\r\n let html: string | null = null;\r\n let usedWayback = false;\r\n for (const tryUrl of urlsToTry) {\r\n html = await fetchRawHtml(tryUrl, 12000);\r\n if (html) break;\r\n }\r\n if (!html) {\r\n html = await fetchWaybackHtml(`https://${domain}`, 15000);\r\n if (html) usedWayback = true;\r\n }\r\n if (!html) throw new Error(`Could not fetch ${fullUrl} (site may be down or blocking)`);\r\n\r\n const contactPages = usedWayback ? [] : discoverContactPages(html, fullUrl);\r\n\r\n const pagePromises = contactPages.map(async (pageUrl) => {\r\n const pageHtml = await fetchRawHtml(pageUrl, 8000);\r\n return { url: pageUrl, html: pageHtml };\r\n });\r\n const pageResults = await Promise.allSettled(pagePromises);\r\n\r\n const successPages: string[] = [usedWayback ? `(wayback) ${domain}` : fullUrl];\r\n const allHtmls = [html];\r\n for (const result of pageResults) {\r\n if (result.status === 'fulfilled' && result.value.html) {\r\n allHtmls.push(result.value.html);\r\n successPages.push(result.value.url);\r\n }\r\n }\r\n\r\n if (usedWayback) {\r\n const waybackContactPaths = ['/contact', '/over-ons', '/about', '/team'];\r\n const wbPromises = waybackContactPaths.map(async (path) => {\r\n const wbHtml = await fetchWaybackHtml(`https://${domain}${path}`, 12000);\r\n return { path, html: wbHtml };\r\n });\r\n const wbResults = await Promise.allSettled(wbPromises);\r\n for (const wr of wbResults) {\r\n if (wr.status === 'fulfilled' && wr.value.html) {\r\n allHtmls.push(wr.value.html);\r\n successPages.push(`(wayback) ${domain}${wr.value.path}`);\r\n }\r\n }\r\n }\r\n\r\n const allEmails = new Set<string>();\r\n const allPhones = new Set<string>();\r\n const allLinkedIn = new Set<string>();\r\n\r\n for (const pageHtml of allHtmls) {\r\n for (const e of extractEmailsFromHtml(pageHtml)) allEmails.add(e);\r\n for (const p of extractPhonesFromHtml(pageHtml)) allPhones.add(p);\r\n for (const l of extractLinkedInFromHtml(pageHtml)) allLinkedIn.add(l);\r\n }\r\n\r\n let searchNote = '';\r\n if (includeSearch) {\r\n try {\r\n const queries = companyName\r\n ? [`\"${companyName}\" \"${domain}\" email`, `\"@${domain}\" email`]\r\n : [`\"${domain}\" email contact`, `\"@${domain}\" email`, `site:${domain} \"@\"`];\r\n\r\n let totalSearchResults = 0;\r\n for (const searchQuery of queries) {\r\n const searchResults = await webSearch(searchQuery, 8);\r\n totalSearchResults += searchResults.length;\r\n\r\n for (const r of searchResults) {\r\n const combined = `${r.title} ${r.snippet}`;\r\n const decoded = decodeHtmlEntities(decodeUnicodeEscapes(combined));\r\n const snippetEmails = decoded.match(EMAIL_REGEX) || [];\r\n for (const e of snippetEmails) {\r\n const lower = e.toLowerCase();\r\n const domainBase = domain.split('.')[0] ?? domain;\r\n if (lower.includes(domainBase) && !NOISE_EMAIL_PATTERNS.some(p => p.test(lower))) {\r\n allEmails.add(lower);\r\n }\r\n }\r\n\r\n const snippetPhones = decoded.match(PHONE_NL_REGEX) || [];\r\n for (const p of snippetPhones) {\r\n const clean = p.replace(/[\\s\\-().]/g, '');\r\n if (clean.length >= 10 && clean.length <= 14) allPhones.add(p.trim());\r\n }\r\n\r\n const snippetLi = decoded.match(LINKEDIN_REGEX) || [];\r\n for (const l of snippetLi) allLinkedIn.add(l.replace(/\\/$/, ''));\r\n }\r\n if (allEmails.size > 0) break;\r\n }\r\n searchNote = ` + ${totalSearchResults} search results`;\r\n } catch { searchNote = ' (search failed)'; }\r\n }\r\n\r\n const foundEmails = [...allEmails];\r\n const generalPatterns = /^(info|contact|hello|admin|office|receptie|secretariaat|verkoop|administratie|support|service|boekingen|reserveringen)@/i;\r\n const generalEmails = foundEmails.filter(e => generalPatterns.test(e));\r\n const personalEmails = foundEmails.filter(e => !generalPatterns.test(e));\r\n\r\n const guessed = guessCommonEmails(domain);\r\n const newGuesses = guessed.filter(g => !allEmails.has(g));\r\n\r\n const lines = [\r\n `=== CONTACT SCAN: ${domain} ===`,\r\n `Pages scanned: ${successPages.length}${searchNote}`,\r\n '',\r\n ];\r\n\r\n if (foundEmails.length > 0) {\r\n lines.push(`EMAILS FOUND (${foundEmails.length}):`);\r\n if (generalEmails.length > 0) {\r\n lines.push(' General:');\r\n for (const e of generalEmails) lines.push(` * ${e}`);\r\n }\r\n if (personalEmails.length > 0) {\r\n lines.push(' Personal/Department:');\r\n for (const e of personalEmails) lines.push(` * ${e}`);\r\n }\r\n } else {\r\n lines.push('EMAILS FOUND: None on website');\r\n lines.push('SUGGESTED EMAILS (common patterns, verify before use):');\r\n for (const e of newGuesses) lines.push(` ? ${e}`);\r\n }\r\n\r\n lines.push('');\r\n if ([...allPhones].length > 0) {\r\n lines.push(`PHONE NUMBERS (${allPhones.size}):`);\r\n for (const p of allPhones) lines.push(` ${p}`);\r\n } else {\r\n lines.push('PHONE NUMBERS: None found');\r\n }\r\n\r\n lines.push('');\r\n if ([...allLinkedIn].length > 0) {\r\n lines.push(`LINKEDIN (${allLinkedIn.size}):`);\r\n for (const l of allLinkedIn) lines.push(` ${l}`);\r\n }\r\n\r\n lines.push('', 'PAGES CHECKED:');\r\n for (const p of successPages) lines.push(` [OK] ${p}`);\r\n const failedPages = contactPages.filter(p => !successPages.includes(p));\r\n for (const p of failedPages) lines.push(` [--] ${p}`);\r\n\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n default:\r\n return { content: [{ type: 'text', text: `Unknown tool: ${name}` }] };\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\r\nimport { CallToolRequestSchema, ListToolsRequestSchema, isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';\r\nimport { createServer as createHttpServer } from 'node:http';\r\nimport { randomUUID } from 'node:crypto';\r\nimport { createClient } from '@supabase/supabase-js';\r\nimport { createHash, randomBytes, createCipheriv, createDecipheriv } from 'crypto';\r\nimport { spawn } from 'node:child_process';\r\nimport { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';\r\nimport { createReadStream, existsSync, statSync } from 'node:fs';\r\nimport { tmpdir } from 'node:os';\r\nimport { isAbsolute, join } from 'node:path';\r\nimport { Readable } from 'node:stream';\r\nimport { Client as SshClient } from 'ssh2';\r\nimport {\r\n TRIGGER_TOOLS,\r\n TRIGGER_TOOL_NAMES,\r\n TRIGGER_TOOL_MODULE_MAP,\r\n handleTriggerTool,\r\n} from './trigger-tools.js';\r\nimport {\r\n AGENT_TOOLS,\r\n AGENT_TOOL_NAMES,\r\n AGENT_TOOL_MODULE_MAP,\r\n handleAgentTool,\r\n} from './agent-tools.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// CLI argument parsing\r\n// ---------------------------------------------------------------------------\r\n\r\nconst args = process.argv.slice(2);\r\n\r\nfunction getArg(name: string): string | undefined {\r\n return args.find(a => a.startsWith(`--${name}=`))?.split('=').slice(1).join('=');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Proxy-bridge mode: when --proxy-url is given we bypass the rest of this\r\n// file entirely and run as a thin SSH-key-authenticated bridge to a remote\r\n// MCP HTTP endpoint (used for the Supabase MCPs behind apps/mcp-proxy).\r\n// ---------------------------------------------------------------------------\r\nconst proxyUrl = getArg('proxy-url') || process.env.MG_DASHBOARD_PROXY_URL;\r\nif (proxyUrl) {\r\n const { runProxyMode } = await import('./proxy-mode.js');\r\n await runProxyMode(args);\r\n // runProxyMode never resolves under normal operation; if it does, exit.\r\n process.exit(0);\r\n}\r\n\r\nconst apiKey = getArg('api-key') || process.env.MG_DASHBOARD_API_KEY;\r\nconst sshKeyPath = getArg('ssh-key') || process.env.MG_DASHBOARD_SSH_KEY;\r\nconst supabaseUrl = getArg('supabase-url') || process.env.SUPABASE_URL;\r\nconst supabaseKey = getArg('supabase-key') || process.env.SUPABASE_SERVICE_ROLE_KEY;\r\nconst encryptionKey = getArg('encryption-key') || process.env.ENCRYPTION_KEY;\r\nconst mijnhostApiKey = getArg('mijnhost-api-key') || process.env.MIJNHOST_API_KEY;\r\nconst httpMode = args.includes('--http');\r\nconst httpPort = Number(getArg('port')) || 3100;\r\n\r\nif (!apiKey || !sshKeyPath) {\r\n console.error('Authentication required. Use both --api-key=dk_xxx and --ssh-key=PATH (path to your SSH private or public key), or set MG_DASHBOARD_API_KEY and MG_DASHBOARD_SSH_KEY.');\r\n process.exit(1);\r\n}\r\n\r\nif (!supabaseUrl || !supabaseKey) {\r\n console.error('Supabase credentials required. Use --supabase-url and --supabase-key or set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY');\r\n process.exit(1);\r\n}\r\n\r\nconst supabase = createClient(supabaseUrl, supabaseKey);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Rate limiting\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface RateLimitEntry {\r\n count: number;\r\n resetAt: number;\r\n}\r\n\r\nclass RateLimiter {\r\n private buckets = new Map<string, RateLimitEntry>();\r\n private readonly maxAttempts: number;\r\n private readonly windowMs: number;\r\n\r\n constructor(maxAttempts: number, windowMs: number) {\r\n this.maxAttempts = maxAttempts;\r\n this.windowMs = windowMs;\r\n }\r\n\r\n /**\r\n * Check if an action is allowed for the given key.\r\n * Increments the counter and returns whether the action should proceed.\r\n */\r\n check(key: string): { allowed: boolean; remaining: number; retryAfterMs: number } {\r\n const now = Date.now();\r\n const entry = this.buckets.get(key);\r\n\r\n if (!entry || now >= entry.resetAt) {\r\n this.buckets.set(key, { count: 1, resetAt: now + this.windowMs });\r\n return { allowed: true, remaining: this.maxAttempts - 1, retryAfterMs: 0 };\r\n }\r\n\r\n entry.count++;\r\n\r\n if (entry.count > this.maxAttempts) {\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n retryAfterMs: entry.resetAt - now,\r\n };\r\n }\r\n\r\n return {\r\n allowed: true,\r\n remaining: this.maxAttempts - entry.count,\r\n retryAfterMs: 0,\r\n };\r\n }\r\n\r\n /** Periodically remove expired entries to prevent unbounded growth. */\r\n cleanup(): void {\r\n const now = Date.now();\r\n for (const [key, entry] of this.buckets) {\r\n if (now >= entry.resetAt) this.buckets.delete(key);\r\n }\r\n }\r\n}\r\n\r\nconst authRateLimiter = new RateLimiter(5, 15 * 60 * 1000);\r\n\r\n// Cleanup expired rate limit entries every 5 minutes\r\nsetInterval(() => {\r\n authRateLimiter.cleanup();\r\n}, 5 * 60 * 1000).unref();\r\n\r\n// Tool-level rate limiting was previously gated per category (ssh / sftp / db\r\n// / default) with hourly buckets. Removed because legitimate dev sessions\r\n// regularly burst over those caps and the resulting \"MCP Rate Limit\" stalls\r\n// were strictly noise — auth-level rate limiting (failed login attempts)\r\n// remains in place above for the actual security concern.\r\n\r\n// ---------------------------------------------------------------------------\r\n// Audit logging\r\n// ---------------------------------------------------------------------------\r\n\r\nconst SENSITIVE_KEYS = new Set(['password', 'private_key', 'passphrase', 'secret', 'token', 'key', 'api_key', 'credentials']);\r\n\r\nfunction redactSensitiveArgs(args: Record<string, unknown>): Record<string, unknown> {\r\n const redacted: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(args)) {\r\n if (SENSITIVE_KEYS.has(k.toLowerCase())) {\r\n redacted[k] = '[REDACTED]';\r\n } else if (typeof v === 'string' && v.length > 500) {\r\n redacted[k] = v.slice(0, 500) + '...[truncated]';\r\n } else {\r\n redacted[k] = v;\r\n }\r\n }\r\n return redacted;\r\n}\r\n\r\nasync function writeAuditLog(entry: {\r\n toolName: string;\r\n arguments?: Record<string, unknown>;\r\n ipAddress?: string;\r\n serverId?: string;\r\n resultStatus: 'success' | 'error';\r\n errorMessage?: string;\r\n durationMs?: number;\r\n}): Promise<void> {\r\n if (!authContext) return;\r\n try {\r\n await supabase.from('mcp_audit_log').insert({\r\n api_key_id: authContext.apiKeyId,\r\n user_id: authContext.userId,\r\n tool_name: entry.toolName,\r\n arguments: entry.arguments ? redactSensitiveArgs(entry.arguments) : null,\r\n ip_address: entry.ipAddress || null,\r\n server_id: entry.serverId || null,\r\n result_status: entry.resultStatus,\r\n error_message: entry.errorMessage?.slice(0, 1000) || null,\r\n duration_ms: entry.durationMs || null,\r\n });\r\n } catch (err) {\r\n console.error('[Audit] Failed to write audit log:', err instanceof Error ? err.message : err);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Permission model (mirrors packages/supabase/src/utils/permissions.ts)\r\n// ---------------------------------------------------------------------------\r\n\r\nconst MODULE_KEYS = [\r\n 'users', 'ssh_servers', 'supabase',\r\n 'wiki', 'ci_cd', 'domains',\r\n 'settings', 'agent_reporting',\r\n] as const;\r\n\r\ntype ModuleKey = (typeof MODULE_KEYS)[number];\r\n\r\ninterface ModulePermissions {\r\n users?: boolean;\r\n ssh_servers?: boolean;\r\n supabase?: boolean;\r\n wiki?: boolean;\r\n ci_cd?: boolean;\r\n\r\n domains?: boolean;\r\n settings?: boolean;\r\n agent_reporting?: boolean;\r\n}\r\n\r\ninterface ResourcePermissions {\r\n ssh_servers: string[];\r\n supabase_instances: string[];\r\n}\r\n\r\ninterface UserPermissions {\r\n modules: ModulePermissions;\r\n resources: ResourcePermissions;\r\n}\r\n\r\nconst FULL_PERMISSIONS: UserPermissions = {\r\n modules: Object.fromEntries(MODULE_KEYS.map((k) => [k, true])) as ModulePermissions,\r\n resources: { ssh_servers: ['*'], supabase_instances: ['*'] },\r\n};\r\n\r\nfunction parsePermissions(raw: unknown): Partial<UserPermissions> | null {\r\n if (!raw || typeof raw !== 'object') return null;\r\n return raw as Partial<UserPermissions>;\r\n}\r\n\r\nfunction resolvePermissions(\r\n roleName: string,\r\n roleDefaults: unknown,\r\n userOverrides: unknown,\r\n): UserPermissions {\r\n if (roleName === 'superadmin') return FULL_PERMISSIONS;\r\n\r\n const base = parsePermissions(roleDefaults);\r\n const overrides = parsePermissions(userOverrides);\r\n\r\n const modules: ModulePermissions = {} as ModulePermissions;\r\n for (const key of MODULE_KEYS) {\r\n const userVal = overrides?.modules?.[key];\r\n const roleVal = base?.modules?.[key];\r\n (modules as Record<string, boolean>)[key] =\r\n userVal !== undefined ? userVal : roleVal !== undefined ? roleVal : false;\r\n }\r\n\r\n const resources: ResourcePermissions = {\r\n ssh_servers: overrides?.resources?.ssh_servers ?? base?.resources?.ssh_servers ?? [],\r\n supabase_instances: overrides?.resources?.supabase_instances ?? base?.resources?.supabase_instances ?? [],\r\n };\r\n\r\n return { modules, resources };\r\n}\r\n\r\n/**\r\n * Intersect key-level server restrictions with user permission resources.\r\n * Most restrictive wins: if both specify lists, return the overlap.\r\n */\r\nfunction intersectServerAccess(\r\n keyServerIds: string[] | null,\r\n permissionServerIds: string[],\r\n): string[] | null {\r\n const keyHasRestriction = keyServerIds !== null;\r\n const permWildcard = permissionServerIds.includes('*');\r\n const permEmpty = permissionServerIds.length === 0;\r\n\r\n if (!keyHasRestriction && permWildcard) return null; // unrestricted\r\n if (!keyHasRestriction && permEmpty) return [];\r\n if (!keyHasRestriction) return permissionServerIds;\r\n if (permWildcard) return keyServerIds;\r\n if (permEmpty) return [];\r\n return keyServerIds.filter((id) => permissionServerIds.includes(id));\r\n}\r\n\r\n/** Maps each MCP tool to the module permission it requires. */\r\nconst TOOL_MODULE_MAP: Partial<Record<string, ModuleKey>> = {\r\n 'list-servers': 'ssh_servers',\r\n 'ssh-execute': 'ssh_servers',\r\n 'sftp-list': 'ssh_servers',\r\n 'sftp-read': 'ssh_servers',\r\n 'sftp-write': 'ssh_servers',\r\n 'sftp-delete': 'ssh_servers',\r\n 'docker-list': 'ssh_servers',\r\n 'docker-logs': 'ssh_servers',\r\n 'docker-exec': 'ssh_servers',\r\n 'docker-compose': 'ssh_servers',\r\n 'db-discover': 'ssh_servers',\r\n 'db-tables': 'ssh_servers',\r\n 'db-describe': 'ssh_servers',\r\n 'db-query': 'ssh_servers',\r\n 'cache-purge': 'ssh_servers',\r\n 'env-list': 'ci_cd',\r\n 'env-get': 'ci_cd',\r\n 'env-store': 'ci_cd',\r\n 'domain-list': 'domains',\r\n 'dns-list': 'domains',\r\n 'dns-create': 'domains',\r\n 'dns-update': 'domains',\r\n 'dns-delete': 'domains',\r\n ...TRIGGER_TOOL_MODULE_MAP,\r\n ...AGENT_TOOL_MODULE_MAP,\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Auth context\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface AuthContext {\r\n apiKeyId: string;\r\n apiKeyName: string;\r\n userId: string;\r\n allowedServerIds: string[] | null;\r\n permissions: UserPermissions;\r\n roleName: string;\r\n}\r\n\r\nlet authContext: AuthContext | null = null;\r\n\r\nasync function validateApiKey(key: string): Promise<AuthContext | null> {\r\n if (!key.startsWith('dk_') || key.length !== 67) {\r\n console.error('Invalid API key format (expected dk_ + 64 hex chars)');\r\n return null;\r\n }\r\n\r\n const keyHash = createHash('sha256').update(key).digest('hex');\r\n\r\n const rateCheck = authRateLimiter.check(keyHash);\r\n if (!rateCheck.allowed) {\r\n const retryMin = Math.ceil(rateCheck.retryAfterMs / 60_000);\r\n console.error(`Rate limited: too many failed auth attempts. Retry in ${retryMin} minute(s).`);\r\n return null;\r\n }\r\n\r\n const { data, error } = await supabase\r\n .from('dashboard_mcp_api_key')\r\n .select('id, name, created_by, allowed_server_ids, is_active, expires_at')\r\n .eq('api_key_hash', keyHash)\r\n .eq('is_active', true)\r\n .single();\r\n\r\n if (error || !data) {\r\n console.error(`API key not found or inactive (${rateCheck.remaining} attempts remaining)`);\r\n return null;\r\n }\r\n\r\n if (data.expires_at && new Date(data.expires_at) < new Date()) {\r\n console.error(`API key has expired (${rateCheck.remaining} attempts remaining)`);\r\n return null;\r\n }\r\n\r\n // Load user + role permissions\r\n const { data: userData, error: userError } = await supabase\r\n .from('user')\r\n .select('permissions, role:role!role_id(name, default_permissions)')\r\n .eq('id', data.created_by)\r\n .single();\r\n\r\n if (userError || !userData) {\r\n console.error(`User not found for API key creator: ${data.created_by}`);\r\n return null;\r\n }\r\n\r\n const roleName = (userData.role as { name?: string })?.name || 'user';\r\n const roleDefaults = (userData.role as { default_permissions?: unknown })?.default_permissions ?? {};\r\n const userOverrides = userData.permissions ?? null;\r\n const permissions = resolvePermissions(roleName, roleDefaults, userOverrides);\r\n\r\n const allowedServerIds = intersectServerAccess(\r\n data.allowed_server_ids,\r\n permissions.resources.ssh_servers,\r\n );\r\n\r\n await supabase\r\n .from('dashboard_mcp_api_key')\r\n .update({ last_used_at: new Date().toISOString() })\r\n .eq('id', data.id);\r\n\r\n const moduleCount = MODULE_KEYS.filter((k) => permissions.modules[k]).length;\r\n console.error(`Authenticated as user ${data.created_by} (role: ${roleName}, modules: ${moduleCount}/${MODULE_KEYS.length})`);\r\n\r\n return {\r\n apiKeyId: data.id,\r\n apiKeyName: data.name || 'Unknown',\r\n userId: data.created_by,\r\n allowedServerIds,\r\n permissions,\r\n roleName,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH-key authentication\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Run a child process and return { stdout, stderr, code }. Never throws. */\r\nfunction runProcess(\r\n command: string,\r\n argv: string[],\r\n options: { stdin?: string; cwd?: string } = {},\r\n): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve) => {\r\n const child = spawn(command, argv, { cwd: options.cwd, stdio: ['pipe', 'pipe', 'pipe'] });\r\n let stdout = '';\r\n let stderr = '';\r\n child.stdout.on('data', (d) => { stdout += d.toString(); });\r\n child.stderr.on('data', (d) => { stderr += d.toString(); });\r\n child.on('error', (err) => {\r\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\r\n });\r\n child.on('close', (code) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n if (options.stdin !== undefined) {\r\n child.stdin.write(options.stdin);\r\n child.stdin.end();\r\n } else {\r\n child.stdin.end();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Resolve the user's SSH public-key file from the path they passed.\r\n *\r\n * Accepts either a `.pub` file directly, or a private-key path (in which case\r\n * we look for `${path}.pub` next to it). Returns the public-key file path and\r\n * its contents trimmed.\r\n */\r\nasync function resolvePubkeyFile(input: string): Promise<{ pubPath: string; pubText: string }> {\r\n const expand = (p: string) => p.startsWith('~')\r\n ? join(process.env.HOME || process.env.USERPROFILE || '', p.slice(1))\r\n : p;\r\n const candidate = expand(input);\r\n let pubPath: string;\r\n if (candidate.endsWith('.pub')) {\r\n pubPath = candidate;\r\n } else if (existsSync(`${candidate}.pub`)) {\r\n pubPath = `${candidate}.pub`;\r\n } else if (existsSync(candidate)) {\r\n // Caller passed a public-key file without `.pub` extension; tolerate it.\r\n pubPath = candidate;\r\n } else {\r\n throw new Error(`SSH key file not found: ${candidate} (also tried ${candidate}.pub)`);\r\n }\r\n const pubText = (await readFile(pubPath, 'utf8')).trim();\r\n if (!pubText) {\r\n throw new Error(`SSH public-key file is empty: ${pubPath}`);\r\n }\r\n return { pubPath, pubText };\r\n}\r\n\r\n/**\r\n * Compute the OpenSSH SHA256 fingerprint (\"SHA256:abc...\") of a public-key\r\n * line. This matches the format that `ssh-keygen -lf <pubkey>` prints and\r\n * what we store in `dashboard_mcp_ssh_key.fingerprint_sha256`.\r\n */\r\nfunction computeOpenSshFingerprint(pubkeyLine: string): string {\r\n const parts = pubkeyLine.trim().split(/\\s+/);\r\n if (parts.length < 2 || !parts[1]) {\r\n throw new Error('Invalid SSH public-key line (expected \"<type> <base64> [comment]\")');\r\n }\r\n const bodyBytes = Buffer.from(parts[1], 'base64');\r\n const hash = createHash('sha256').update(bodyBytes).digest('base64').replace(/=+$/, '');\r\n return `SHA256:${hash}`;\r\n}\r\n\r\n/**\r\n * Sign a challenge with the user's SSH key (via ssh-agent or on-disk key).\r\n * Uses `ssh-keygen -Y sign` (SSHSIG format, OpenSSH >= 8.2).\r\n *\r\n * Returns the armored signature (\"-----BEGIN SSH SIGNATURE----- ...\").\r\n */\r\nasync function sshKeygenSign(pubkeyPath: string, challenge: string, namespace: string): Promise<string> {\r\n const result = await runProcess(\r\n 'ssh-keygen',\r\n ['-Y', 'sign', '-f', pubkeyPath, '-n', namespace, '-q'],\r\n { stdin: challenge },\r\n );\r\n if (result.code !== 0) {\r\n throw new Error(\r\n `ssh-keygen sign failed (exit ${result.code}). ` +\r\n `Make sure ssh-agent is running and has the matching private key loaded ` +\r\n `(or that the private key is at the path next to the .pub file). ` +\r\n `stderr: ${result.stderr.trim() || '(empty)'}`,\r\n );\r\n }\r\n if (!result.stdout.includes('BEGIN SSH SIGNATURE')) {\r\n throw new Error(`ssh-keygen sign produced no signature (stderr: ${result.stderr.trim() || '(empty)'})`);\r\n }\r\n return result.stdout;\r\n}\r\n\r\n/**\r\n * Verify an SSHSIG armored signature against a known public-key line.\r\n * Returns true if the signature is valid.\r\n */\r\nasync function sshKeygenVerify(\r\n pubkeyLine: string,\r\n signature: string,\r\n challenge: string,\r\n namespace: string,\r\n): Promise<boolean> {\r\n const dir = await mkdtemp(join(tmpdir(), 'mcp-ssh-verify-'));\r\n try {\r\n const allowedSigners = `mcp@local ${pubkeyLine.trim()}\\n`;\r\n const allowedPath = join(dir, 'allowed_signers');\r\n const sigPath = join(dir, 'sig');\r\n await writeFile(allowedPath, allowedSigners, 'utf8');\r\n await writeFile(sigPath, signature, 'utf8');\r\n const result = await runProcess(\r\n 'ssh-keygen',\r\n ['-Y', 'verify', '-f', allowedPath, '-I', 'mcp@local', '-n', namespace, '-s', sigPath, '-q'],\r\n { stdin: challenge },\r\n );\r\n return result.code === 0;\r\n } finally {\r\n await rm(dir, { recursive: true, force: true }).catch(() => undefined);\r\n }\r\n}\r\n\r\n/**\r\n * Authenticate to the dashboard using an SSH key.\r\n *\r\n * 1. Read the user's pubkey file and compute its SHA256 fingerprint.\r\n * 2. Generate a fresh nonce, sign it via `ssh-keygen -Y sign` (uses ssh-agent\r\n * or the private key on disk), then locally verify the signature against\r\n * the pubkey we read. This proves the caller actually possesses the\r\n * private key (or has it loaded in ssh-agent), not just a stolen pubkey.\r\n * 3. Look up the fingerprint in `dashboard_mcp_ssh_key`, require it to be\r\n * linked to the already validated API key, then load permissions exactly\r\n * like the bearer-token path does.\r\n *\r\n * The signature step is optional but defaults to ON. Set\r\n * `MG_DASHBOARD_SSH_SKIP_VERIFY=1` to skip it (e.g. for first-time enrollment\r\n * before the key is registered, where you just want to print the fingerprint).\r\n */\r\nasync function validateSshKey(\r\n pubkeyPathInput: string,\r\n expectedApiKeyId: string,\r\n): Promise<AuthContext | null> {\r\n let pubPath: string;\r\n let pubText: string;\r\n try {\r\n const resolved = await resolvePubkeyFile(pubkeyPathInput);\r\n pubPath = resolved.pubPath;\r\n pubText = resolved.pubText;\r\n } catch (err) {\r\n console.error(`SSH key error: ${err instanceof Error ? err.message : String(err)}`);\r\n return null;\r\n }\r\n\r\n let fingerprint: string;\r\n try {\r\n fingerprint = computeOpenSshFingerprint(pubText);\r\n } catch (err) {\r\n console.error(`SSH key error: ${err instanceof Error ? err.message : String(err)}`);\r\n return null;\r\n }\r\n\r\n const rateCheck = authRateLimiter.check(fingerprint);\r\n if (!rateCheck.allowed) {\r\n const retryMin = Math.ceil(rateCheck.retryAfterMs / 60_000);\r\n console.error(`Rate limited: too many failed SSH-key auth attempts. Retry in ${retryMin} minute(s).`);\r\n return null;\r\n }\r\n\r\n const skipVerify = process.env.MG_DASHBOARD_SSH_SKIP_VERIFY === '1';\r\n if (!skipVerify) {\r\n try {\r\n const challenge = randomBytes(32).toString('hex');\r\n const signature = await sshKeygenSign(pubPath, challenge, 'mg-dashboard-mcp');\r\n const verified = await sshKeygenVerify(pubText, signature, challenge, 'mg-dashboard-mcp');\r\n if (!verified) {\r\n console.error('SSH-key challenge verification failed (signature did not validate against the public key).');\r\n return null;\r\n }\r\n } catch (err) {\r\n console.error(`SSH-key challenge failed: ${err instanceof Error ? err.message : String(err)}`);\r\n console.error('Tip: set MG_DASHBOARD_SSH_SKIP_VERIFY=1 to skip the challenge if you only need to print the fingerprint for enrollment.');\r\n return null;\r\n }\r\n }\r\n\r\n const { data: keyRow, error: keyErr } = await supabase\r\n .from('dashboard_mcp_ssh_key')\r\n .select('id, name, api_key_id, is_active')\r\n .eq('fingerprint_sha256', fingerprint)\r\n .eq('is_active', true)\r\n .maybeSingle();\r\n\r\n if (keyErr || !keyRow) {\r\n console.error(\r\n `SSH key not registered (fingerprint ${fingerprint}; ${rateCheck.remaining} attempts remaining). ` +\r\n `Add it under MCP API Keys → SSH Keys in the dashboard.`,\r\n );\r\n return null;\r\n }\r\n\r\n if (keyRow.api_key_id !== expectedApiKeyId) {\r\n console.error(\r\n `SSH key \"${keyRow.name}\" is registered, but it is not linked to the provided MCP API key. ` +\r\n `Add this SSH key under the same MCP API Key entry used by --api-key.`,\r\n );\r\n return null;\r\n }\r\n\r\n const { data: apiRow, error: apiErr } = await supabase\r\n .from('dashboard_mcp_api_key')\r\n .select('id, name, created_by, allowed_server_ids, is_active, expires_at')\r\n .eq('id', keyRow.api_key_id)\r\n .eq('is_active', true)\r\n .maybeSingle();\r\n\r\n if (apiErr || !apiRow) {\r\n console.error('SSH key is linked to an inactive or missing MCP API key entry.');\r\n return null;\r\n }\r\n\r\n if (apiRow.expires_at && new Date(apiRow.expires_at) < new Date()) {\r\n console.error('Linked MCP API key entry has expired.');\r\n return null;\r\n }\r\n\r\n const { data: userData, error: userError } = await supabase\r\n .from('user')\r\n .select('permissions, role:role!role_id(name, default_permissions)')\r\n .eq('id', apiRow.created_by)\r\n .single();\r\n\r\n if (userError || !userData) {\r\n console.error(`User not found for SSH key creator: ${apiRow.created_by}`);\r\n return null;\r\n }\r\n\r\n const roleName = (userData.role as { name?: string })?.name || 'user';\r\n const roleDefaults = (userData.role as { default_permissions?: unknown })?.default_permissions ?? {};\r\n const userOverrides = userData.permissions ?? null;\r\n const permissions = resolvePermissions(roleName, roleDefaults, userOverrides);\r\n\r\n const allowedServerIds = intersectServerAccess(\r\n apiRow.allowed_server_ids,\r\n permissions.resources.ssh_servers,\r\n );\r\n\r\n const nowIso = new Date().toISOString();\r\n await Promise.all([\r\n supabase.from('dashboard_mcp_ssh_key').update({ last_used_at: nowIso }).eq('id', keyRow.id),\r\n supabase.from('dashboard_mcp_api_key').update({ last_used_at: nowIso }).eq('id', apiRow.id),\r\n ]);\r\n\r\n const moduleCount = MODULE_KEYS.filter((k) => permissions.modules[k]).length;\r\n console.error(\r\n `Authenticated via SSH key \"${keyRow.name}\" (fp ${fingerprint.slice(0, 24)}...) ` +\r\n `as user ${apiRow.created_by} (role: ${roleName}, modules: ${moduleCount}/${MODULE_KEYS.length})`,\r\n );\r\n\r\n return {\r\n apiKeyId: apiRow.id,\r\n apiKeyName: `${apiRow.name || 'Unknown'} (ssh: ${keyRow.name})`,\r\n userId: apiRow.created_by,\r\n allowedServerIds,\r\n permissions,\r\n roleName,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Server access helper\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction assertServerAccess(serverId: string): void {\r\n if (!authContext) throw new Error('Not authenticated');\r\n if (authContext.allowedServerIds === null) return;\r\n if (!authContext.allowedServerIds.includes(serverId)) {\r\n throw new Error(`Access denied: you do not have permission for server ${serverId}`);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Release profile resolution helper\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Resolve a release profile name to its stage IDs.\r\n * Returns { stageIds, profileId } or throws with available profile names.\r\n */\r\nasync function resolveReleaseProfileStageIds(\r\n profileName: string,\r\n): Promise<{ stageIds: string[]; profileId: string }> {\r\n const { data: profile, error } = await supabase\r\n .from('release_profile')\r\n .select('id, name')\r\n .ilike('name', profileName)\r\n .maybeSingle();\r\n\r\n if (error) throw new Error(`Failed to look up release profile: ${error.message}`);\r\n\r\n if (!profile) {\r\n const { data: all } = await supabase\r\n .from('release_profile')\r\n .select('name')\r\n .order('name');\r\n const names = (all || []).map((p) => p.name).join(', ');\r\n throw new Error(\r\n `Release profile \"${profileName}\" not found. Available profiles: ${names || '(none)'}`,\r\n );\r\n }\r\n\r\n const { data: stages, error: stageErr } = await supabase\r\n .from('release_profile_stage')\r\n .select('id')\r\n .eq('release_profile_id', profile.id);\r\n\r\n if (stageErr) throw new Error(`Failed to look up stages: ${stageErr.message}`);\r\n if (!stages || stages.length === 0) {\r\n throw new Error(`Release profile \"${profile.name}\" has no stages configured`);\r\n }\r\n\r\n return { stageIds: stages.map((s) => s.id), profileId: profile.id };\r\n}\r\n\r\n/**\r\n * Look up release profile names for a set of stage IDs.\r\n * Returns a map of stageId -> profileName.\r\n */\r\nasync function getProfileNamesForStageIds(\r\n stageIds: string[],\r\n): Promise<Record<string, string>> {\r\n if (stageIds.length === 0) return {};\r\n\r\n const { data: stages } = await supabase\r\n .from('release_profile_stage')\r\n .select('id, release_profile_id')\r\n .in('id', stageIds);\r\n\r\n if (!stages || stages.length === 0) return {};\r\n\r\n const profileIds = [...new Set(stages.map((s) => s.release_profile_id))];\r\n const { data: profiles } = await supabase\r\n .from('release_profile')\r\n .select('id, name')\r\n .in('id', profileIds);\r\n\r\n if (!profiles) return {};\r\n\r\n const profileMap: Record<string, string> = {};\r\n for (const p of profiles) profileMap[p.id] = p.name;\r\n\r\n const result: Record<string, string> = {};\r\n for (const s of stages) {\r\n result[s.id] = profileMap[s.release_profile_id] || 'unknown';\r\n }\r\n return result;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Encryption helpers (AES-256-GCM, compatible with dashboard encryption.ts)\r\n// ---------------------------------------------------------------------------\r\n\r\nconst ENC_ALGORITHM = 'aes-256-gcm';\r\nconst ENC_IV_LENGTH = 16;\r\nconst ENC_TAG_LENGTH = 16;\r\n\r\nfunction getEncryptionKey(): Buffer {\r\n if (!encryptionKey) throw new Error('ENCRYPTION_KEY is required for env operations');\r\n const buf = Buffer.from(encryptionKey, 'hex');\r\n if (buf.length !== 32) throw new Error('ENCRYPTION_KEY must be a 64-character hex string');\r\n return buf;\r\n}\r\n\r\nfunction encrypt(text: string): string {\r\n const key = getEncryptionKey();\r\n const iv = randomBytes(ENC_IV_LENGTH);\r\n const cipher = createCipheriv(ENC_ALGORITHM, new Uint8Array(key), new Uint8Array(iv));\r\n let encrypted = cipher.update(text, 'utf8', 'hex');\r\n encrypted += cipher.final('hex');\r\n const authTag = cipher.getAuthTag();\r\n return Buffer.concat([\r\n new Uint8Array(iv),\r\n new Uint8Array(authTag),\r\n new Uint8Array(Buffer.from(encrypted, 'hex')),\r\n ]).toString('base64');\r\n}\r\n\r\nfunction decrypt(payload: string): string {\r\n const key = getEncryptionKey();\r\n const buf = Buffer.from(payload, 'base64');\r\n const iv = buf.subarray(0, ENC_IV_LENGTH);\r\n const authTag = buf.subarray(ENC_IV_LENGTH, ENC_IV_LENGTH + ENC_TAG_LENGTH);\r\n const encrypted = buf.subarray(ENC_IV_LENGTH + ENC_TAG_LENGTH);\r\n const decipher = createDecipheriv(ENC_ALGORITHM, new Uint8Array(key), new Uint8Array(iv));\r\n decipher.setAuthTag(new Uint8Array(authTag));\r\n let decrypted = decipher.update(encrypted.toString('hex'), 'hex', 'utf8');\r\n decrypted += decipher.final('utf8');\r\n return decrypted;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Vercel env sync helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst VERCEL_API = 'https://api.vercel.com';\r\n\r\n/**\r\n * Parse a .env content string into key-value pairs.\r\n * Lines starting with # and empty lines are skipped.\r\n */\r\nfunction parseEnvContent(content: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const line of content.split('\\n')) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n const eqIdx = trimmed.indexOf('=');\r\n if (eqIdx === -1) continue;\r\n const key = trimmed.slice(0, eqIdx).trim();\r\n let value = trimmed.slice(eqIdx + 1).trim();\r\n if (\r\n (value.startsWith('\"') && value.endsWith('\"')) ||\r\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\r\n ) {\r\n value = value.slice(1, -1);\r\n }\r\n if (key) result[key] = value;\r\n }\r\n return result;\r\n}\r\n\r\ninterface VercelEnvVar {\r\n key: string;\r\n value: string;\r\n type: 'encrypted';\r\n target?: ('production' | 'preview' | 'development')[];\r\n customEnvironmentIds?: string[];\r\n}\r\n\r\ninterface StageApp {\r\n path: string;\r\n label: string;\r\n deployMethod: string;\r\n enabled: boolean;\r\n vercelProjectId?: string | null;\r\n vercelCustomEnvId?: string | null;\r\n}\r\n\r\n/**\r\n * Map stage type to Vercel target environments or custom environment ID.\r\n */\r\nfunction stageToVercelTargets(\r\n stageType: 'dev' | 'staging' | 'prod',\r\n customEnvId?: string | null,\r\n): { target?: ('production' | 'preview' | 'development')[]; customEnvironmentIds?: string[] } {\r\n if (stageType === 'prod') return { target: ['production'] };\r\n if (customEnvId) return { customEnvironmentIds: [customEnvId] };\r\n return { target: ['preview'] };\r\n}\r\n\r\n/** Dev stages also sync to built-in `development` for `vercel dev` (matches dashboard). */\r\nfunction getVercelEnvSyncTargetings(\r\n stageType: 'dev' | 'staging' | 'prod',\r\n customEnvId?: string | null,\r\n): Array<{ target?: ('production' | 'preview' | 'development')[]; customEnvironmentIds?: string[] }> {\r\n const primary = stageToVercelTargets(stageType, customEnvId);\r\n if (stageType !== 'dev') return [primary];\r\n return [primary, { target: ['development'] }];\r\n}\r\n\r\n/**\r\n * Push env vars to a Vercel project using upsert.\r\n */\r\nasync function syncEnvVarsToVercel(\r\n token: string,\r\n projectId: string,\r\n envVars: VercelEnvVar[],\r\n): Promise<{ created: number; error: string | null }> {\r\n if (envVars.length === 0) return { created: 0, error: null };\r\n\r\n const res = await fetch(\r\n `${VERCEL_API}/v10/projects/${encodeURIComponent(projectId)}/env?upsert=true`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(envVars),\r\n },\r\n );\r\n\r\n if (!res.ok) {\r\n const body = await res.text().catch(() => '');\r\n return { created: 0, error: `Vercel API ${res.status}: ${body}` };\r\n }\r\n\r\n const data = await res.json().catch(() => ({}));\r\n return { created: (data as any)?.created?.length ?? envVars.length, error: null };\r\n}\r\n\r\n/**\r\n * After an env_config upsert, attempt to sync env vars to Vercel for the\r\n * linked stage. Resolves the stage via `release_profile_stage_id` on the\r\n * record or by looking up siblings with the same `app_name`.\r\n *\r\n * Returns a status string for inclusion in the MCP response.\r\n */\r\nasync function attemptVercelSync(appName: string, environment: string, knownStageId?: string): Promise<string> {\r\n try {\r\n // 1. Find the stage linked to this app_name\r\n let stageId = knownStageId;\r\n if (!stageId) {\r\n const { data: direct } = await supabase\r\n .from('env_config')\r\n .select('release_profile_stage_id')\r\n .eq('app_name', appName)\r\n .not('release_profile_stage_id', 'is', null)\r\n .limit(1)\r\n .single();\r\n\r\n stageId = direct?.release_profile_stage_id;\r\n }\r\n if (!stageId) return 'Vercel sync skipped: no stage link found';\r\n\r\n // 2. Get Vercel token\r\n const { data: settings } = await supabase\r\n .from('app_setting')\r\n .select('vercel_token_encrypted')\r\n .maybeSingle();\r\n\r\n if (!settings?.vercel_token_encrypted) return 'Vercel sync skipped: no Vercel token configured';\r\n\r\n let token: string;\r\n try {\r\n token = decrypt(settings.vercel_token_encrypted);\r\n } catch {\r\n return 'Vercel sync failed: could not decrypt Vercel token';\r\n }\r\n\r\n // 3. Fetch stage + stage_apps\r\n const { data: stage } = await supabase\r\n .from('release_profile_stage')\r\n .select('id, stage, stage_apps')\r\n .eq('id', stageId)\r\n .single();\r\n\r\n if (!stage) return 'Vercel sync skipped: stage not found';\r\n\r\n const stageType = stage.stage as 'dev' | 'staging' | 'prod';\r\n const stageApps: StageApp[] = (stage.stage_apps as StageApp[]) || [];\r\n const vercelApps = stageApps.filter(\r\n (a) => a.deployMethod === 'vercel' && a.enabled && a.vercelProjectId,\r\n );\r\n\r\n if (vercelApps.length === 0) return 'Vercel sync skipped: no Vercel apps in stage';\r\n\r\n // 4. Fetch all env_configs for the stage\r\n const { data: envConfigs } = await supabase\r\n .from('env_config')\r\n .select('*')\r\n .eq('release_profile_stage_id', stageId);\r\n\r\n if (!envConfigs || envConfigs.length === 0) return 'Vercel sync skipped: no env configs for stage';\r\n\r\n const variantMap: Record<string, string> = {\r\n dev: 'development',\r\n staging: 'staging',\r\n prod: 'production',\r\n };\r\n const deployedVariant = variantMap[stageType] ?? stageType;\r\n\r\n // 5. Sync each Vercel app\r\n const syncResults: string[] = [];\r\n for (const app of vercelApps) {\r\n const name = app.path.replace('apps/', '');\r\n const config = envConfigs.find(\r\n (c: any) => c.app_name === name && c.variant === deployedVariant,\r\n );\r\n\r\n if (!config) {\r\n syncResults.push(`${app.label}: skipped (no config for variant \"${deployedVariant}\")`);\r\n continue;\r\n }\r\n\r\n let envContent: string;\r\n try {\r\n envContent = decrypt((config as any).env_data_encrypted);\r\n } catch {\r\n syncResults.push(`${app.label}: decrypt failed`);\r\n continue;\r\n }\r\n\r\n const pairs = parseEnvContent(envContent);\r\n const keys = Object.keys(pairs);\r\n if (keys.length === 0) {\r\n syncResults.push(`${app.label}: empty config`);\r\n continue;\r\n }\r\n\r\n const targetings = getVercelEnvSyncTargetings(stageType, app.vercelCustomEnvId);\r\n let createdTotal = 0;\r\n let lastErr: string | null = null;\r\n\r\n for (const targeting of targetings) {\r\n const envVars: VercelEnvVar[] = keys.map((key) => ({\r\n key,\r\n value: pairs[key]!,\r\n type: 'encrypted' as const,\r\n ...targeting,\r\n }));\r\n\r\n const { created, error } = await syncEnvVarsToVercel(token, app.vercelProjectId!, envVars);\r\n if (error) lastErr = error;\r\n else createdTotal += created;\r\n }\r\n\r\n if (lastErr) {\r\n syncResults.push(`${app.label}: FAILED - ${lastErr}`);\r\n } else {\r\n syncResults.push(`${app.label}: ${createdTotal} var upsert(s) synced`);\r\n }\r\n }\r\n\r\n return `Vercel sync: ${syncResults.join('; ')}`;\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n return `Vercel sync error: ${msg}`;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n// ---------------------------------------------------------------------------\r\n// Shell quoting / OS-aware command builders\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * POSIX shell single-quote escape. Wraps in `'...'` and escapes any embedded\r\n * `'` as `'\\''`. Bare-word fast-path for safe characters skips quoting.\r\n * Used by ssh-execute (linux mode), docker-exec, sftp-list pattern building,\r\n * and anywhere we previously relied on the LLM to escape `$`, `#`, spaces,\r\n * etc. inside command strings.\r\n */\r\nfunction posixQuote(arg: string): string {\r\n if (arg === '') return \"''\";\r\n if (/^[A-Za-z0-9._\\/=:@%+\\-]+$/.test(arg)) return arg;\r\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\r\n}\r\n\r\n/**\r\n * Build a POSIX shell command line from a program + argv. The program itself\r\n * is NOT quoted if it's a simple identifier/path (so `cd` / `docker compose`\r\n * keep working when passed as `command: 'docker compose'` with args).\r\n */\r\nfunction buildPosixCommand(command: string, args: string[]): string {\r\n const program = /^[A-Za-z0-9._\\/\\- ]+$/.test(command) ? command : posixQuote(command);\r\n if (args.length === 0) return program;\r\n return `${program} ${args.map(posixQuote).join(' ')}`;\r\n}\r\n\r\n/**\r\n * Build a PowerShell `-EncodedCommand` invocation. PowerShell decodes the\r\n * UTF-16LE-base64 payload itself, so embedded `$`, `'`, `\"`, `#`, spaces, etc.\r\n * never see cmd.exe parsing — this is the only quoting-safe way to call\r\n * PowerShell over SSH on Windows servers.\r\n */\r\nfunction buildPowerShellEncodedCommand(command: string, args: string[]): string {\r\n const psSingleQuote = (s: string) => \"'\" + s.replace(/'/g, \"''\") + \"'\";\r\n let body: string;\r\n if (args.length === 0) {\r\n body = command;\r\n } else {\r\n body = `& ${psSingleQuote(command)} ${args.map(psSingleQuote).join(' ')}`;\r\n }\r\n // Suppress PowerShell's progress CLIXML stream that otherwise pollutes stderr\r\n // with `<Objs Version=\"1.1.0.1\" ...>` blobs on first use of certain cmdlets.\r\n const psExpr = `$ProgressPreference='SilentlyContinue'; ${body}`;\r\n const utf16 = Buffer.from(psExpr, 'utf16le');\r\n const b64 = utf16.toString('base64');\r\n // -OutputFormat Text disables PowerShell's CLIXML serialization of errors/objects\r\n // when run as a subprocess (default is XML for non-interactive). Combined with\r\n // $ProgressPreference above, this gives clean text on stdout/stderr.\r\n return `powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand ${b64}`;\r\n}\r\n\r\ninterface SshConnectionOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\ninterface SshResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n}\r\n\r\nconst SSH_PROXY_SERVER_ID = '03659d55-e194-400d-b82a-bf6457371ded';\r\nlet _proxyConnCache: SshConnectionOptions | null = null;\r\n\r\nasync function getProxyConnection(): Promise<SshConnectionOptions> {\r\n if (_proxyConnCache) return _proxyConnCache;\r\n\r\n const { data, error } = await supabase\r\n .from('ssh_server')\r\n .select('hostname, port, username, password_encrypted, ssh_key_encrypted, ssh_key_passphrase_encrypted')\r\n .eq('id', SSH_PROXY_SERVER_ID)\r\n .single();\r\n\r\n if (error || !data) throw new Error('SSH Proxy server not found in database');\r\n if (!encryptionKey) throw new Error('ENCRYPTION_KEY required to decrypt server credentials');\r\n\r\n _proxyConnCache = {\r\n hostname: data.hostname,\r\n port: data.port || 22,\r\n username: data.username,\r\n password: data.password_encrypted ? decrypt(data.password_encrypted) : undefined,\r\n privateKey: data.ssh_key_encrypted ? decrypt(data.ssh_key_encrypted) : undefined,\r\n passphrase: data.ssh_key_passphrase_encrypted ? decrypt(data.ssh_key_passphrase_encrypted) : undefined,\r\n };\r\n return _proxyConnCache;\r\n}\r\n\r\ntype ServerOs = 'linux' | 'windows';\r\n\r\n/**\r\n * Get connection options for a server. When `allowed_ssh_ips` is configured,\r\n * also returns proxy options so callers can route through the SSH Proxy.\r\n *\r\n * Also returns the server's `os_type` so callers (notably ssh-execute) can\r\n * pick the right shell wrapper (bash vs PowerShell -EncodedCommand).\r\n */\r\nasync function getServerConnection(\r\n serverId: string,\r\n): Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions; os: ServerOs }> {\r\n assertServerAccess(serverId);\r\n\r\n const { data, error } = await supabase\r\n .from('ssh_server')\r\n .select('hostname, port, username, password_encrypted, ssh_key_encrypted, ssh_key_passphrase_encrypted, allowed_ssh_ips, os_type')\r\n .eq('id', serverId)\r\n .single();\r\n\r\n if (error || !data) throw new Error(`Server not found: ${serverId}`);\r\n if (!encryptionKey) throw new Error('ENCRYPTION_KEY required to decrypt server credentials');\r\n\r\n const conn: SshConnectionOptions = {\r\n hostname: data.hostname,\r\n port: data.port || 22,\r\n username: data.username,\r\n password: data.password_encrypted ? decrypt(data.password_encrypted) : undefined,\r\n privateKey: data.ssh_key_encrypted ? decrypt(data.ssh_key_encrypted) : undefined,\r\n passphrase: data.ssh_key_passphrase_encrypted ? decrypt(data.ssh_key_passphrase_encrypted) : undefined,\r\n };\r\n\r\n const needsProxy = data.allowed_ssh_ips !== null && serverId !== SSH_PROXY_SERVER_ID;\r\n const proxy = needsProxy ? await getProxyConnection() : undefined;\r\n const os: ServerOs = (data as { os_type?: string }).os_type === 'windows' ? 'windows' : 'linux';\r\n\r\n return { conn, proxy, os };\r\n}\r\n\r\n/**\r\n * Execute an SSH command, optionally tunnelling through a proxy (ProxyJump).\r\n * When proxy is provided, the target server only sees the proxy's IP.\r\n *\r\n * `stdin` lets callers pipe data into the remote process (used by ssh-execute\r\n * smart mode + db-* helpers to avoid command-line escape hell with passwords,\r\n * SQL queries, scripts containing `$` or `#`, etc.).\r\n */\r\nasync function sshExec(\r\n opts: SshConnectionOptions,\r\n command: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { stdin?: string; pty?: boolean },\r\n): Promise<SshResult> {\r\n if (proxy) return sshExecViaProxy(proxy, opts, command, options);\r\n\r\n return new Promise((resolve) => {\r\n const ssh = new SshClient();\r\n let stdout = '';\r\n let stderr = '';\r\n let done = false;\r\n const timeout = opts.timeout || 60_000;\r\n\r\n const timer = setTimeout(() => {\r\n if (!done) { done = true; ssh.end(); resolve({ stdout, stderr, exitCode: -1 }); }\r\n }, timeout);\r\n\r\n ssh.on('ready', () => {\r\n // Allocating a PTY collapses stderr into stdout (a real terminal has no\r\n // separate stderr fd) which is exactly what callers want for tty-mode\r\n // commands like `psql`/`mysql`/`bash`. Without pty: stderr is captured\r\n // separately so structured tools still get clean stderr.\r\n const execOpts = options?.pty ? { pty: true } : {};\r\n ssh.exec(command, execOpts, (err, stream) => {\r\n if (err) {\r\n if (!done) { done = true; clearTimeout(timer); ssh.end(); resolve({ stdout, stderr, exitCode: -1 }); }\r\n return;\r\n }\r\n stream.on('data', (d: Buffer) => { stdout += d.toString(); });\r\n stream.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\r\n stream.on('close', (code: number | null) => {\r\n if (!done) { done = true; clearTimeout(timer); ssh.end(); resolve({ stdout, stderr, exitCode: code ?? 0 }); }\r\n });\r\n if (options?.stdin !== undefined) {\r\n stream.end(options.stdin);\r\n }\r\n });\r\n });\r\n\r\n ssh.on('error', (err) => {\r\n if (!done) { done = true; clearTimeout(timer); resolve({ stdout, stderr: err.message, exitCode: -1 }); }\r\n });\r\n\r\n ssh.connect({\r\n host: opts.hostname, port: opts.port, username: opts.username,\r\n password: opts.password, privateKey: opts.privateKey, passphrase: opts.passphrase,\r\n readyTimeout: timeout,\r\n });\r\n });\r\n}\r\n\r\nfunction sshExecViaProxy(\r\n proxyOpts: SshConnectionOptions,\r\n targetOpts: SshConnectionOptions,\r\n command: string,\r\n options?: { stdin?: string; pty?: boolean },\r\n): Promise<SshResult> {\r\n return new Promise((resolve) => {\r\n const proxyClient = new SshClient();\r\n let done = false;\r\n const timeout = targetOpts.timeout || 60_000;\r\n\r\n const timer = setTimeout(() => {\r\n if (!done) { done = true; proxyClient.end(); resolve({ stdout: '', stderr: 'SSH proxy command timeout', exitCode: -1 }); }\r\n }, timeout);\r\n\r\n const cleanup = () => { clearTimeout(timer); proxyClient.end(); };\r\n\r\n proxyClient.on('ready', () => {\r\n proxyClient.forwardOut('127.0.0.1', 0, targetOpts.hostname, targetOpts.port, (err, tunnel) => {\r\n if (err) {\r\n if (!done) { done = true; cleanup(); resolve({ stdout: '', stderr: err.message, exitCode: -1 }); }\r\n return;\r\n }\r\n\r\n const targetClient = new SshClient();\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n targetClient.on('ready', () => {\r\n const execOpts = options?.pty ? { pty: true } : {};\r\n targetClient.exec(command, execOpts, (execErr, stream) => {\r\n if (execErr) {\r\n if (!done) { done = true; targetClient.end(); cleanup(); resolve({ stdout, stderr, exitCode: -1 }); }\r\n return;\r\n }\r\n stream.on('data', (d: Buffer) => { stdout += d.toString(); });\r\n stream.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\r\n stream.on('close', (code: number | null) => {\r\n if (!done) { done = true; targetClient.end(); cleanup(); resolve({ stdout, stderr, exitCode: code ?? 0 }); }\r\n });\r\n if (options?.stdin !== undefined) {\r\n stream.end(options.stdin);\r\n }\r\n });\r\n });\r\n\r\n targetClient.on('error', (targetErr) => {\r\n if (!done) { done = true; targetClient.end(); cleanup(); resolve({ stdout, stderr: targetErr.message, exitCode: -1 }); }\r\n });\r\n\r\n targetClient.connect({\r\n sock: tunnel,\r\n username: targetOpts.username, password: targetOpts.password,\r\n privateKey: targetOpts.privateKey, passphrase: targetOpts.passphrase,\r\n readyTimeout: timeout,\r\n });\r\n });\r\n });\r\n\r\n proxyClient.on('error', (err) => {\r\n if (!done) { done = true; cleanup(); resolve({ stdout: '', stderr: err.message, exitCode: -1 }); }\r\n });\r\n\r\n proxyClient.connect({\r\n host: proxyOpts.hostname, port: proxyOpts.port, username: proxyOpts.username,\r\n password: proxyOpts.password, privateKey: proxyOpts.privateKey, passphrase: proxyOpts.passphrase,\r\n readyTimeout: proxyOpts.timeout || 30_000,\r\n });\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Shared SSH connection helper (supports proxy tunnelling)\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction connectSshClient(\r\n opts: SshConnectionOptions,\r\n proxy?: SshConnectionOptions,\r\n readyTimeout = 60_000,\r\n extraConnect?: { compress?: boolean | 'force' },\r\n): Promise<{ client: SshClient; cleanup: () => void }> {\r\n const compress = extraConnect?.compress;\r\n if (!proxy) {\r\n return new Promise((resolve, reject) => {\r\n const ssh = new SshClient();\r\n ssh.on('ready', () => resolve({ client: ssh, cleanup: () => ssh.end() }));\r\n ssh.on('error', (e) => reject(e));\r\n ssh.connect({\r\n host: opts.hostname, port: opts.port, username: opts.username,\r\n password: opts.password, privateKey: opts.privateKey, passphrase: opts.passphrase,\r\n readyTimeout,\r\n ...(compress ? { compress } : {}),\r\n });\r\n });\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const proxyClient = new SshClient();\r\n\r\n proxyClient.on('ready', () => {\r\n proxyClient.forwardOut('127.0.0.1', 0, opts.hostname, opts.port, (err, tunnel) => {\r\n if (err) { proxyClient.end(); reject(err); return; }\r\n\r\n const targetClient = new SshClient();\r\n targetClient.on('ready', () =>\r\n resolve({\r\n client: targetClient,\r\n cleanup: () => { targetClient.end(); proxyClient.end(); },\r\n }),\r\n );\r\n targetClient.on('error', (e) => { proxyClient.end(); reject(e); });\r\n targetClient.connect({\r\n sock: tunnel,\r\n username: opts.username, password: opts.password,\r\n privateKey: opts.privateKey, passphrase: opts.passphrase,\r\n readyTimeout,\r\n ...(compress ? { compress } : {}),\r\n });\r\n });\r\n });\r\n\r\n proxyClient.on('error', (e) => reject(e));\r\n proxyClient.connect({\r\n host: proxy.hostname, port: proxy.port, username: proxy.username,\r\n password: proxy.password, privateKey: proxy.privateKey, passphrase: proxy.passphrase,\r\n readyTimeout: proxy.timeout || 30_000,\r\n });\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// R2 (Cloudflare S3-compatible) helpers\r\n//\r\n// The four sftp-* tools route to R2 instead of an SSH server when the caller\r\n// passes `bucket: <name>`. Credentials come from env vars (R2_ENDPOINT +\r\n// R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY), so the MCP runs against any\r\n// Cloudflare R2 account without per-call config. The bucket *name* is part of\r\n// the call so the same MCP can address multiple buckets (backup, assets, etc.).\r\n// ---------------------------------------------------------------------------\r\n\r\nimport {\r\n S3Client,\r\n ListObjectsV2Command,\r\n GetObjectCommand,\r\n PutObjectCommand,\r\n DeleteObjectCommand,\r\n DeleteObjectsCommand,\r\n HeadObjectCommand,\r\n CreateMultipartUploadCommand,\r\n UploadPartCommand,\r\n CompleteMultipartUploadCommand,\r\n AbortMultipartUploadCommand,\r\n type _Object,\r\n type CommonPrefix,\r\n} from '@aws-sdk/client-s3';\r\n\r\nlet _r2Client: S3Client | null = null;\r\n\r\nfunction getR2Client(): S3Client {\r\n if (_r2Client) return _r2Client;\r\n const endpoint = process.env.R2_ENDPOINT;\r\n const accessKeyId = process.env.R2_ACCESS_KEY_ID;\r\n const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;\r\n if (!endpoint || !accessKeyId || !secretAccessKey) {\r\n throw new Error(\r\n 'R2 not configured. Set R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY in the MCP env (mcp.json).',\r\n );\r\n }\r\n _r2Client = new S3Client({ region: 'auto', endpoint, credentials: { accessKeyId, secretAccessKey } });\r\n return _r2Client;\r\n}\r\n\r\n/** Strip a leading `/` so callers can use familiar paths (`/foo/bar.txt`)\r\n * while R2 keys are stored without the slash (`foo/bar.txt`). */\r\nfunction r2Key(path: string): string {\r\n return path.replace(/^\\/+/, '');\r\n}\r\n\r\ninterface R2ListEntry {\r\n key: string;\r\n size: number;\r\n mtime: string;\r\n isPrefix: boolean;\r\n}\r\n\r\nasync function r2List(\r\n bucket: string,\r\n prefix: string,\r\n options: { recursive: boolean; maxResults: number },\r\n): Promise<R2ListEntry[]> {\r\n const client = getR2Client();\r\n const entries: R2ListEntry[] = [];\r\n let continuationToken: string | undefined;\r\n // Folder mode uses delimiter so we get CommonPrefixes (one entry per \"directory\").\r\n // Recursive mode omits delimiter and walks every key.\r\n const delimiter = options.recursive ? undefined : '/';\r\n\r\n do {\r\n const result = await client.send(new ListObjectsV2Command({\r\n Bucket: bucket,\r\n Prefix: prefix || undefined,\r\n Delimiter: delimiter,\r\n ContinuationToken: continuationToken,\r\n MaxKeys: Math.min(1000, options.maxResults - entries.length),\r\n }));\r\n\r\n for (const cp of (result.CommonPrefixes || []) as CommonPrefix[]) {\r\n if (cp.Prefix) entries.push({ key: cp.Prefix, size: 0, mtime: '', isPrefix: true });\r\n if (entries.length >= options.maxResults) break;\r\n }\r\n for (const obj of (result.Contents || []) as _Object[]) {\r\n if (entries.length >= options.maxResults) break;\r\n entries.push({\r\n key: obj.Key || '',\r\n size: obj.Size || 0,\r\n mtime: obj.LastModified ? obj.LastModified.toISOString() : '',\r\n isPrefix: false,\r\n });\r\n }\r\n continuationToken = result.IsTruncated ? result.NextContinuationToken : undefined;\r\n } while (continuationToken && entries.length < options.maxResults);\r\n\r\n return entries;\r\n}\r\n\r\nasync function r2GetObject(bucket: string, key: string, maxBytes: number): Promise<string> {\r\n const client = getR2Client();\r\n // Cheap HEAD first so we can refuse oversized objects without downloading them.\r\n const head = await client.send(new HeadObjectCommand({ Bucket: bucket, Key: key }));\r\n const size = head.ContentLength || 0;\r\n if (size > maxBytes) {\r\n throw new Error(`Object too large: ${size} bytes (max ${maxBytes} for inline read; use sftp-write with sourcePath to mirror locally instead, or pass { offset, length } for a ranged read)`);\r\n }\r\n const result = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));\r\n const body = result.Body as unknown as { transformToString?: () => Promise<string> };\r\n if (!body?.transformToString) throw new Error('R2 returned no readable body');\r\n return body.transformToString();\r\n}\r\n\r\nasync function r2GetObjectRange(\r\n bucket: string,\r\n key: string,\r\n range: { offset: number; length?: number },\r\n): Promise<string> {\r\n const client = getR2Client();\r\n const head = await client.send(new HeadObjectCommand({ Bucket: bucket, Key: key }));\r\n const size = head.ContentLength || 0;\r\n if (range.offset >= size && size > 0) throw new Error(`offset ${range.offset} is past end of object (size ${size})`);\r\n const MAX = 1_048_576;\r\n const remaining = Math.max(0, size - range.offset);\r\n const effectiveLen = range.length !== undefined ? Math.min(range.length, remaining, MAX) : Math.min(remaining, MAX);\r\n const end = range.offset + effectiveLen - 1;\r\n // S3 Range header is inclusive on both ends.\r\n const result = await client.send(new GetObjectCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n Range: `bytes=${range.offset}-${end}`,\r\n }));\r\n const body = result.Body as unknown as { transformToString?: () => Promise<string> };\r\n if (!body?.transformToString) throw new Error('R2 returned no readable body');\r\n const text = await body.transformToString();\r\n const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;\r\n return `${header}\\n${text}`;\r\n}\r\n\r\nasync function r2PutObject(bucket: string, key: string, body: Buffer | Readable, contentLength?: number): Promise<void> {\r\n const client = getR2Client();\r\n await client.send(new PutObjectCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n Body: body,\r\n ContentLength: contentLength,\r\n ContentType: 'application/octet-stream',\r\n }));\r\n}\r\n\r\nasync function r2DeleteObject(bucket: string, key: string): Promise<void> {\r\n const client = getR2Client();\r\n await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));\r\n}\r\n\r\n/** Delete all objects under a prefix. R2's DeleteObjects supports up to 1000\r\n * keys per request, so we loop list→delete in pages. Returns deleted count. */\r\nasync function r2DeletePrefix(bucket: string, prefix: string): Promise<number> {\r\n const client = getR2Client();\r\n let deleted = 0;\r\n let continuationToken: string | undefined;\r\n do {\r\n const list = await client.send(new ListObjectsV2Command({\r\n Bucket: bucket,\r\n Prefix: prefix,\r\n ContinuationToken: continuationToken,\r\n MaxKeys: 1000,\r\n }));\r\n const keys = (list.Contents || []).map(o => o.Key).filter((k): k is string => !!k);\r\n if (keys.length === 0) break;\r\n await client.send(new DeleteObjectsCommand({\r\n Bucket: bucket,\r\n Delete: { Objects: keys.map(k => ({ Key: k })), Quiet: true },\r\n }));\r\n deleted += keys.length;\r\n continuationToken = list.IsTruncated ? list.NextContinuationToken : undefined;\r\n } while (continuationToken);\r\n return deleted;\r\n}\r\n\r\n/** Multipart upload for files larger than ~4.5 GB (R2 single-PUT limit is 5 GB\r\n * with a safety margin). Streams the local file in 100 MB parts. */\r\nconst R2_MULTIPART_THRESHOLD = 4.5 * 1024 * 1024 * 1024; // 4.5 GB\r\nconst R2_MULTIPART_PART_SIZE = 100 * 1024 * 1024; // 100 MB\r\n\r\nasync function r2PutObjectMultipart(\r\n bucket: string,\r\n key: string,\r\n localPath: string,\r\n totalBytes: number,\r\n onProgress?: (bytes: number) => void,\r\n): Promise<void> {\r\n const client = getR2Client();\r\n const create = await client.send(new CreateMultipartUploadCommand({ Bucket: bucket, Key: key }));\r\n const uploadId = create.UploadId;\r\n if (!uploadId) throw new Error('R2 returned no UploadId for multipart create');\r\n\r\n const parts: { PartNumber: number; ETag: string }[] = [];\r\n try {\r\n let partNumber = 1;\r\n let uploaded = 0;\r\n let offset = 0;\r\n while (offset < totalBytes) {\r\n const end = Math.min(offset + R2_MULTIPART_PART_SIZE, totalBytes);\r\n // Read this part into memory (100 MB max). Streaming a single part with\r\n // unknown length is unreliable across SDK versions; buffering keeps us\r\n // simple and predictable.\r\n const chunk = await new Promise<Buffer>((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n const rs = createReadStream(localPath, { start: offset, end: end - 1 });\r\n rs.on('data', (c: string | Buffer) => { chunks.push(typeof c === 'string' ? Buffer.from(c) : c); });\r\n rs.on('end', () => resolve(Buffer.concat(chunks.map(b => new Uint8Array(b)))));\r\n rs.on('error', reject);\r\n });\r\n const partResult = await client.send(new UploadPartCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n UploadId: uploadId,\r\n PartNumber: partNumber,\r\n Body: chunk,\r\n ContentLength: chunk.length,\r\n }));\r\n if (!partResult.ETag) throw new Error(`Part ${partNumber} returned no ETag`);\r\n parts.push({ PartNumber: partNumber, ETag: partResult.ETag });\r\n uploaded += chunk.length;\r\n onProgress?.(uploaded);\r\n offset = end;\r\n partNumber++;\r\n }\r\n await client.send(new CompleteMultipartUploadCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n UploadId: uploadId,\r\n MultipartUpload: { Parts: parts },\r\n }));\r\n } catch (e) {\r\n // Best-effort abort to avoid orphaned parts (R2 charges for them).\r\n try { await client.send(new AbortMultipartUploadCommand({ Bucket: bucket, Key: key, UploadId: uploadId })); } catch { /* ignore */ }\r\n throw e;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SFTP helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction sanitizePath(path: string): string {\r\n let normalized = path.replace(/\\\\/g, '/').replace(/\\0/g, '');\r\n const parts = normalized.split('/');\r\n const resolved: string[] = [];\r\n for (const part of parts) {\r\n if (part === '..') { if (resolved.length > 0 && resolved[resolved.length - 1] !== '') resolved.pop(); }\r\n else if (part !== '.' && part !== '') resolved.push(part);\r\n }\r\n return '/' + resolved.join('/');\r\n}\r\n\r\nconst PROTECTED_PATHS = ['/etc/', '/boot/', '/usr/', '/bin/', '/sbin/', '/lib/', '/lib64/'];\r\n\r\nfunction assertWritablePath(path: string): void {\r\n const safe = sanitizePath(path);\r\n for (const p of PROTECTED_PATHS) {\r\n if (safe === p.slice(0, -1) || safe.startsWith(p)) {\r\n throw new Error(`Write access denied to protected path: ${safe}`);\r\n }\r\n }\r\n}\r\n\r\n/** Convert a glob pattern (`*`, `?`, character classes) to a RegExp anchored\r\n * to the basename only. Used by sftp-list for filtering. */\r\nfunction globToRegExp(pattern: string): RegExp {\r\n let re = '';\r\n for (const c of pattern) {\r\n if (c === '*') re += '.*';\r\n else if (c === '?') re += '.';\r\n else if (/[.+^${}()|[\\]\\\\]/.test(c)) re += '\\\\' + c;\r\n else re += c;\r\n }\r\n return new RegExp(`^${re}$`);\r\n}\r\n\r\ninterface SftpEntry {\r\n kind: 'd' | '-';\r\n size: number;\r\n mtime: string; // ISO; '' if unknown\r\n mtimeMs: number; // 0 if unknown; used for sorting\r\n path: string; // full or basename (depending on recursive mode)\r\n}\r\n\r\nasync function sftpReaddir(\r\n opts: SshConnectionOptions,\r\n dirPath: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { recursive?: boolean; maxDepth?: number; pattern?: string; maxResults?: number },\r\n): Promise<{ entries: SftpEntry[]; truncated: boolean; error?: string }> {\r\n const recursive = options?.recursive === true;\r\n const maxDepth = Math.max(1, Math.min(20, options?.maxDepth ?? 5));\r\n const maxResults = Math.max(1, Math.min(50_000, options?.maxResults ?? 5_000));\r\n const matcher = options?.pattern ? globToRegExp(options.pattern) : null;\r\n const rootSafe = sanitizePath(dirPath);\r\n\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 30_000);\r\n cleanup = c;\r\n return await new Promise<{ entries: SftpEntry[]; truncated: boolean; error?: string }>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve({ entries: [], truncated: false, error: 'timeout' }); cleanup = undefined; }, 60_000);\r\n\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve({ entries: [], truncated: false, error: err.message }); return; }\r\n\r\n const entries: SftpEntry[] = [];\r\n let truncated = false;\r\n const errors: string[] = [];\r\n\r\n const readOne = (path: string, depth: number): Promise<void> =>\r\n new Promise((resolveOne) => {\r\n sftp.readdir(path, (err2, list) => {\r\n if (err2) {\r\n errors.push(`error reading ${path}: ${err2.message}`);\r\n return resolveOne();\r\n }\r\n const subdirs: string[] = [];\r\n for (const item of list) {\r\n if (entries.length >= maxResults) { truncated = true; break; }\r\n const mode = item.attrs.mode || 0;\r\n const isDir = (mode & 0o170000) === 0o040000;\r\n const size = item.attrs.size || 0;\r\n const mtimeMs = item.attrs.mtime ? item.attrs.mtime * 1000 : 0;\r\n const mtime = mtimeMs ? new Date(mtimeMs).toISOString() : '';\r\n const fullPath = path === '/' ? `/${item.filename}` : `${path}/${item.filename}`;\r\n const include = !matcher || matcher.test(item.filename);\r\n if (include) {\r\n entries.push({ kind: isDir ? 'd' : '-', size, mtime, mtimeMs, path: recursive ? fullPath : item.filename });\r\n }\r\n if (isDir && recursive && depth < maxDepth) subdirs.push(fullPath);\r\n }\r\n if (truncated || subdirs.length === 0) return resolveOne();\r\n // Walk subdirs sequentially to keep one SFTP session calm.\r\n (async () => {\r\n for (const sub of subdirs) {\r\n if (truncated) break;\r\n await readOne(sub, depth + 1);\r\n }\r\n resolveOne();\r\n })();\r\n });\r\n });\r\n\r\n readOne(rootSafe, 1).then(() => {\r\n clearTimeout(timer);\r\n cleanup?.(); cleanup = undefined;\r\n resolve({ entries, truncated, error: errors.length ? errors.join('; ') : undefined });\r\n });\r\n });\r\n });\r\n } catch (e: any) {\r\n cleanup?.();\r\n return { entries: [], truncated: false, error: e.message };\r\n }\r\n}\r\n\r\nasync function sftpRead(\r\n opts: SshConnectionOptions,\r\n filePath: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { offset?: number; length?: number },\r\n): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n const offset = Math.max(0, Math.floor(options?.offset ?? 0));\r\n // Cap at 1 MiB regardless of how much the caller asks for; LLM context can't\r\n // sensibly absorb more than that and large reads should use SFTP→local file.\r\n const MAX = 1_048_576;\r\n const requestedLen = options?.length !== undefined ? Math.max(0, Math.floor(options.length)) : undefined;\r\n\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 60_000);\r\n cleanup = c;\r\n return await new Promise<string>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve('Error: timeout'); cleanup = undefined; }, 60_000);\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\r\n sftp.stat(safe, (err2, stats) => {\r\n if (err2) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err2.message}`); return; }\r\n const total = stats.size || 0;\r\n if (offset >= total && total > 0) {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Error: offset ${offset} is past end of file (size ${total})`);\r\n return;\r\n }\r\n const remaining = Math.max(0, total - offset);\r\n // Effective read length = caller-requested OR remaining-from-offset,\r\n // whichever is smaller, but never above MAX. In whole-file mode (no\r\n // offset/length) we still refuse files >MAX so the contract matches.\r\n const effectiveLen = requestedLen !== undefined\r\n ? Math.min(requestedLen, remaining, MAX)\r\n : Math.min(remaining, MAX);\r\n const isWholeFileRequest = options === undefined || (offset === 0 && requestedLen === undefined);\r\n if (isWholeFileRequest && total > MAX) {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Error: file too large (${total} bytes, max ${MAX}). Use { offset, length } for ranged reads.`);\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n // ssh2 createReadStream supports `start` (inclusive) and `end` (inclusive).\r\n const rs = sftp.createReadStream(safe, { start: offset, end: offset + effectiveLen - 1 });\r\n rs.on('data', (ch: Buffer) => chunks.push(ch));\r\n rs.on('end', () => {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n const text = Buffer.concat(chunks.map(ch => new Uint8Array(ch))).toString('utf-8');\r\n // For ranged reads, prepend a one-line header so the LLM knows the\r\n // window. Whole-file reads stay unchanged for backwards compat.\r\n if (!isWholeFileRequest) {\r\n const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;\r\n resolve(`${header}\\n${text}`);\r\n } else {\r\n resolve(text);\r\n }\r\n });\r\n rs.on('error', (e: Error) => { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${e.message}`); });\r\n });\r\n });\r\n });\r\n } catch (e: any) {\r\n cleanup?.();\r\n return `Error: ${e.message}`;\r\n }\r\n}\r\n\r\n// SFTP tuning. ssh2 fastPut uses 64 concurrent in-flight WRITE packets which\r\n// gives near-linerate throughput on modern OpenSSH (>= 8.6). The 64 KiB chunk\r\n// size is the safe upper bound for servers without the limits@openssh.com\r\n// extension; with it most OpenSSH builds happily accept up to 256 KiB.\r\nconst SFTP_FASTPUT_CONCURRENCY = 64;\r\nconst SFTP_FASTPUT_CHUNK_SIZE = 65_536;\r\n// Watchdog: kill the upload if no progress is observed for this long. Reset on\r\n// every fastPut step callback. Tighter than a wall-clock timeout because it\r\n// adapts to file size automatically.\r\nconst SFTP_IDLE_TIMEOUT_MS = 120_000;\r\n// Inline writes have no progress events, so we use a wall-clock cap.\r\nconst SFTP_INLINE_TIMEOUT_MS = 60_000;\r\nconst SFTP_PROGRESS_LOG_BYTES = 50 * 1024 * 1024;\r\n\r\nexport type SftpWriteInput =\r\n | { content: string }\r\n | { sourcePath: string };\r\n\r\nfunction formatBytes(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;\r\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;\r\n}\r\n\r\nasync function sftpWrite(\r\n opts: SshConnectionOptions,\r\n filePath: string,\r\n input: SftpWriteInput,\r\n proxy?: SshConnectionOptions,\r\n meta?: { fileMode?: number; mtimeMs?: number },\r\n): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\r\n\r\n // File permission bits: caller may override (e.g. 0o755 for executable).\r\n // Default 0o644 keeps existing behaviour for plain config writes.\r\n const fileMode = meta?.fileMode !== undefined ? (meta.fileMode & 0o7777) : 0o644;\r\n\r\n // Validate source up-front so the LLM gets a clear error before we open SSH.\r\n let mode: 'content' | 'sourcePath';\r\n let inlineBuffer: Buffer | undefined;\r\n let localPath: string | undefined;\r\n let expectedBytes = 0;\r\n\r\n if ('content' in input && typeof input.content === 'string') {\r\n mode = 'content';\r\n inlineBuffer = Buffer.from(input.content, 'utf-8');\r\n expectedBytes = inlineBuffer.length;\r\n } else if ('sourcePath' in input && typeof input.sourcePath === 'string') {\r\n mode = 'sourcePath';\r\n localPath = input.sourcePath;\r\n if (!isAbsolute(localPath)) return `Error: sourcePath must be an absolute path: ${localPath}`;\r\n if (!existsSync(localPath)) return `Error: sourcePath does not exist: ${localPath}`;\r\n const st = statSync(localPath);\r\n if (!st.isFile()) return `Error: sourcePath is not a regular file: ${localPath}`;\r\n expectedBytes = st.size;\r\n } else {\r\n return 'Error: sftp-write requires exactly one of: content (string) or sourcePath (absolute local path)';\r\n }\r\n\r\n // For inline text we leave SSH compression enabled (cheap, often 5-10x for\r\n // configs/scripts). For sourcePath we disable it: large files are usually\r\n // already-compressed (zip/jpg/mp4/dump.gz) and SSH-level compression then\r\n // wastes CPU and slows the transfer.\r\n const compress = mode === 'content';\r\n const startedAt = Date.now();\r\n let cleanup: (() => void) | undefined;\r\n\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 60_000, { compress });\r\n cleanup = c;\r\n\r\n return await new Promise<string>((resolve) => {\r\n let resolved = false;\r\n let bytesWritten = 0;\r\n\r\n const finish = (msg: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n watchdog?.cancel();\r\n wallTimer && clearTimeout(wallTimer);\r\n cleanup?.();\r\n cleanup = undefined;\r\n resolve(msg);\r\n };\r\n\r\n // For sourcePath: idle watchdog reset on every fastPut step.\r\n // For content: simple wall-clock timeout.\r\n let watchdog: { reset: () => void; cancel: () => void } | undefined;\r\n let wallTimer: NodeJS.Timeout | undefined;\r\n\r\n if (mode === 'sourcePath') {\r\n const armWatchdog = () => {\r\n let timer: NodeJS.Timeout = setTimeout(\r\n () => finish(`Error: idle timeout (no SFTP progress for ${SFTP_IDLE_TIMEOUT_MS / 1000}s, wrote ${formatBytes(bytesWritten)} of ${formatBytes(expectedBytes)})`),\r\n SFTP_IDLE_TIMEOUT_MS,\r\n );\r\n return {\r\n reset: () => { clearTimeout(timer); timer = setTimeout(\r\n () => finish(`Error: idle timeout (no SFTP progress for ${SFTP_IDLE_TIMEOUT_MS / 1000}s, wrote ${formatBytes(bytesWritten)} of ${formatBytes(expectedBytes)})`),\r\n SFTP_IDLE_TIMEOUT_MS,\r\n ); },\r\n cancel: () => clearTimeout(timer),\r\n };\r\n };\r\n watchdog = armWatchdog();\r\n } else {\r\n wallTimer = setTimeout(\r\n () => finish(`Error: timeout after ${SFTP_INLINE_TIMEOUT_MS / 1000}s`),\r\n SFTP_INLINE_TIMEOUT_MS,\r\n );\r\n }\r\n\r\n client.sftp((err, sftp) => {\r\n if (err) return finish(`Error: ${err.message}`);\r\n\r\n // Apply mtime after a successful write. SFTP `setstat` with atime+mtime\r\n // is the standard way; we leave atime equal to mtime (close enough for\r\n // tooling that cares about freshness). Errors are surfaced as a warning\r\n // suffix so the upload itself is still considered successful.\r\n const applyMtime = (then: (suffix: string) => void) => {\r\n if (meta?.mtimeMs === undefined) return then('');\r\n const secs = Math.floor(meta.mtimeMs / 1000);\r\n sftp.setstat(safe, { atime: secs, mtime: secs }, (statErr) => {\r\n then(statErr ? ` (mtime set failed: ${statErr.message})` : ` (mtime=${new Date(meta.mtimeMs!).toISOString()})`);\r\n });\r\n };\r\n\r\n if (mode === 'content') {\r\n const ws = sftp.createWriteStream(safe, { mode: fileMode });\r\n ws.on('error', (e: Error) => finish(`Error: ${e.message}`));\r\n ws.on('close', () => {\r\n const elapsed = Date.now() - startedAt;\r\n applyMtime((suffix) => finish(`Written ${expectedBytes} bytes to ${safe} in ${elapsed}ms (mode=0o${fileMode.toString(8)})${suffix}`));\r\n });\r\n ws.end(inlineBuffer!);\r\n return;\r\n }\r\n\r\n // sourcePath path: ssh2 fastPut does the heavy lifting (parallel\r\n // pipelined SFTP_WRITE packets). Step callback gives us progress for\r\n // the watchdog and periodic logs.\r\n let nextProgressLog = SFTP_PROGRESS_LOG_BYTES;\r\n sftp.fastPut(\r\n localPath!,\r\n safe,\r\n {\r\n concurrency: SFTP_FASTPUT_CONCURRENCY,\r\n chunkSize: SFTP_FASTPUT_CHUNK_SIZE,\r\n mode: fileMode,\r\n fileSize: expectedBytes,\r\n step: (transferred: number) => {\r\n bytesWritten = transferred;\r\n watchdog?.reset();\r\n if (transferred >= nextProgressLog) {\r\n console.error(\r\n `[sftp-write] ${formatBytes(transferred)} / ${formatBytes(expectedBytes)} → ${safe}`,\r\n );\r\n nextProgressLog += SFTP_PROGRESS_LOG_BYTES;\r\n }\r\n },\r\n },\r\n (fpErr) => {\r\n if (fpErr) return finish(`Error: ${fpErr.message}`);\r\n const elapsed = Date.now() - startedAt;\r\n const mbps = expectedBytes / (1024 * 1024) / Math.max(0.001, elapsed / 1000);\r\n applyMtime((suffix) => finish(\r\n `Uploaded ${formatBytes(expectedBytes)} from ${localPath} to ${safe} ` +\r\n `in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s, mode=0o${fileMode.toString(8)})${suffix}`,\r\n ));\r\n },\r\n );\r\n });\r\n });\r\n } catch (e: unknown) {\r\n cleanup?.();\r\n return `Error: ${e instanceof Error ? e.message : String(e)}`;\r\n }\r\n}\r\n\r\nasync function sftpDelete(\r\n opts: SshConnectionOptions,\r\n filePath: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { recursive?: boolean },\r\n): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\r\n const recursive = options?.recursive === true;\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 30_000);\r\n cleanup = c;\r\n return await new Promise<string>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve('Error: timeout'); cleanup = undefined; }, 60_000);\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\r\n\r\n // Recursive directory removal: walk the tree depth-first via SFTP and\r\n // unlink files / rmdir dirs from the bottom up. Pure SFTP — no shell\r\n // shenanigans, so it works on Windows OpenSSH too.\r\n if (recursive) {\r\n const removeTree = async (target: string): Promise<{ files: number; dirs: number }> => {\r\n return new Promise((resolveTree) => {\r\n sftp.stat(target, (statErr, stats) => {\r\n if (statErr) return resolveTree({ files: 0, dirs: 0 });\r\n const mode = stats.mode || 0;\r\n const isDir = (mode & 0o170000) === 0o040000;\r\n if (!isDir) {\r\n sftp.unlink(target, () => resolveTree({ files: 1, dirs: 0 }));\r\n return;\r\n }\r\n sftp.readdir(target, async (rdErr, list) => {\r\n if (rdErr) return resolveTree({ files: 0, dirs: 0 });\r\n let files = 0; let dirs = 0;\r\n for (const item of list) {\r\n const child = target === '/' ? `/${item.filename}` : `${target}/${item.filename}`;\r\n const r = await removeTree(child);\r\n files += r.files; dirs += r.dirs;\r\n }\r\n sftp.rmdir(target, () => resolveTree({ files, dirs: dirs + 1 }));\r\n });\r\n });\r\n });\r\n };\r\n removeTree(safe).then(({ files, dirs }) => {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Removed ${safe} recursively (${files} files, ${dirs} directories)`);\r\n });\r\n return;\r\n }\r\n\r\n sftp.unlink(safe, (unlinkErr) => {\r\n if (unlinkErr) {\r\n sftp.rmdir(safe, (rmdirErr) => {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(rmdirErr ? `Error: ${unlinkErr.message}` : `Deleted directory ${safe}`);\r\n });\r\n } else {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Deleted file ${safe}`);\r\n }\r\n });\r\n });\r\n });\r\n } catch (e: any) {\r\n cleanup?.();\r\n return `Error: ${e.message}`;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Safety: dangerous command blocklist\r\n// ---------------------------------------------------------------------------\r\n\r\nconst BLOCKED_COMMANDS = [\r\n 'rm -rf /', 'rm -fr /', 'mkfs', 'dd if=', ':(){ :|:& };:',\r\n 'shutdown', 'halt', 'init 0', 'init 6',\r\n '> /dev/sda', 'mv /* /dev/null', 'chmod -R 000 /',\r\n];\r\n\r\nfunction assertSafeCommand(command: string): void {\r\n const lower = command.toLowerCase().trim();\r\n for (const blocked of BLOCKED_COMMANDS) {\r\n if (lower.includes(blocked)) {\r\n throw new Error(`Blocked dangerous command pattern: \"${blocked}\"`);\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// MySQL / Database helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface DbCredentials {\r\n host: string;\r\n user: string;\r\n password: string;\r\n database: string;\r\n port: number;\r\n sitePath: string;\r\n appType: string;\r\n}\r\n\r\n/**\r\n * Discovers web applications under /var/www and extracts DB credentials\r\n * from their config files (WordPress, PrestaShop, Laravel, custom .env).\r\n */\r\nasync function discoverSiteDatabases(conn: SshConnectionOptions, proxy?: SshConnectionOptions): Promise<DbCredentials[]> {\r\n const script = `\r\ncheck_dir() {\r\n local base=\"$1\" root=\"$2\"\r\n # WordPress\r\n if [ -f \"$root/wp-config.php\" ]; then\r\n echo \"WP|$base|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_NAME'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_USER'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_PASSWORD'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_HOST'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\"\r\n return\r\n fi\r\n # PrestaShop 1.7+\r\n if [ -f \"$root/app/config/parameters.php\" ]; then\r\n echo \"PS|$base|$(grep -oP \"'database_name'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_user'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_password'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_host'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\"\r\n return\r\n fi\r\n # PrestaShop 1.6\r\n if [ -f \"$root/config/settings.inc.php\" ]; then\r\n echo \"PS|$base|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_NAME_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_USER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_PASSWD_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_SERVER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\"\r\n return\r\n fi\r\n # Laravel / generic .env\r\n if [ -f \"$root/.env\" ]; then\r\n DB_CONN=$(grep -oP '^DB_CONNECTION=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n if [ -n \"$DB_CONN\" ] && [ \"$DB_CONN\" != \"sqlite\" ]; then\r\n echo \"ENV|$base|$(grep -oP '^DB_DATABASE=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_USERNAME=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_PASSWORD=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_HOST=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_PORT=\\\\K.*' \"$root/.env\" 2>/dev/null)\"\r\n return\r\n fi\r\n fi\r\n}\r\nfor dir in /var/www/*/; do\r\n [ -d \"$dir\" ] || continue\r\n check_dir \"$dir\" \"$dir\"\r\n # Also check common subdirectories: html, public_html, public, httpdocs\r\n for sub in html public_html public httpdocs; do\r\n [ -d \"$dir$sub\" ] && check_dir \"$dir\" \"$dir$sub\"\r\n done\r\ndone\r\n`.trim();\r\n\r\n const result = await sshExec(conn, script, proxy);\r\n const sites: DbCredentials[] = [];\r\n\r\n for (const line of result.stdout.split('\\n')) {\r\n if (!line.trim()) continue;\r\n const parts = line.split('|');\r\n if (parts.length < 6) continue;\r\n\r\n const [type, sitePath, database, user, password, host, port] = parts;\r\n if (!database || !user || !type || !sitePath) continue;\r\n\r\n const appTypes: Record<string, string> = { WP: 'WordPress', PS: 'PrestaShop', ENV: 'Laravel/.env' };\r\n\r\n sites.push({\r\n appType: appTypes[type] || type,\r\n sitePath: sitePath.replace(/\\/$/, ''),\r\n database,\r\n user,\r\n password: password || '',\r\n host: host || 'localhost',\r\n port: parseInt(port || '3306', 10),\r\n });\r\n }\r\n\r\n return sites;\r\n}\r\n\r\nfunction escapeMysqlShell(value: string): string {\r\n return value.replace(/'/g, \"'\\\\''\");\r\n}\r\n\r\nconst BLOCKED_SQL_PATTERNS = [\r\n /\\bDROP\\s+DATABASE\\b/i,\r\n /\\bDROP\\s+TABLE\\b/i,\r\n /\\bDROP\\s+INDEX\\b/i,\r\n /\\bTRUNCATE\\b/i,\r\n /\\bALTER\\s+TABLE\\s+\\w+\\s+DROP\\b/i,\r\n /\\bDELETE\\s+FROM\\s+\\w+\\s*$/i,\r\n];\r\n\r\nfunction assertSafeSql(query: string): void {\r\n const trimmed = query.trim();\r\n for (const pattern of BLOCKED_SQL_PATTERNS) {\r\n if (pattern.test(trimmed)) {\r\n throw new Error(`Blocked destructive SQL pattern: ${pattern.source}`);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Builds a shell snippet that discovers DB credentials for a site path\r\n * and then executes a MySQL query, all in a single SSH session.\r\n */\r\nfunction buildSiteMysqlCommand(sitePath: string, query: string): string {\r\n const safePath = escapeMysqlShell(sitePath.replace(/\\/$/, ''));\r\n const safeQuery = escapeMysqlShell(query);\r\n\r\n return `\r\nSITE='${safePath}'\r\nDB_USER=\"\" DB_PASS=\"\" DB_NAME=\"\" DB_HOST=\"localhost\" DB_PORT=\"3306\"\r\nfor root in \"$SITE\" \"$SITE/html\" \"$SITE/public_html\" \"$SITE/public\" \"$SITE/httpdocs\"; do\r\n [ -d \"$root\" ] || continue\r\n if [ -f \"$root/wp-config.php\" ]; then\r\n DB_NAME=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_NAME'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n DB_USER=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_USER'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n DB_PASS=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_PASSWORD'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n DB_HOST=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_HOST'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n break\r\n elif [ -f \"$root/app/config/parameters.php\" ]; then\r\n DB_NAME=$(grep -oP \"'database_name'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n DB_USER=$(grep -oP \"'database_user'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n DB_PASS=$(grep -oP \"'database_password'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n DB_HOST=$(grep -oP \"'database_host'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n break\r\n elif [ -f \"$root/config/settings.inc.php\" ]; then\r\n DB_NAME=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_NAME_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n DB_USER=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_USER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n DB_PASS=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_PASSWD_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n DB_HOST=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_SERVER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n break\r\n elif [ -f \"$root/.env\" ]; then\r\n DB_CONN=$(grep -oP '^DB_CONNECTION=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n if [ -n \"$DB_CONN\" ] && [ \"$DB_CONN\" != \"sqlite\" ]; then\r\n DB_NAME=$(grep -oP '^DB_DATABASE=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_USER=$(grep -oP '^DB_USERNAME=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_PASS=$(grep -oP '^DB_PASSWORD=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_HOST=$(grep -oP '^DB_HOST=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_PORT=$(grep -oP '^DB_PORT=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n break\r\n fi\r\n fi\r\ndone\r\n[ -z \"$DB_NAME\" ] || [ -z \"$DB_USER\" ] && echo \"ERROR: No database config found at $SITE\" && exit 1\r\nDB_HOST=\\${DB_HOST:-localhost}\r\nDB_PORT=\\${DB_PORT:-3306}\r\nmysql --user=\"$DB_USER\" --password=\"$DB_PASS\" --host=\"$DB_HOST\" --port=\"$DB_PORT\" -t -e '${safeQuery}' \"$DB_NAME\" 2>&1 | grep -v \"\\\\[Warning\\\\].*password\"\r\n`.trim();\r\n}\r\n\r\n/**\r\n * Execute a MySQL query for a site in a single SSH session.\r\n * Discovers credentials and runs the query in one command.\r\n */\r\nasync function execSiteMysql(conn: SshConnectionOptions, sitePath: string, query: string, proxy?: SshConnectionOptions): Promise<string> {\r\n const cmd = buildSiteMysqlCommand(sitePath, query);\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = (result.stdout || '').trim();\r\n if (output.startsWith('ERROR: No database config found')) {\r\n throw new Error(output);\r\n }\r\n if (result.exitCode !== 0 && !output) {\r\n throw new Error(result.stderr || 'MySQL command failed');\r\n }\r\n return output;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// mijn.host API helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst MIJNHOST_BASE_URL = 'https://mijn.host/api/v2';\r\n\r\ninterface MijnHostApiResponse<T = unknown> {\r\n status: number;\r\n status_description: string;\r\n data: T;\r\n}\r\n\r\nfunction requireMijnhostApiKey(): string {\r\n if (!mijnhostApiKey) {\r\n throw new Error('mijn.host API key not configured. Use --mijnhost-api-key=xxx or set MIJNHOST_API_KEY');\r\n }\r\n return mijnhostApiKey;\r\n}\r\n\r\nasync function mijnhostFetch<T>(path: string, options: RequestInit = {}): Promise<MijnHostApiResponse<T>> {\r\n const key = requireMijnhostApiKey();\r\n\r\n const res = await fetch(`${MIJNHOST_BASE_URL}${path}`, {\r\n ...options,\r\n headers: {\r\n 'API-Key': key,\r\n 'Accept': 'application/json',\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': 'mg-dashboard-mcp/2.2.0',\r\n ...((options.headers as Record<string, string>) || {}),\r\n },\r\n });\r\n\r\n const json: unknown = await res.json();\r\n const body = json as MijnHostApiResponse<T>;\r\n\r\n if (!res.ok) {\r\n throw new Error(body?.status_description || `mijn.host API error: ${res.status}`);\r\n }\r\n\r\n return body;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\nconst TOOLS = [\r\n {\r\n name: 'list-servers',\r\n description:\r\n 'List all SSH servers you have access to. Returns id, name, hostname, tags, and os_type per server. ' +\r\n 'Pass `includeStats: true` to also probe each server in parallel for container count, disk-free, and uptime ' +\r\n '(skips unreachable hosts gracefully).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n includeStats: { type: 'boolean', description: 'When true, probe each server (in parallel, with timeout) for container count, disk-free, and uptime.' },\r\n statsParallelism: { type: 'number', description: 'Max parallel probes when includeStats is true (default 8, cap 20).' },\r\n statsTimeoutMs: { type: 'number', description: 'Per-server probe timeout in ms when includeStats is true (default 6000, range 1000-30000).' },\r\n },\r\n },\r\n },\r\n {\r\n name: 'ssh-execute',\r\n description:\r\n 'Execute a command on a remote server via SSH. OS-aware: bash on linux, `powershell -EncodedCommand` (UTF-16LE base64) on windows, so $, #, quotes, spaces inside `args` are never re-interpreted by a shell. Some dangerous commands are blocked. Use `list-servers` first to see each server\\'s os_type.\\n' +\r\n 'Two ways to invoke (use `args` for anything with passwords or special chars):\\n' +\r\n '- Quick: `command` only, e.g. `command: \"df -h\"`.\\n' +\r\n '- Safe: `command` + `args[]`, e.g. `command: \"mysql\"`, `args: [\"-u\",\"root\",\"-p$tr@nge#pwd\",\"-e\",\"SELECT 1\"]`.\\n' +\r\n '`stdin` pipes data into the remote process (queries, scripts, secrets) without putting it on the command line.\\n' +\r\n '`cwd` sets the working directory (auto `cd` on Linux / `Set-Location` on Windows).\\n' +\r\n 'Fan-out: pass `serverIds: [id1, id2, ...]` (instead of `serverId`) to run the same command across multiple servers in parallel. Each server\\'s output is grouped under its own `=== name (os, exit N) ===` header.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of one SSH server. Mutually exclusive with serverIds.' },\r\n serverIds: { type: 'array', items: { type: 'string' }, description: 'Fan-out: list of server UUIDs to run the command on in parallel. Mutually exclusive with serverId.' },\r\n command: { type: 'string', description: 'Program/command to run (e.g. \"mysql\", \"Get-Service\", \"df\"). Required.' },\r\n args: { type: 'array', items: { type: 'string' }, description: 'Optional argv list. When provided, each entry is safely quoted/encoded for the target OS.' },\r\n stdin: { type: 'string', description: 'Optional data piped to the remote process stdin.' },\r\n cwd: { type: 'string', description: 'Working directory on the remote (cd <cwd> on Linux, Set-Location on Windows).' },\r\n shell: { type: 'string', enum: ['auto', 'bash', 'powershell'], description: 'Override shell selection (default \"auto\" uses the server\\'s os_type).' },\r\n parallelism: { type: 'number', description: 'Max concurrent SSH sessions when using serverIds[] (default 5, max 20).' },\r\n timeout: { type: 'number', description: 'Per-server timeout in milliseconds (default: 60000)' },\r\n },\r\n required: ['command'],\r\n },\r\n },\r\n {\r\n name: 'sftp-list',\r\n description:\r\n 'List files in remote storage. Two backends (provide exactly one of `serverId` or `bucket`):\\n' +\r\n '- `serverId`: list a directory on an SSH server via SFTP. Supports recursive traversal, depth cap, and glob filtering (no need for `ssh-execute \"find ...\"`).\\n' +\r\n '- `bucket`: list objects in a Cloudflare R2 bucket. `path` becomes the key prefix. Default folder mode groups by `/` delimiter; pass `recursive: true` for a flat listing of all keys under the prefix. Requires R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY env vars on the MCP.\\n\\n' +\r\n 'Sorting/summary applies to both backends: `sortBy` (name|size|mtime) + `reverse`. `summary: true` returns just totals (file count, dir count, total bytes) — useful as a cheap pre-flight before pulling a full listing.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'Directory path (SSH) or key prefix (R2). Default: /' },\r\n recursive: { type: 'boolean', description: 'Walk into subdirectories / list all keys flat (default false)' },\r\n maxDepth: { type: 'number', description: 'Maximum recursion depth for SSH mode (1-20, default 5). Ignored for R2.' },\r\n pattern: { type: 'string', description: 'Glob pattern to filter basenames (e.g. \"*.conf\", \"wp-*.php\").' },\r\n maxResults: { type: 'number', description: 'Cap total entries returned (default 5000, max 50000)' },\r\n sortBy: { type: 'string', enum: ['name', 'size', 'mtime'], description: 'Sort order (default `name`). Directories always come first within each ordering.' },\r\n reverse: { type: 'boolean', description: 'Reverse sort direction (e.g. largest-first or newest-first).' },\r\n summary: { type: 'boolean', description: 'Return only totals (file count, directory count, total bytes) instead of the full listing.' },\r\n },\r\n },\r\n },\r\n {\r\n name: 'sftp-read',\r\n description:\r\n 'Read a text file from remote storage (max 1 MiB). Two backends (provide exactly one of `serverId` or `bucket`):\\n' +\r\n '- `serverId`: read from an SSH server via SFTP.\\n' +\r\n '- `bucket`: read an object from a Cloudflare R2 bucket. `path` is the object key.\\n\\n' +\r\n 'Use `offset` and/or `length` for ranged reads — perfect for sampling a slice of a multi-MB log/dump without exceeding the 1 MiB inline limit. Ranged reads include a `# range: bytes A-B of TOTAL` header so you know what window you got.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'File path (SSH) or object key (R2)' },\r\n offset: { type: 'number', description: 'Byte offset to start reading from (0-indexed). Triggers ranged read mode.' },\r\n length: { type: 'number', description: 'Number of bytes to read (capped at 1 MiB). Defaults to remaining-from-offset when omitted.' },\r\n },\r\n required: ['path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-write',\r\n description:\r\n 'Write a file to remote storage. Two backends (provide exactly one of `serverId` or `bucket`) and two source modes (provide exactly one of `content` or `sourcePath`):\\n\\n' +\r\n 'Backends:\\n' +\r\n '- `serverId`: SSH server via SFTP. Protected system paths blocked. Optional `mode` sets POSIX permission bits (e.g. 0o755 for executables) and `mtime` sets the modification time.\\n' +\r\n '- `bucket`: Cloudflare R2 bucket (S3-compatible). Single PUT for files <4.5 GB, automatic multipart upload (100 MB parts) for larger files up to ~5 TB. `mode`/`mtime` are ignored on R2.\\n\\n' +\r\n 'Sources:\\n' +\r\n '- `content` (string): inline UTF-8 text. Practical max ~1 MB.\\n' +\r\n '- `sourcePath` (absolute local path): streams the local file. SSH uses ssh2 fastPut (64 parallel pipelined writes); R2 uses streamed PUT or multipart depending on size. Both handle GB-scale files. Only usable when the MCP runs locally.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'Remote file path (SSH) or object key (R2)' },\r\n content: { type: 'string', description: 'Inline UTF-8 file content (mutually exclusive with sourcePath)' },\r\n sourcePath: { type: 'string', description: 'Absolute local file path to upload (mutually exclusive with content). Use for files >1 MB or any binary.' },\r\n mode: { oneOf: [{ type: 'number' }, { type: 'string' }], description: 'POSIX file permission bits (SSH only). Number (0o755 / 493) or octal string (\"755\" / \"0o755\"). Default 0o644.' },\r\n mtime: { oneOf: [{ type: 'number' }, { type: 'string' }], description: 'File modification time (SSH only). ms-since-epoch number or ISO-8601 date string.' },\r\n },\r\n required: ['path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-delete',\r\n description:\r\n 'Delete a file (or directory tree) from remote storage. Two backends (provide exactly one of `serverId` or `bucket`):\\n' +\r\n '- `serverId`: delete a file or empty directory on an SSH server via SFTP. Protected system paths blocked. With `recursive: true` walks the tree depth-first via SFTP and removes files + empty dirs from the bottom up (works on Windows OpenSSH too — no shell tricks).\\n' +\r\n '- `bucket`: delete an object from a Cloudflare R2 bucket. `path` is the object key. With `recursive: true`, treats `path` as a key prefix and batch-deletes every object beneath it (R2 caps at 1000 keys per call; we loop pages automatically).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'File path / object key (or directory / key prefix when recursive)' },\r\n recursive: { type: 'boolean', description: 'Recursively remove a directory tree (SSH) or all objects under a key prefix (R2).' },\r\n },\r\n required: ['path'],\r\n },\r\n },\r\n {\r\n name: 'docker-list',\r\n description:\r\n 'List Docker containers on a remote server. Sorted by compose project then name, with a HEALTH column (healthy / unhealthy / starting / no-check). Filter by `nameFilter` (string OR array of substring/glob entries — passes if ANY entry matches), restrict to compose containers with `composeOnly`, or group output per project with `groupByProject`.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n format: { type: 'string', enum: ['table', 'json'], description: 'Output format: human table (default) or NDJSON (one JSON object per line, includes labels).' },\r\n composeOnly: { type: 'boolean', description: 'Only show containers that have a docker-compose project label.' },\r\n nameFilter: { oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }], description: 'Filter by container name. Single entry or array; each entry is glob (* or ?) or substring. A row passes when ANY entry matches.' },\r\n groupByProject: { type: 'boolean', description: 'Group output per compose project with a `=== project (count) ===` header.' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'docker-logs',\r\n description:\r\n 'Get logs from one or more Docker containers. `containerName` accepts a string OR an array — multi-container output is line-prefixed with `[name]` so you can read related services together (e.g. `[\"refront-rest-1\", \"refront-kong-1\", \"refront-db-1\"]`). Supports time-window (`since`), server-side `grep`, line-count (`tail`), and real-time follow (`followSeconds`). Always merges stderr into stdout.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n containerName: { oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }], description: 'Single container name/ID or an array for multi-container tail. Multi mode prefixes each line with [name].' },\r\n tail: { type: 'number', description: 'Number of recent log lines per container (default 100). Alias: `lines`.' },\r\n lines: { type: 'number', description: 'Deprecated alias for `tail`. Prefer `tail`.' },\r\n since: { type: 'string', description: 'Time window, e.g. \"10m\", \"2h\", \"24h\", or an absolute \"2026-05-09T10:00:00\".' },\r\n grep: { type: 'string', description: 'Case-insensitive regex/literal filter applied server-side (saves tokens for noisy containers).' },\r\n followSeconds: { type: 'number', description: 'When >0, stream new log lines for N seconds via `docker logs -f`, then exit (max 300). Multi-container follow runs all streams in parallel.' },\r\n },\r\n required: ['serverId', 'containerName'],\r\n },\r\n },\r\n {\r\n name: 'docker-exec',\r\n description:\r\n 'Run a command inside a running Docker container. `args[]` are quoted safely (no shell-escape hell with $ or quotes). Optional `stdin` pipes data into the container process (for SQL, scripts, etc.). Pass `interactive: true` to allocate a TTY (`docker exec -it`) so commands like `psql`/`mysql`/`bash` produce human-friendly output. Use this instead of `ssh-execute \"docker exec ...\"`.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n container: { type: 'string', description: 'Container name or ID' },\r\n command: { type: 'string', description: 'Program to run inside the container (e.g. \"psql\", \"wp\", \"node\").' },\r\n args: { type: 'array', items: { type: 'string' }, description: 'Argument list, each safely quoted.' },\r\n stdin: { type: 'string', description: 'Optional data piped to the container process stdin.' },\r\n interactive: { type: 'boolean', description: 'Allocate a TTY (`docker exec -it`). Useful for tools that probe isatty(stdout) — collapses stderr into stdout when enabled.' },\r\n workdir: { type: 'string', description: 'Working directory inside the container (-w).' },\r\n user: { type: 'string', description: 'User to run as inside the container (-u).' },\r\n timeout: { type: 'number', description: 'Timeout in milliseconds (default: 60000)' },\r\n },\r\n required: ['serverId', 'container', 'command'],\r\n },\r\n },\r\n {\r\n name: 'docker-compose',\r\n description:\r\n 'Run a docker-compose action against a project on a remote server. Replaces the common `ssh-execute \"cd /opt/x && docker compose ...\"` pattern. Action enum keeps the surface tiny.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n projectPath: { type: 'string', description: 'Absolute path to the directory containing docker-compose.yml.' },\r\n action: { type: 'string', enum: ['up', 'down', 'restart', 'logs', 'ps', 'pull', 'build'], description: 'Compose action.' },\r\n service: { type: 'string', description: 'Optional service name to scope the action to (e.g. \"studio\"). Omit to act on the whole project.' },\r\n tail: { type: 'number', description: 'For `logs`: number of lines (default 200).' },\r\n timeout: { type: 'number', description: 'Timeout in milliseconds (default: 120000 — compose ops can be slow).' },\r\n },\r\n required: ['serverId', 'projectPath', 'action'],\r\n },\r\n },\r\n {\r\n name: 'db-discover',\r\n description: 'Scan /var/www on a server for web applications (WordPress, PrestaShop, Laravel, .env) and list their database credentials. Use this first to find available sites before running other db-* tools.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'db-tables',\r\n description: 'List all tables in a site database with row counts and sizes. Credentials are auto-discovered from the site config files (wp-config.php, parameters.php, .env).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n sitePath: { type: 'string', description: 'Site root path (e.g. /var/www/example.com)' },\r\n },\r\n required: ['serverId', 'sitePath'],\r\n },\r\n },\r\n {\r\n name: 'db-describe',\r\n description: 'Show the structure of a database table (columns, types, keys, defaults). Credentials are auto-discovered from site config files.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n sitePath: { type: 'string', description: 'Site root path (e.g. /var/www/example.com)' },\r\n table: { type: 'string', description: 'Table name' },\r\n },\r\n required: ['serverId', 'sitePath', 'table'],\r\n },\r\n },\r\n {\r\n name: 'db-query',\r\n description: 'Execute a SQL query on a site database. Credentials are auto-discovered from site config files. Destructive operations (DROP, TRUNCATE) are blocked.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n sitePath: { type: 'string', description: 'Site root path (e.g. /var/www/example.com)' },\r\n query: { type: 'string', description: 'SQL query to execute' },\r\n },\r\n required: ['serverId', 'sitePath', 'query'],\r\n },\r\n },\r\n {\r\n name: 'env-list',\r\n description: 'List all stored environment configurations with their release profile names.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n releaseProfile: { type: 'string', description: 'Release profile name to filter by (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Omit to list all.' },\r\n },\r\n },\r\n },\r\n {\r\n name: 'env-get',\r\n description: 'Retrieve the decrypted .env content for a specific app and environment.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n appName: { type: 'string', description: 'Application name (e.g. backoffice, api, web)' },\r\n environment: { type: 'string', enum: ['production', 'staging', 'development', 'local'], description: 'Environment name' },\r\n releaseProfile: { type: 'string', description: 'Release profile name (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Required when multiple profiles exist. Use env-list to discover available profiles.' },\r\n },\r\n required: ['appName', 'environment'],\r\n },\r\n },\r\n {\r\n name: 'env-store',\r\n description: 'Store or update an encrypted .env configuration for an app and environment.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n appName: { type: 'string', description: 'Application name (e.g. backoffice, api, web)' },\r\n environment: { type: 'string', enum: ['production', 'staging', 'development', 'local'], description: 'Environment name' },\r\n content: { type: 'string', description: 'The .env file content to store' },\r\n description: { type: 'string', description: 'Optional description' },\r\n releaseProfile: { type: 'string', description: 'Release profile name (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Required when multiple profiles exist. Use env-list to discover available profiles.' },\r\n },\r\n required: ['appName', 'environment', 'content'],\r\n },\r\n },\r\n {\r\n name: 'cache-purge',\r\n description: 'Purge ALL caches on a server in one operation: OPcache (kills lsphp), LiteSpeed cache, WordPress object cache (wp-cli or file-based), PrestaShop Smarty/app cache, Redis FLUSHALL, and Memcached flush. Returns a per-cache status report.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n // ----- Domains (mijn.host) -----\r\n {\r\n name: 'domain-list',\r\n description: 'List all domains from the mijn.host account. Returns domain name, status, renewal date, and tags. Requires MIJNHOST_API_KEY.',\r\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\r\n },\r\n {\r\n name: 'dns-list',\r\n description: 'List all DNS records for a domain. Returns type (A, AAAA, CNAME, MX, TXT, etc.), name, value, and TTL for each record.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n },\r\n required: ['domain'],\r\n },\r\n },\r\n {\r\n name: 'dns-create',\r\n description: 'Add a new DNS record to a domain. Uses PATCH to add without replacing existing records.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n type: { type: 'string', description: 'Record type: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, or TLSA' },\r\n name: { type: 'string', description: 'Record name (e.g. @ or subdomain)' },\r\n value: { type: 'string', description: 'Record value (e.g. IP address, hostname)' },\r\n ttl: { type: 'number', description: 'TTL in seconds (min 60, default 3600)' },\r\n },\r\n required: ['domain', 'type', 'name', 'value'],\r\n },\r\n },\r\n {\r\n name: 'dns-update',\r\n description: 'Update an existing DNS record. Identifies the record by type+name+oldValue, then replaces it with new values via PATCH.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n type: { type: 'string', description: 'Record type: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, or TLSA' },\r\n name: { type: 'string', description: 'Record name' },\r\n oldValue: { type: 'string', description: 'Current value of the record to update' },\r\n newValue: { type: 'string', description: 'New value for the record' },\r\n ttl: { type: 'number', description: 'New TTL in seconds (min 60)' },\r\n },\r\n required: ['domain', 'type', 'name', 'oldValue', 'newValue'],\r\n },\r\n },\r\n {\r\n name: 'dns-delete',\r\n description: 'Delete a DNS record by type, name, and value. Fetches all records, removes the matching one, then replaces the full set.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n type: { type: 'string', description: 'Record type to delete' },\r\n name: { type: 'string', description: 'Record name to delete' },\r\n value: { type: 'string', description: 'Record value to delete (must match exactly)' },\r\n },\r\n required: ['domain', 'type', 'name', 'value'],\r\n },\r\n },\r\n // ----- Trigger.dev -----\r\n ...TRIGGER_TOOLS,\r\n // ----- Agent Reporting -----\r\n ...AGENT_TOOLS,\r\n];\r\n\r\n// ---------------------------------------------------------------------------\r\n// MCP Server\r\n// ---------------------------------------------------------------------------\r\n\r\nconst MCP_VERSION = '3.7.0';\r\n\r\nasync function handleListTools() {\r\n if (!authContext) return { tools: TOOLS };\r\n\r\n const accessible = TOOLS.filter((tool) => {\r\n const requiredModule = TOOL_MODULE_MAP[tool.name];\r\n if (!requiredModule) return true;\r\n return authContext!.permissions.modules[requiredModule] === true;\r\n });\r\n\r\n return { tools: accessible };\r\n}\r\n\r\nasync function handleCallTool(request: { params: { name: string; arguments?: Record<string, unknown> } }) {\r\n if (!authContext) {\r\n return { content: [{ type: 'text', text: 'Error: not authenticated' }] };\r\n }\r\n\r\n const { name, arguments: toolArgs } = request.params;\r\n const a = (toolArgs || {}) as Record<string, unknown>;\r\n\r\n // Module-level permission check\r\n const requiredModule = TOOL_MODULE_MAP[name];\r\n if (requiredModule && authContext.permissions.modules[requiredModule] !== true) {\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Access denied: you do not have permission for the \"${requiredModule}\" module (tool: ${name})`,\r\n }],\r\n };\r\n }\r\n\r\n const startTime = Date.now();\r\n const serverId = (a.serverId || a.server_id) as string | undefined;\r\n\r\n const result = await executeToolCall(name, a, serverId);\r\n const durationMs = Date.now() - startTime;\r\n const isError = result.content?.[0]?.text?.startsWith('Error:');\r\n void writeAuditLog({\r\n toolName: name,\r\n arguments: a,\r\n serverId,\r\n resultStatus: isError ? 'error' : 'success',\r\n errorMessage: isError ? result.content?.[0]?.text : undefined,\r\n durationMs,\r\n });\r\n return result;\r\n}\r\n\r\nasync function executeToolCall(\r\n name: string,\r\n a: Record<string, unknown>,\r\n _serverId: string | undefined,\r\n): Promise<{ content: { type: string; text: string }[] }> {\r\n const ctx = authContext!;\r\n\r\n try {\r\n switch (name) {\r\n // ----- Servers -----\r\n case 'list-servers': {\r\n let query = supabase\r\n .from('ssh_server')\r\n .select('id, name, hostname, port, username, tags, hosted_by, os_type, created_at')\r\n .order('name');\r\n\r\n if (ctx.allowedServerIds !== null) {\r\n query = query.in('id', ctx.allowedServerIds);\r\n }\r\n\r\n const { data, error } = await query;\r\n if (error) throw new Error(error.message);\r\n\r\n const includeStats = a.includeStats === true;\r\n const servers = data || [];\r\n\r\n // Stats are opt-in because they require an SSH round-trip per server.\r\n // We probe in parallel with a short per-server timeout so a single\r\n // unreachable host can't stall the listing.\r\n type Stats = { containers?: number; diskFreeHuman?: string; uptimeHuman?: string; reachable: boolean; error?: string };\r\n let statsByServer: Map<string, Stats> = new Map();\r\n if (includeStats && servers.length > 0) {\r\n const parallelism = Math.max(1, Math.min(20, Number(a.statsParallelism) || 8));\r\n const probeTimeoutMs = Math.max(1000, Math.min(30_000, Number(a.statsTimeoutMs) || 6000));\r\n\r\n // Combined one-shot probe per server. Three pipe-delimited values:\r\n // <containerCount>|<diskFreeHuman>|<uptimeHuman>\r\n // Missing tools are tolerated (returns 0/N/A).\r\n const linuxProbe =\r\n \"echo \\\"$(docker ps -q 2>/dev/null | wc -l)|$(df -h / 2>/dev/null | awk 'NR==2{print $4}')|$(uptime -p 2>/dev/null || uptime)\\\"\";\r\n const windowsProbe = [\r\n \"$ProgressPreference='SilentlyContinue';\",\r\n \"$c = (docker ps -q 2>$null | Measure-Object).Count;\",\r\n \"$d = try { '{0:N1} GB' -f ((Get-PSDrive C).Free/1GB) } catch { 'N/A' };\",\r\n \"$u = try { (Get-Uptime).ToString() } catch { ((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime).ToString() };\",\r\n \"Write-Output \\\"$c|$d|$u\\\"\",\r\n ].join(' ');\r\n\r\n const probeOne = async (s: typeof servers[number]): Promise<[string, Stats]> => {\r\n try {\r\n const { conn, proxy, os } = await getServerConnection(s.id);\r\n conn.timeout = probeTimeoutMs;\r\n const wrapped = os === 'windows'\r\n ? buildPowerShellEncodedCommand(windowsProbe, [])\r\n : `bash -c ${posixQuote(linuxProbe)}`;\r\n const result = await sshExec(conn, wrapped, proxy);\r\n if (result.exitCode !== 0) {\r\n return [s.id, { reachable: false, error: (result.stderr || result.stdout || 'probe failed').trim().slice(0, 120) }];\r\n }\r\n const parts = result.stdout.trim().split('|');\r\n return [s.id, {\r\n reachable: true,\r\n containers: Number(parts[0]) || 0,\r\n diskFreeHuman: (parts[1] || '').trim() || 'N/A',\r\n uptimeHuman: (parts[2] || '').trim() || 'N/A',\r\n }];\r\n } catch (err) {\r\n return [s.id, { reachable: false, error: err instanceof Error ? err.message.slice(0, 120) : String(err).slice(0, 120) }];\r\n }\r\n };\r\n\r\n // Bounded parallelism so we don't open 50 SSH sessions at once.\r\n const results: Array<[string, Stats]> = [];\r\n for (let i = 0; i < servers.length; i += parallelism) {\r\n const batch = servers.slice(i, i + parallelism);\r\n const chunk = await Promise.all(batch.map(probeOne));\r\n results.push(...chunk);\r\n }\r\n statsByServer = new Map(results);\r\n }\r\n\r\n const lines = servers.map(s => {\r\n const tags = Array.isArray(s.tags) ? (s.tags as string[]).join(', ') : '';\r\n const os = (s as Record<string, unknown>).os_type || 'linux';\r\n const base = `${s.id} ${s.name} ${s.hostname}:${s.port} ${s.username} [${tags}] ${s.hosted_by || ''} os:${os}`;\r\n if (!includeStats) return base;\r\n const st = statsByServer.get(s.id);\r\n if (!st) return `${base} stats:skipped`;\r\n if (!st.reachable) return `${base} UNREACHABLE (${st.error || 'unknown'})`;\r\n return `${base} containers:${st.containers} disk_free:${st.diskFreeHuman} uptime:${st.uptimeHuman}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: lines.length ? lines.join('\\n') : 'No servers found' }] };\r\n }\r\n\r\n // ----- SSH -----\r\n case 'ssh-execute': {\r\n const command = String(a.command);\r\n assertSafeCommand(command);\r\n const args = Array.isArray(a.args) ? (a.args as unknown[]).map(String) : undefined;\r\n const stdin = typeof a.stdin === 'string' ? a.stdin : undefined;\r\n const shellOverride = typeof a.shell === 'string' ? (a.shell as 'auto' | 'bash' | 'powershell') : 'auto';\r\n const cwd = typeof a.cwd === 'string' && a.cwd ? a.cwd : undefined;\r\n const timeoutMs = a.timeout ? Number(a.timeout) : undefined;\r\n\r\n // Resolve target list. `serverIds` (array) wins over `serverId` (single).\r\n // Both forms are supported so the existing `serverId` API stays intact.\r\n const targetIds: string[] = Array.isArray(a.serverIds) && a.serverIds.length > 0\r\n ? (a.serverIds as unknown[]).map(String)\r\n : a.serverId ? [String(a.serverId)] : [];\r\n if (targetIds.length === 0) {\r\n return { content: [{ type: 'text', text: 'Error: pass either `serverId` or `serverIds[]`' }] };\r\n }\r\n\r\n const parallelism = Math.max(1, Math.min(20, Number(a.parallelism) || 5));\r\n\r\n // Per-server runner. Resolves connection, builds OS-aware command, runs.\r\n const runOne = async (serverId: string): Promise<{ serverId: string; serverName: string; os: ServerOs; shell: 'bash' | 'powershell'; result: SshResult }> => {\r\n const { conn, proxy, os } = await getServerConnection(serverId);\r\n if (timeoutMs) conn.timeout = timeoutMs;\r\n const shell = shellOverride === 'auto' ? (os === 'windows' ? 'powershell' : 'bash') : shellOverride;\r\n\r\n // Build the program-with-args portion first, then prepend cwd.\r\n let body: string;\r\n if (args && args.length > 0) {\r\n body = shell === 'powershell'\r\n ? buildPowerShellEncodedCommand(command, args)\r\n : buildPosixCommand(command, args);\r\n } else if (shell === 'powershell' && !/^powershell\\b/i.test(command.trim())) {\r\n // For Windows raw strings, still wrap so $/quotes don't get reinterpreted.\r\n body = buildPowerShellEncodedCommand(command, []);\r\n } else {\r\n body = command;\r\n }\r\n\r\n // Apply cwd. For PowerShell with EncodedCommand, we can't simply\r\n // prepend `cd ... && ...` because `body` is already a full\r\n // `powershell -EncodedCommand <b64>` invocation. Instead we re-encode\r\n // a wrapper script that does `Set-Location` then runs the original.\r\n let finalCmd = body;\r\n if (cwd) {\r\n if (shell === 'bash') {\r\n finalCmd = `cd ${posixQuote(cwd)} && ${body}`;\r\n } else {\r\n // body is `powershell ... -EncodedCommand <b64>`; pull out the b64.\r\n // Wrap as: powershell -EC <NEW_b64>, where NEW = `Set-Location ...; <decoded original>`.\r\n const ecMatch = body.match(/-EncodedCommand\\s+(\\S+)$/);\r\n if (ecMatch) {\r\n const decoded = Buffer.from(ecMatch[1] as string, 'base64').toString('utf16le');\r\n const wrapped = `Set-Location -LiteralPath '${cwd.replace(/'/g, \"''\")}'; ${decoded}`;\r\n const reencoded = Buffer.from(wrapped, 'utf16le').toString('base64');\r\n finalCmd = body.replace(/-EncodedCommand\\s+\\S+$/, `-EncodedCommand ${reencoded}`);\r\n }\r\n }\r\n }\r\n\r\n const result = await sshExec(conn, finalCmd, proxy, stdin !== undefined ? { stdin } : undefined);\r\n // Best-effort fetch of server name for output headers (only matters in fan-out).\r\n let serverName = serverId;\r\n try {\r\n const { data } = await supabase.from('ssh_server').select('name').eq('id', serverId).single();\r\n if (data?.name) serverName = data.name as string;\r\n } catch { /* fall back to id */ }\r\n return { serverId, serverName, os, shell, result };\r\n };\r\n\r\n // Single-target: keep the original output format unchanged.\r\n if (targetIds.length === 1) {\r\n const { os, shell, result } = await runOne(targetIds[0] as string);\r\n const output = [`Exit code: ${result.exitCode} (os: ${os}, shell: ${shell})`];\r\n if (result.stdout) output.push(`--- stdout ---\\n${result.stdout}`);\r\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\r\n return { content: [{ type: 'text', text: output.join('\\n') }] };\r\n }\r\n\r\n // Fan-out: bounded parallel execution. We run in batches of `parallelism`.\r\n const allResults: Array<Awaited<ReturnType<typeof runOne>> | { serverId: string; error: string }> = [];\r\n for (let i = 0; i < targetIds.length; i += parallelism) {\r\n const batch = targetIds.slice(i, i + parallelism);\r\n const settled = await Promise.allSettled(batch.map(id => runOne(id)));\r\n for (let j = 0; j < settled.length; j++) {\r\n const s = settled[j]!;\r\n if (s.status === 'fulfilled') allResults.push(s.value);\r\n else allResults.push({ serverId: batch[j] as string, error: s.reason instanceof Error ? s.reason.message : String(s.reason) });\r\n }\r\n }\r\n\r\n // Render per-server sections + a 1-line summary at the bottom.\r\n const sections: string[] = [];\r\n let okCount = 0;\r\n let failCount = 0;\r\n for (const r of allResults) {\r\n if ('error' in r) {\r\n failCount++;\r\n sections.push(`=== ${r.serverId} === !! connection error: ${r.error}`);\r\n continue;\r\n }\r\n if (r.result.exitCode === 0) okCount++; else failCount++;\r\n const header = `=== ${r.serverName} (${r.os}, exit ${r.result.exitCode}) ===`;\r\n const parts = [header];\r\n if (r.result.stdout) parts.push(r.result.stdout.trimEnd());\r\n if (r.result.stderr) parts.push(`[stderr] ${r.result.stderr.trimEnd()}`);\r\n sections.push(parts.join('\\n'));\r\n }\r\n sections.push(`--- fan-out summary: ${okCount} ok / ${failCount} failed across ${allResults.length} servers (parallelism ${parallelism}) ---`);\r\n return { content: [{ type: 'text', text: sections.join('\\n\\n') }] };\r\n }\r\n\r\n // ----- SFTP -----\r\n case 'sftp-list': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n const recursive = a.recursive === true;\r\n const maxResults = Math.max(1, Math.min(50_000, Number(a.maxResults) || 5_000));\r\n const pattern = typeof a.pattern === 'string' ? a.pattern : '';\r\n const summary = a.summary === true;\r\n // Sort key: 'name' (default), 'size', 'mtime'. `reverse: true` flips.\r\n const sortBy = (a.sortBy === 'size' || a.sortBy === 'mtime' || a.sortBy === 'name') ? a.sortBy : 'name';\r\n const reverse = a.reverse === true;\r\n\r\n // Collect into a backend-agnostic shape so sort/reverse/summary apply\r\n // identically to SSH and R2 listings.\r\n let entries: SftpEntry[];\r\n let truncated = false;\r\n let warning = '';\r\n\r\n if (bucket) {\r\n const prefix = r2Key(String(a.path || ''));\r\n const matcher = pattern ? globToRegExp(pattern) : null;\r\n const r2Entries = await r2List(bucket, prefix, { recursive, maxResults });\r\n const filtered = matcher\r\n ? r2Entries.filter(e => matcher.test(e.key.split('/').pop() || e.key))\r\n : r2Entries;\r\n entries = filtered.map(e => {\r\n const ms = e.mtime ? Date.parse(e.mtime) : 0;\r\n return {\r\n kind: e.isPrefix ? 'd' as const : '-' as const,\r\n size: e.size,\r\n mtime: e.mtime,\r\n mtimeMs: Number.isFinite(ms) ? ms : 0,\r\n path: e.key,\r\n };\r\n });\r\n } else {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sftpReaddir(conn, String(a.path || '/'), proxy, {\r\n recursive,\r\n maxDepth: typeof a.maxDepth === 'number' ? a.maxDepth : undefined,\r\n pattern: pattern || undefined,\r\n maxResults,\r\n });\r\n if (result.error && result.entries.length === 0) {\r\n return { content: [{ type: 'text', text: `Error: ${result.error}` }] };\r\n }\r\n entries = result.entries;\r\n truncated = result.truncated;\r\n if (result.error) warning = result.error;\r\n }\r\n\r\n // Summary mode short-circuits before sorting (we just aggregate).\r\n if (summary) {\r\n const files = entries.filter(e => e.kind === '-');\r\n const dirs = entries.filter(e => e.kind === 'd');\r\n const totalSize = files.reduce((acc, e) => acc + (e.size || 0), 0);\r\n const lines = [\r\n `Files: ${files.length}`,\r\n `Directories: ${dirs.length}`,\r\n `Total size: ${totalSize} bytes (${(totalSize / (1024 * 1024)).toFixed(2)} MB)`,\r\n ];\r\n if (truncated) lines.push(`(truncated at ${maxResults}; counts may be partial)`);\r\n if (warning) lines.push(`(warnings: ${warning})`);\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n // Sort. Directories first within the chosen sort, both ascending by\r\n // default; `reverse: true` flips the secondary order. `name` uses\r\n // localeCompare so digits/dots sort naturally.\r\n entries.sort((x, y) => {\r\n if (x.kind !== y.kind) return x.kind === 'd' ? -1 : 1;\r\n let cmp = 0;\r\n if (sortBy === 'size') cmp = x.size - y.size;\r\n else if (sortBy === 'mtime') cmp = x.mtimeMs - y.mtimeMs;\r\n else cmp = x.path.localeCompare(y.path);\r\n return reverse ? -cmp : cmp;\r\n });\r\n\r\n if (entries.length === 0) return { content: [{ type: 'text', text: 'No entries' }] };\r\n const lines = entries.map(e => {\r\n const sizeCol = e.kind === 'd' && bucket ? '(prefix)' : String(e.size);\r\n return `${e.kind} ${sizeCol.padStart(10)} ${(e.mtime || '').padEnd(24)} ${e.path}`;\r\n });\r\n if (truncated) lines.push(`... (truncated at ${maxResults} entries; raise maxResults or narrow path/pattern)`);\r\n if (warning) lines.push(`! ${warning}`);\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n case 'sftp-read': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n const offset = a.offset !== undefined ? Math.max(0, Number(a.offset)) : undefined;\r\n const length = a.length !== undefined ? Math.max(0, Number(a.length)) : undefined;\r\n const hasRange = offset !== undefined || length !== undefined;\r\n\r\n if (bucket) {\r\n const key = r2Key(String(a.path));\r\n if (!key) return { content: [{ type: 'text', text: 'Error: path is required' }] };\r\n try {\r\n if (hasRange) {\r\n const content = await r2GetObjectRange(bucket, key, { offset: offset ?? 0, length });\r\n return { content: [{ type: 'text', text: content }] };\r\n }\r\n const content = await r2GetObject(bucket, key, 1_048_576);\r\n return { content: [{ type: 'text', text: content }] };\r\n } catch (e) {\r\n return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };\r\n }\r\n }\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const content = await sftpRead(conn, String(a.path), proxy, hasRange ? { offset, length } : undefined);\r\n return { content: [{ type: 'text', text: content }] };\r\n }\r\n\r\n case 'sftp-write': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n // Optional file metadata. `mode` accepts a number (0o755) or a string\r\n // (\"755\" or \"0o755\") so the LLM can write either form. mtime accepts\r\n // ms since epoch or an ISO date string.\r\n let fileMode: number | undefined;\r\n if (typeof a.mode === 'number' && Number.isFinite(a.mode)) fileMode = a.mode & 0o7777;\r\n else if (typeof a.mode === 'string' && a.mode) {\r\n const cleaned = a.mode.replace(/^0o?/i, '');\r\n const parsed = parseInt(cleaned, 8);\r\n if (!Number.isNaN(parsed)) fileMode = parsed & 0o7777;\r\n }\r\n let mtimeMs: number | undefined;\r\n if (typeof a.mtime === 'number' && Number.isFinite(a.mtime)) mtimeMs = a.mtime;\r\n else if (typeof a.mtime === 'string' && a.mtime) {\r\n const parsed = Date.parse(a.mtime);\r\n if (!Number.isNaN(parsed)) mtimeMs = parsed;\r\n }\r\n\r\n if (bucket) {\r\n const key = r2Key(String(a.path));\r\n if (!key) return { content: [{ type: 'text', text: 'Error: path is required' }] };\r\n if (fileMode !== undefined || mtimeMs !== undefined) {\r\n // R2 (S3) has no POSIX mode/mtime. Surface this so the user knows\r\n // the params were ignored rather than silently dropping them.\r\n // We continue with the upload anyway.\r\n }\r\n try {\r\n if (typeof a.sourcePath === 'string' && a.sourcePath.length > 0) {\r\n const local = a.sourcePath;\r\n if (!isAbsolute(local)) return { content: [{ type: 'text', text: `Error: sourcePath must be an absolute path: ${local}` }] };\r\n if (!existsSync(local)) return { content: [{ type: 'text', text: `Error: sourcePath does not exist: ${local}` }] };\r\n const st = statSync(local);\r\n if (!st.isFile()) return { content: [{ type: 'text', text: `Error: sourcePath is not a regular file: ${local}` }] };\r\n const startedAt = Date.now();\r\n if (st.size > R2_MULTIPART_THRESHOLD) {\r\n // Multipart path: streams the local file in 100 MB parts and\r\n // logs progress per part. Up to ~5 TB per object on R2.\r\n let lastLog = 0;\r\n await r2PutObjectMultipart(bucket, key, local, st.size, (uploaded) => {\r\n if (uploaded - lastLog >= 500 * 1024 * 1024) {\r\n console.error(`[r2-write] ${formatBytes(uploaded)} / ${formatBytes(st.size)} → r2://${bucket}/${key}`);\r\n lastLog = uploaded;\r\n }\r\n });\r\n const elapsed = Date.now() - startedAt;\r\n const mbps = st.size / (1024 * 1024) / Math.max(0.001, elapsed / 1000);\r\n const noteParts: string[] = [];\r\n if (fileMode !== undefined) noteParts.push('mode ignored (R2)');\r\n if (mtimeMs !== undefined) noteParts.push('mtime ignored (R2)');\r\n const note = noteParts.length ? ` [${noteParts.join(', ')}]` : '';\r\n return { content: [{ type: 'text', text: `Uploaded ${formatBytes(st.size)} from ${local} to r2://${bucket}/${key} via multipart in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s)${note}` }] };\r\n }\r\n const stream = createReadStream(local);\r\n await r2PutObject(bucket, key, stream, st.size);\r\n const elapsed = Date.now() - startedAt;\r\n return { content: [{ type: 'text', text: `Uploaded ${st.size} bytes from ${local} to r2://${bucket}/${key} in ${elapsed}ms` }] };\r\n }\r\n const buf = Buffer.from(String(a.content ?? ''), 'utf-8');\r\n await r2PutObject(bucket, key, buf, buf.length);\r\n return { content: [{ type: 'text', text: `Wrote ${buf.length} bytes to r2://${bucket}/${key}` }] };\r\n } catch (e) {\r\n return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };\r\n }\r\n }\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const input: SftpWriteInput =\r\n typeof a.sourcePath === 'string' && a.sourcePath.length > 0\r\n ? { sourcePath: a.sourcePath }\r\n : { content: String(a.content ?? '') };\r\n const result = await sftpWrite(conn, String(a.path), input, proxy, { fileMode, mtimeMs });\r\n return { content: [{ type: 'text', text: result }] };\r\n }\r\n\r\n case 'sftp-delete': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n const recursive = a.recursive === true;\r\n if (bucket) {\r\n const key = r2Key(String(a.path));\r\n if (!key) return { content: [{ type: 'text', text: 'Error: path is required' }] };\r\n try {\r\n if (recursive) {\r\n // Treat the path as a prefix: delete every object whose key\r\n // starts with it. R2 batches up to 1000 keys per call.\r\n const deleted = await r2DeletePrefix(bucket, key);\r\n return { content: [{ type: 'text', text: `Deleted ${deleted} object(s) under r2://${bucket}/${key}` }] };\r\n }\r\n await r2DeleteObject(bucket, key);\r\n return { content: [{ type: 'text', text: `Deleted r2://${bucket}/${key}` }] };\r\n } catch (e) {\r\n return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };\r\n }\r\n }\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sftpDelete(conn, String(a.path), proxy, { recursive });\r\n return { content: [{ type: 'text', text: result }] };\r\n }\r\n\r\n // ----- Docker -----\r\n case 'docker-list': {\r\n const format = a.format === 'json' ? 'json' : 'table';\r\n const composeOnly = a.composeOnly === true;\r\n const groupByProject = a.groupByProject === true;\r\n // nameFilter accepts string OR string[]. Each entry is matched as glob\r\n // (when it contains * or ?) or as a substring; a row passes if it\r\n // matches ANY entry.\r\n const nameFiltersRaw: string[] = Array.isArray(a.nameFilter)\r\n ? (a.nameFilter as unknown[]).map(v => String(v).trim()).filter(Boolean)\r\n : (typeof a.nameFilter === 'string' && a.nameFilter.trim() ? [a.nameFilter.trim()] : []);\r\n\r\n // Always fetch as NDJSON so we can sort/filter/group locally. This is\r\n // far more flexible than tweaking docker's --format on every variation.\r\n const filterArg = composeOnly ? ` --filter \"label=com.docker.compose.project\"` : '';\r\n const cmd = `docker ps -a${filterArg} --format '{{json .}}'`;\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sshExec(conn, cmd, proxy);\r\n if (result.exitCode !== 0) {\r\n return { content: [{ type: 'text', text: `Error: ${result.stderr || result.stdout}` }] };\r\n }\r\n\r\n type DockerPsRow = { Names?: string; Image?: string; Status?: string; Ports?: string; Labels?: string; Project?: string; Health?: string };\r\n const containers: DockerPsRow[] = [];\r\n for (const line of result.stdout.split('\\n')) {\r\n const trimmed = line.trim();\r\n if (!trimmed) continue;\r\n try { containers.push(JSON.parse(trimmed) as DockerPsRow); } catch { /* ignore malformed line */ }\r\n }\r\n\r\n // Enrich each row: compose project label + health status parsed from\r\n // the Status string (Docker reports \"Up 5 minutes (healthy)\" /\r\n // \"(unhealthy)\" / \"(health: starting)\" when a HEALTHCHECK is defined).\r\n for (const c of containers) {\r\n const m = (c.Labels || '').match(/com\\.docker\\.compose\\.project=([^,]+)/);\r\n c.Project = m ? m[1] : '';\r\n const status = c.Status || '';\r\n if (/\\(unhealthy\\)/i.test(status)) c.Health = 'unhealthy';\r\n else if (/\\(health: starting\\)|\\(starting\\)/i.test(status)) c.Health = 'starting';\r\n else if (/\\(healthy\\)/i.test(status)) c.Health = 'healthy';\r\n else if (/^Up\\b/i.test(status)) c.Health = 'no-check';\r\n else c.Health = ''; // exited / created / dead / paused: blank\r\n }\r\n\r\n // Multi-pattern filter: row passes when ANY pattern matches.\r\n let filtered = containers;\r\n if (nameFiltersRaw.length > 0) {\r\n const matchers = nameFiltersRaw.map(raw => {\r\n if (raw.includes('*') || raw.includes('?')) return { kind: 'glob' as const, re: globToRegExp(raw) };\r\n return { kind: 'sub' as const, lower: raw.toLowerCase() };\r\n });\r\n filtered = containers.filter(c => {\r\n const name = c.Names || '';\r\n const lower = name.toLowerCase();\r\n return matchers.some(m => m.kind === 'glob' ? m.re.test(name) : lower.includes(m.lower));\r\n });\r\n }\r\n\r\n // Default sort: project (empty last), then name.\r\n filtered.sort((x, y) => {\r\n const px = x.Project || '~'; // '~' sorts after letters so empty projects go last\r\n const py = y.Project || '~';\r\n const p = px.localeCompare(py);\r\n return p !== 0 ? p : (x.Names || '').localeCompare(y.Names || '');\r\n });\r\n\r\n if (format === 'json') {\r\n const text = filtered.map(c => JSON.stringify(c)).join('\\n') || '(no containers)';\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n // Table output. Health is a small fixed-width column so unhealthy\r\n // containers jump out visually.\r\n const fmtRow = (r: DockerPsRow) =>\r\n `${(r.Names || '').padEnd(36)} ${(r.Image || '').padEnd(40)} ${(r.Status || '').padEnd(24)} ${(r.Health || '').padEnd(10)} ${(r.Ports || '').padEnd(40)}`;\r\n\r\n if (groupByProject) {\r\n const groups = new Map<string, DockerPsRow[]>();\r\n for (const c of filtered) {\r\n const key = c.Project || '(no compose project)';\r\n const list = groups.get(key);\r\n if (list) list.push(c); else groups.set(key, [c]);\r\n }\r\n const out: string[] = [];\r\n for (const [project, rows] of groups) {\r\n out.push(`=== ${project} (${rows.length}) ===`);\r\n for (const r of rows) out.push(' ' + fmtRow(r));\r\n out.push('');\r\n }\r\n return { content: [{ type: 'text', text: out.join('\\n').trimEnd() || '(no containers)' }] };\r\n }\r\n\r\n const header = `${'NAMES'.padEnd(36)} ${'IMAGE'.padEnd(40)} ${'STATUS'.padEnd(24)} ${'HEALTH'.padEnd(10)} ${'PORTS'.padEnd(40)} PROJECT`;\r\n const body = filtered.map(r => `${fmtRow(r)} ${r.Project || ''}`);\r\n const text = filtered.length === 0 ? '(no containers match)' : [header, ...body].join('\\n');\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n case 'docker-logs': {\r\n // Accept containerName as string or string[]. Multi-container mode tails\r\n // each container in parallel and prefixes every line with [name] so it\r\n // reads like a unified, deinterleaved stream.\r\n const rawNames = Array.isArray(a.containerName)\r\n ? (a.containerName as unknown[]).map(String)\r\n : [String(a.containerName)];\r\n const containers = rawNames\r\n .map(n => n.replace(/[^a-zA-Z0-9._-]/g, ''))\r\n .filter(n => n.length > 0);\r\n if (containers.length === 0) {\r\n return { content: [{ type: 'text', text: 'Error: no valid containerName provided' }] };\r\n }\r\n\r\n // `tail` is the canonical name for \"last N lines\"; keep `lines` as alias\r\n // for backwards compatibility with any caller still using it.\r\n const tail = Number(a.tail) > 0 ? Number(a.tail) : (Number(a.lines) > 0 ? Number(a.lines) : 100);\r\n const sinceRaw = typeof a.since === 'string' ? a.since.trim() : '';\r\n const grepRaw = typeof a.grep === 'string' ? a.grep : '';\r\n // Real-time follow mode: stream new lines for N seconds, then exit.\r\n // Implemented via remote `timeout Ns` so the docker-logs process\r\n // self-terminates even if the SSH session goes weird.\r\n const followSeconds = Math.max(0, Math.min(300, Number(a.followSeconds) || 0));\r\n\r\n // Validate `since`: relative (\"10m\"/\"2h\"/\"24h\"/\"30s\"/\"7d\") or ISO-ish absolute.\r\n if (sinceRaw && !/^\\d+[smhd]$/i.test(sinceRaw) && !/^\\d{4}-\\d{2}-\\d{2}/.test(sinceRaw)) {\r\n return { content: [{ type: 'text', text: 'Error: invalid `since` format (expected e.g. \"10m\", \"2h\", or ISO timestamp)' }] };\r\n }\r\n const sinceArg = sinceRaw ? ` --since ${posixQuote(sinceRaw)}` : '';\r\n const grepSuffix = grepRaw ? ` | grep -i -E ${posixQuote(grepRaw)} --line-buffered` : '';\r\n // In follow mode we usually only care about NEW lines, so default\r\n // `--tail` to 0 unless the caller explicitly asked for backlog.\r\n const followTail = a.tail !== undefined || a.lines !== undefined ? tail : 0;\r\n const tailArg = followSeconds > 0 ? followTail : tail;\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n // Slack ssh timeout in follow mode so the remote `timeout` finishes first.\r\n if (followSeconds > 0) conn.timeout = (followSeconds + 10) * 1000;\r\n\r\n const followFlag = followSeconds > 0 ? ' -f' : '';\r\n\r\n // Single-container: keep the original (unprefixed) output for backwards compat.\r\n if (containers.length === 1) {\r\n const c = containers[0];\r\n const inner = `docker logs${followFlag} --tail ${tailArg}${sinceArg} ${c} 2>&1${grepSuffix}`;\r\n // `timeout --signal=INT N CMD` so docker logs gets a clean SIGINT\r\n // and exits 124 on timeout (which we treat as success in follow mode).\r\n const cmd = followSeconds > 0\r\n ? `timeout --signal=INT ${followSeconds} sh -c ${posixQuote(inner)}`\r\n : inner;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const acceptable = followSeconds > 0\r\n ? (result.exitCode === 0 || result.exitCode === 124 || result.exitCode === 130)\r\n : (result.exitCode === 0 || (grepRaw && result.exitCode === 1));\r\n if (!acceptable) {\r\n return { content: [{ type: 'text', text: `Error (exit ${result.exitCode}): ${result.stderr || result.stdout}` }] };\r\n }\r\n return { content: [{ type: 'text', text: result.stdout || '(no log lines matched)' }] };\r\n }\r\n\r\n // Multi-container path. In follow mode we MUST run sub-shells in parallel\r\n // (otherwise only the first container's stream would ever be reached);\r\n // in batch mode we keep sequential ordering for clean per-container blocks.\r\n const subShells = containers.map(c => {\r\n const inner = `docker logs${followFlag} --tail ${tailArg}${sinceArg} ${c} 2>&1${grepSuffix}`;\r\n return `(${inner} | sed -u -e ${posixQuote(`s/^/[${c}] /`)})`;\r\n });\r\n const inner = followSeconds > 0\r\n ? subShells.join(' & ') + ' & wait'\r\n : subShells.join('; ');\r\n const cmd = followSeconds > 0\r\n ? `timeout --signal=INT ${followSeconds} sh -c ${posixQuote(inner)}`\r\n : inner;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const acceptable = followSeconds > 0\r\n ? (result.exitCode === 0 || result.exitCode === 124 || result.exitCode === 130 || result.exitCode === 143)\r\n : (result.exitCode === 0 || (grepRaw && result.exitCode === 1));\r\n if (!acceptable) {\r\n return { content: [{ type: 'text', text: `Error (exit ${result.exitCode}): ${result.stderr || result.stdout}` }] };\r\n }\r\n return { content: [{ type: 'text', text: result.stdout || '(no log lines matched)' }] };\r\n }\r\n\r\n case 'docker-exec': {\r\n const container = String(a.container).replace(/[^a-zA-Z0-9._-]/g, '');\r\n if (!container) return { content: [{ type: 'text', text: 'Error: invalid container name' }] };\r\n const command = String(a.command);\r\n const args = Array.isArray(a.args) ? (a.args as unknown[]).map(String) : [];\r\n const stdin = typeof a.stdin === 'string' ? a.stdin : undefined;\r\n const interactive = a.interactive === true;\r\n const workdir = typeof a.workdir === 'string' && a.workdir ? ['-w', a.workdir] : [];\r\n const user = typeof a.user === 'string' && a.user ? ['-u', a.user] : [];\r\n\r\n // Flag matrix:\r\n // - stdin given: -i (attach stdin)\r\n // - interactive: -t (allocate TTY) so commands like psql / mysql / bash\r\n // that probe `isatty(stdout)` produce human-friendly output AND don't\r\n // complain (\"the input device is not a TTY\"). Combine with -i for full\r\n // interactive use; -t alone is allowed for tty-only programs.\r\n const flags: string[] = [];\r\n if (stdin !== undefined || interactive) flags.push('-i');\r\n if (interactive) flags.push('-t');\r\n\r\n // docker exec [-it] [-w DIR] [-u USER] CONTAINER CMD [ARG ...]\r\n const dockerArgs = [...flags, ...workdir, ...user, container, command, ...args];\r\n const fullCmd = buildPosixCommand('docker', ['exec', ...dockerArgs]);\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n if (a.timeout) conn.timeout = Number(a.timeout);\r\n // sshExec needs to allocate a PTY when -t is used; the existing ssh2\r\n // exec call requests a pseudo-terminal when we ask for one explicitly.\r\n const result = await sshExec(conn, fullCmd, proxy, {\r\n stdin,\r\n pty: interactive,\r\n });\r\n const output = [`Exit code: ${result.exitCode}`];\r\n if (result.stdout) output.push(`--- stdout ---\\n${result.stdout}`);\r\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\r\n return { content: [{ type: 'text', text: output.join('\\n') }] };\r\n }\r\n\r\n case 'docker-compose': {\r\n const projectPath = String(a.projectPath);\r\n if (!projectPath || !projectPath.startsWith('/')) {\r\n return { content: [{ type: 'text', text: 'Error: projectPath must be an absolute path' }] };\r\n }\r\n const action = String(a.action);\r\n const allowedActions = ['up', 'down', 'restart', 'logs', 'ps', 'pull', 'build'] as const;\r\n if (!allowedActions.includes(action as typeof allowedActions[number])) {\r\n return { content: [{ type: 'text', text: `Error: invalid action (allowed: ${allowedActions.join(', ')})` }] };\r\n }\r\n const service = typeof a.service === 'string' && a.service ? a.service : '';\r\n const tail = Number(a.tail) > 0 ? Number(a.tail) : 200;\r\n\r\n let composeArgs: string[];\r\n switch (action) {\r\n case 'up': composeArgs = service ? ['up', '-d', service] : ['up', '-d']; break;\r\n case 'down': composeArgs = service ? ['down', service] : ['down']; break;\r\n case 'restart': composeArgs = service ? ['restart', service] : ['restart']; break;\r\n case 'logs': composeArgs = service ? ['logs', '--no-color', `--tail=${tail}`, service] : ['logs', '--no-color', `--tail=${tail}`]; break;\r\n case 'ps': composeArgs = service ? ['ps', service] : ['ps']; break;\r\n case 'pull': composeArgs = service ? ['pull', service] : ['pull']; break;\r\n case 'build': composeArgs = service ? ['build', service] : ['build']; break;\r\n default: composeArgs = []; // unreachable\r\n }\r\n\r\n const composeCmd = buildPosixCommand('docker', ['compose', ...composeArgs]);\r\n const fullCmd = `cd ${posixQuote(projectPath)} && ${composeCmd} 2>&1`;\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n conn.timeout = Number(a.timeout) > 0 ? Number(a.timeout) : 120_000;\r\n const result = await sshExec(conn, fullCmd, proxy);\r\n const output = [`Exit code: ${result.exitCode} (compose ${action}${service ? ` ${service}` : ''} @ ${projectPath})`];\r\n if (result.stdout) output.push(result.stdout);\r\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\r\n return { content: [{ type: 'text', text: output.join('\\n') }] };\r\n }\r\n\r\n // ----- Database -----\r\n case 'db-discover': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const sites = await discoverSiteDatabases(conn, proxy);\r\n if (!sites.length) {\r\n return { content: [{ type: 'text', text: 'No web applications with database configs found in /var/www/' }] };\r\n }\r\n const lines = sites.map(s =>\r\n `${s.sitePath} [${s.appType}] db=${s.database} user=${s.user} host=${s.host}:${s.port}`\r\n );\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n case 'db-tables': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const sql = \"SELECT TABLE_NAME, ENGINE, TABLE_ROWS, ROUND(DATA_LENGTH/1024/1024, 2) AS `Size (MB)`, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME\";\r\n const output = await execSiteMysql(conn, String(a.sitePath), sql, proxy);\r\n return { content: [{ type: 'text', text: output || 'No tables found' }] };\r\n }\r\n\r\n case 'db-describe': {\r\n const table = String(a.table).replace(/[^a-zA-Z0-9_]/g, '');\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const output = await execSiteMysql(conn, String(a.sitePath),\r\n `DESCRIBE \\`${table}\\`; SHOW INDEX FROM \\`${table}\\``, proxy);\r\n return { content: [{ type: 'text', text: output }] };\r\n }\r\n\r\n case 'db-query': {\r\n const query = String(a.query).trim();\r\n assertSafeSql(query);\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const output = await execSiteMysql(conn, String(a.sitePath), query, proxy);\r\n return { content: [{ type: 'text', text: output || 'Query executed successfully (no output)' }] };\r\n }\r\n\r\n // ----- Env Config -----\r\n case 'env-list': {\r\n let query = supabase\r\n .from('env_config')\r\n .select('id, app_name, environment, description, updated_at, release_profile_stage_id')\r\n .order('app_name')\r\n .order('environment');\r\n\r\n if (a.releaseProfile) {\r\n const { stageIds } = await resolveReleaseProfileStageIds(String(a.releaseProfile));\r\n query = query.in('release_profile_stage_id', stageIds);\r\n }\r\n\r\n const { data, error } = await query;\r\n if (error) throw new Error(error.message);\r\n\r\n const stageIds = (data || [])\r\n .map((e) => e.release_profile_stage_id)\r\n .filter(Boolean) as string[];\r\n const profileNames = await getProfileNamesForStageIds(stageIds);\r\n\r\n const lines = (data || []).map((e) => {\r\n const profile = e.release_profile_stage_id\r\n ? profileNames[e.release_profile_stage_id] || 'unknown'\r\n : 'unlinked';\r\n return `${e.app_name}/${e.environment} [${profile}] (updated: ${e.updated_at})`;\r\n });\r\n return { content: [{ type: 'text', text: lines.length ? lines.join('\\n') : 'No environment configs stored' }] };\r\n }\r\n\r\n case 'env-get': {\r\n let query = supabase\r\n .from('env_config')\r\n .select('env_data_encrypted, release_profile_stage_id')\r\n .eq('app_name', String(a.appName))\r\n .eq('environment', String(a.environment));\r\n\r\n if (a.releaseProfile) {\r\n const { stageIds } = await resolveReleaseProfileStageIds(String(a.releaseProfile));\r\n query = query.in('release_profile_stage_id', stageIds);\r\n }\r\n\r\n const { data, error } = await query;\r\n\r\n if (error) throw new Error(`Env config query failed: ${error.message}`);\r\n if (!data || data.length === 0) {\r\n throw new Error(`Env config not found: ${a.appName}/${a.environment}${a.releaseProfile ? ` (profile: ${a.releaseProfile})` : ''}`);\r\n }\r\n if (data.length > 1) {\r\n const stageIds = data\r\n .map((r) => r.release_profile_stage_id)\r\n .filter(Boolean) as string[];\r\n const profileNames = await getProfileNamesForStageIds(stageIds);\r\n const names = [...new Set(Object.values(profileNames))].join(', ');\r\n throw new Error(\r\n `Multiple env configs found for ${a.appName}/${a.environment} across profiles: ${names}. ` +\r\n `Pass releaseProfile parameter to select one (e.g. releaseProfile: \"${Object.values(profileNames)[0] || '...'}\")`,\r\n );\r\n }\r\n\r\n const decrypted = decrypt(data[0]!.env_data_encrypted);\r\n return { content: [{ type: 'text', text: decrypted }] };\r\n }\r\n\r\n case 'env-store': {\r\n const appName = String(a.appName);\r\n const environment = String(a.environment);\r\n const encrypted = encrypt(String(a.content));\r\n\r\n let resolvedStageIds: string[] | null = null;\r\n if (a.releaseProfile) {\r\n const { stageIds } = await resolveReleaseProfileStageIds(String(a.releaseProfile));\r\n resolvedStageIds = stageIds;\r\n }\r\n\r\n let existQuery = supabase\r\n .from('env_config')\r\n .select('id, release_profile_stage_id')\r\n .eq('app_name', appName)\r\n .eq('environment', environment);\r\n\r\n if (resolvedStageIds) {\r\n existQuery = existQuery.in('release_profile_stage_id', resolvedStageIds);\r\n }\r\n\r\n const { data: existingRows, error: existErr } = await existQuery;\r\n if (existErr) throw new Error(`Lookup failed: ${existErr.message}`);\r\n\r\n if (existingRows && existingRows.length > 1 && !resolvedStageIds) {\r\n const stageIds = existingRows\r\n .map((r) => r.release_profile_stage_id)\r\n .filter(Boolean) as string[];\r\n const profileNames = await getProfileNamesForStageIds(stageIds);\r\n const names = [...new Set(Object.values(profileNames))].join(', ');\r\n throw new Error(\r\n `Multiple env configs found for ${appName}/${environment} across profiles: ${names}. ` +\r\n `Pass releaseProfile parameter to select one.`,\r\n );\r\n }\r\n\r\n const existing = existingRows?.[0] ?? null;\r\n let saveMsg: string;\r\n if (existing) {\r\n const { error } = await supabase\r\n .from('env_config')\r\n .update({\r\n env_data_encrypted: encrypted,\r\n description: a.description ? String(a.description) : undefined,\r\n updated_by: authContext!.userId,\r\n updated_at: new Date().toISOString(),\r\n })\r\n .eq('id', existing.id);\r\n if (error) throw new Error(error.message);\r\n saveMsg = `Updated env config: ${appName}/${environment}`;\r\n } else {\r\n const insertData: Record<string, unknown> = {\r\n app_name: appName,\r\n environment,\r\n env_data_encrypted: encrypted,\r\n description: a.description ? String(a.description) : null,\r\n created_by: authContext!.userId,\r\n updated_by: authContext!.userId,\r\n };\r\n if (resolvedStageIds?.[0]) {\r\n insertData.release_profile_stage_id = resolvedStageIds[0];\r\n }\r\n const { error } = await supabase.from('env_config').insert(insertData);\r\n if (error) throw new Error(error.message);\r\n saveMsg = `Stored env config: ${appName}/${environment}`;\r\n }\r\n\r\n const syncStageId = existing?.release_profile_stage_id ?? resolvedStageIds?.[0];\r\n const vercelStatus = await attemptVercelSync(appName, environment, syncStageId);\r\n return { content: [{ type: 'text', text: `${saveMsg}. ${vercelStatus}` }] };\r\n }\r\n\r\n // ----- Cache Purge -----\r\n case 'cache-purge': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n conn.timeout = 120_000;\r\n const script = `\r\nR=\"\"\r\n# 1. OPcache – kill lsphp so it respawns with a fresh OPcache\r\nif pgrep -x lsphp >/dev/null 2>&1; then\r\n sudo killall lsphp 2>/dev/null && R=\"\\${R}[OK] OPcache: killed lsphp processes\\\\n\" || R=\"\\${R}[FAIL] OPcache: could not kill lsphp\\\\n\"\r\nelse\r\n R=\"\\${R}[SKIP] OPcache: no lsphp processes running\\\\n\"\r\nfi\r\n# 2. LiteSpeed cache directories\r\nLS=0\r\nfor cdir in /tmp/lshttpd/swap /usr/local/lsws/cachedata; do\r\n if [ -d \"\\$cdir\" ] && [ \"\\$(ls -A \"\\$cdir\" 2>/dev/null)\" ]; then\r\n sudo rm -rf \"\\$cdir\"/* 2>/dev/null && R=\"\\${R}[OK] LS cache: cleared \\$cdir\\\\n\" && LS=1 || R=\"\\${R}[FAIL] LS cache: \\$cdir\\\\n\"\r\n fi\r\ndone\r\n[ \"\\$LS\" -eq 0 ] && R=\"\\${R}[SKIP] LS cache: no cache dirs with content\\\\n\"\r\n# 3. LiteSpeed graceful restart\r\nif [ -x /usr/local/lsws/bin/lswsctrl ]; then\r\n sudo /usr/local/lsws/bin/lswsctrl restart 2>/dev/null && R=\"\\${R}[OK] LiteSpeed: graceful restart\\\\n\" || R=\"\\${R}[FAIL] LiteSpeed: restart failed\\\\n\"\r\nelif systemctl is-active lsws >/dev/null 2>&1 || systemctl is-active lshttpd >/dev/null 2>&1; then\r\n sudo systemctl restart lsws 2>/dev/null || sudo systemctl restart lshttpd 2>/dev/null\r\n R=\"\\${R}[OK] LiteSpeed: restarted via systemctl\\\\n\"\r\nelse\r\n R=\"\\${R}[SKIP] LiteSpeed: not detected\\\\n\"\r\nfi\r\n# 4. WordPress caches\r\nWP=0\r\nfor dir in /var/www/*/; do\r\n [ -d \"\\$dir\" ] || continue\r\n for root in \"\\$dir\" \"\\${dir}html\" \"\\${dir}public_html\" \"\\${dir}public\" \"\\${dir}httpdocs\"; do\r\n [ -f \"\\$root/wp-config.php\" ] || continue\r\n WP=1; SITE=\\$(basename \"\\$dir\")\r\n if command -v wp >/dev/null 2>&1; then\r\n wp cache flush --allow-root --path=\"\\$root\" 2>/dev/null && R=\"\\${R}[OK] WP (\\$SITE): wp cache flush\\\\n\" || R=\"\\${R}[FAIL] WP (\\$SITE): wp cache flush\\\\n\"\r\n elif [ -d \"\\$root/wp-content/cache\" ]; then\r\n rm -rf \"\\$root/wp-content/cache\"/* 2>/dev/null && R=\"\\${R}[OK] WP (\\$SITE): cleared wp-content/cache\\\\n\"\r\n else\r\n R=\"\\${R}[SKIP] WP (\\$SITE): no cache dir, no wp-cli\\\\n\"\r\n fi\r\n break\r\n done\r\ndone\r\n[ \"\\$WP\" -eq 0 ] && R=\"\\${R}[SKIP] WordPress: no sites found\\\\n\"\r\n# 5. PrestaShop caches\r\nPS=0\r\nfor dir in /var/www/*/; do\r\n [ -d \"\\$dir\" ] || continue\r\n for root in \"\\$dir\" \"\\${dir}html\" \"\\${dir}public_html\" \"\\${dir}public\" \"\\${dir}httpdocs\"; do\r\n IS=0\r\n [ -f \"\\$root/app/config/parameters.php\" ] && IS=1\r\n [ -f \"\\$root/config/settings.inc.php\" ] && IS=1\r\n [ \"\\$IS\" -eq 0 ] && continue\r\n PS=1; SITE=\\$(basename \"\\$dir\"); C=\"\"\r\n [ -d \"\\$root/var/cache\" ] && rm -rf \"\\$root/var/cache\"/* 2>/dev/null && C=\"\\${C}var/cache \"\r\n [ -d \"\\$root/cache/smarty/compile\" ] && rm -rf \"\\$root/cache/smarty/compile\"/* 2>/dev/null && C=\"\\${C}smarty/compile \"\r\n [ -d \"\\$root/cache/smarty/cache\" ] && rm -rf \"\\$root/cache/smarty/cache\"/* 2>/dev/null && C=\"\\${C}smarty/cache \"\r\n [ -n \"\\$C\" ] && R=\"\\${R}[OK] PS (\\$SITE): cleared \\${C}\\\\n\" || R=\"\\${R}[SKIP] PS (\\$SITE): no cache dirs\\\\n\"\r\n break\r\n done\r\ndone\r\n[ \"\\$PS\" -eq 0 ] && R=\"\\${R}[SKIP] PrestaShop: no sites found\\\\n\"\r\n# 6. Redis\r\nif command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then\r\n redis-cli FLUSHALL 2>/dev/null && R=\"\\${R}[OK] Redis: FLUSHALL\\\\n\" || R=\"\\${R}[FAIL] Redis: FLUSHALL failed\\\\n\"\r\nelse\r\n R=\"\\${R}[SKIP] Redis: not available\\\\n\"\r\nfi\r\n# 7. Memcached\r\nif systemctl is-active memcached >/dev/null 2>&1; then\r\n if command -v memcflush >/dev/null 2>&1; then\r\n memcflush --servers=localhost 2>/dev/null && R=\"\\${R}[OK] Memcached: flushed\\\\n\" || R=\"\\${R}[FAIL] Memcached: flush failed\\\\n\"\r\n else\r\n echo \"flush_all\" | nc -q1 localhost 11211 2>/dev/null && R=\"\\${R}[OK] Memcached: flushed via nc\\\\n\" || R=\"\\${R}[FAIL] Memcached: flush failed\\\\n\"\r\n fi\r\nelse\r\n R=\"\\${R}[SKIP] Memcached: not active\\\\n\"\r\nfi\r\necho -e \"\\$R\"\r\n`.trim();\r\n const result = await sshExec(conn, script, proxy);\r\n const output = (result.stdout || '').trim();\r\n return { content: [{ type: 'text', text: output || 'Cache purge completed (no output)' }] };\r\n }\r\n\r\n // ----- Domains (mijn.host) -----\r\n case 'domain-list': {\r\n interface DomainListItem {\r\n id: number;\r\n domain: string;\r\n renewal_date: string;\r\n status: string;\r\n status_id: number;\r\n tags: string[];\r\n }\r\n\r\n const res = await mijnhostFetch<{ domains: DomainListItem[] }>('/domains');\r\n const domains = res.data.domains;\r\n\r\n if (!domains.length) {\r\n return { content: [{ type: 'text', text: 'No domains found' }] };\r\n }\r\n\r\n const lines = domains.map(d => {\r\n const tags = d.tags?.length ? ` [${d.tags.join(', ')}]` : '';\r\n return `${d.domain} status=${d.status} renewal=${d.renewal_date}${tags}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: `${domains.length} domain(s):\\n\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n case 'dns-list': {\r\n const domain = String(a.domain);\r\n if (!domain) throw new Error('domain is required');\r\n\r\n interface DnsRecord { type: string; name: string; value: string; ttl: number; }\r\n\r\n const res = await mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n const records = res.data.records;\r\n\r\n if (!records.length) {\r\n return { content: [{ type: 'text', text: `No DNS records found for ${domain}` }] };\r\n }\r\n\r\n const header = 'TYPE NAME VALUE TTL';\r\n const sep = '-'.repeat(90);\r\n const lines = records.map(r =>\r\n `${r.type.padEnd(10)}${r.name.padEnd(31)}${r.value.substring(0, 40).padEnd(41)}${r.ttl}`\r\n );\r\n\r\n return { content: [{ type: 'text', text: `DNS records for ${domain} (${records.length}):\\n\\n${header}\\n${sep}\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n case 'dns-create': {\r\n const domain = String(a.domain);\r\n const type = String(a.type).toUpperCase();\r\n const dnsName = String(a.name);\r\n const value = String(a.value);\r\n const ttl = Number(a.ttl) || 3600;\r\n\r\n if (!domain || !type || !dnsName || !value) {\r\n throw new Error('domain, type, name, and value are required');\r\n }\r\n\r\n interface DnsRecordCreate { type: string; name: string; value: string; ttl: number; }\r\n\r\n const current = await mijnhostFetch<{ domain: string; records: DnsRecordCreate[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n\r\n const records = [...current.data.records, { type, name: dnsName, value, ttl }];\r\n\r\n await mijnhostFetch<void>(`/domains/${encodeURIComponent(domain)}/dns`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ records }),\r\n });\r\n\r\n return { content: [{ type: 'text', text: `DNS record created: ${type} ${dnsName} → ${value} (TTL: ${ttl})` }] };\r\n }\r\n\r\n case 'dns-update': {\r\n const domain = String(a.domain);\r\n const type = String(a.type).toUpperCase();\r\n const dnsName = String(a.name);\r\n const oldValue = String(a.oldValue);\r\n const newValue = String(a.newValue);\r\n const ttl = Number(a.ttl) || undefined;\r\n\r\n if (!domain || !type || !dnsName || !oldValue || !newValue) {\r\n throw new Error('domain, type, name, oldValue, and newValue are required');\r\n }\r\n\r\n interface DnsRecord { type: string; name: string; value: string; ttl: number; }\r\n\r\n const current = await mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n\r\n const idx = current.data.records.findIndex(\r\n r => r.type === type && r.name === dnsName && r.value === oldValue\r\n );\r\n\r\n if (idx === -1) {\r\n throw new Error(`No matching DNS record found: ${type} ${dnsName} = ${oldValue}`);\r\n }\r\n\r\n const updated = [...current.data.records];\r\n const existingTtl = updated[idx]!.ttl;\r\n updated[idx] = {\r\n type,\r\n name: dnsName,\r\n value: newValue,\r\n ttl: ttl ?? existingTtl,\r\n };\r\n\r\n await mijnhostFetch<void>(`/domains/${encodeURIComponent(domain)}/dns`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ records: updated }),\r\n });\r\n\r\n return { content: [{ type: 'text', text: `DNS record updated: ${type} ${dnsName} → ${newValue}${ttl ? ` (TTL: ${ttl})` : ''}` }] };\r\n }\r\n\r\n case 'dns-delete': {\r\n const domain = String(a.domain);\r\n const type = String(a.type).toUpperCase();\r\n const dnsName = String(a.name);\r\n const value = String(a.value);\r\n\r\n if (!domain || !type || !dnsName || !value) {\r\n throw new Error('domain, type, name, and value are required');\r\n }\r\n\r\n interface DnsRecord { type: string; name: string; value: string; ttl: number; }\r\n\r\n const current = await mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n\r\n const before = current.data.records.length;\r\n const remaining = current.data.records.filter(\r\n r => !(r.type === type && r.name === dnsName && r.value === value)\r\n );\r\n\r\n if (remaining.length === before) {\r\n throw new Error(`No matching DNS record found: ${type} ${dnsName} = ${value}`);\r\n }\r\n\r\n await mijnhostFetch<void>(`/domains/${encodeURIComponent(domain)}/dns`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ records: remaining }),\r\n });\r\n\r\n return { content: [{ type: 'text', text: `DNS record deleted: ${type} ${dnsName} = ${value} (${remaining.length} records remaining)` }] };\r\n }\r\n\r\n default:\r\n if (TRIGGER_TOOL_NAMES.has(name)) {\r\n return handleTriggerTool(name, a, { sshExec, getServerConnection });\r\n }\r\n if (AGENT_TOOL_NAMES.has(name)) {\r\n return handleAgentTool(name, a);\r\n }\r\n return { content: [{ type: 'text', text: `Unknown tool: ${name}` }] };\r\n }\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : String(err);\r\n return { content: [{ type: 'text', text: `Error: ${message}` }] };\r\n }\r\n}\r\n\r\n/** Create a configured MCP Server instance with handlers attached. */\r\nfunction createMcpServer(): Server {\r\n const s = new Server(\r\n { name: 'mg-dashboard-mcp', version: MCP_VERSION },\r\n { capabilities: { tools: {} } },\r\n );\r\n s.setRequestHandler(ListToolsRequestSchema, handleListTools);\r\n s.setRequestHandler(CallToolRequestSchema, handleCallTool as Parameters<typeof s.setRequestHandler>[1]);\r\n return s;\r\n}\r\n\r\nconst server = createMcpServer();\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main\r\n// ---------------------------------------------------------------------------\r\n\r\nasync function main() {\r\n console.error('Starting MG Dashboard MCP Server...');\r\n\r\n const apiAuthContext = await validateApiKey(apiKey!);\r\n if (!apiAuthContext) {\r\n console.error('API key validation failed');\r\n process.exit(1);\r\n }\r\n\r\n authContext = await validateSshKey(sshKeyPath!, apiAuthContext.apiKeyId);\r\n if (!authContext) {\r\n console.error('SSH-key authentication failed');\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Security] MCP v${MCP_VERSION} | Key: ${authContext.apiKeyName}`);\r\n\r\n const toolNames = TOOLS.map(t => t.name).join(', ');\r\n\r\n if (httpMode) {\r\n console.error(`API key validated. Starting Streamable HTTP transport on port ${httpPort}...`);\r\n\r\n const transports = new Map<string, StreamableHTTPServerTransport>();\r\n\r\n const REST_TOOL_MAP: Record<string, string> = {\r\n '/api/web-search': 'web-search',\r\n '/api/web-fetch': 'web-fetch',\r\n };\r\n\r\n const httpServer = createHttpServer(async (req, res) => {\r\n const url = new URL(req.url ?? '/', `http://localhost:${httpPort}`);\r\n\r\n // ── Simple REST endpoints for agents that can't use MCP protocol ──\r\n const restToolName = REST_TOOL_MAP[url.pathname];\r\n if (restToolName && req.method === 'POST') {\r\n if (!authContext) {\r\n res.writeHead(401, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: 'Not authenticated' }));\r\n return;\r\n }\r\n const requiredModule = TOOL_MODULE_MAP[restToolName];\r\n if (requiredModule && authContext.permissions.modules[requiredModule] !== true) {\r\n res.writeHead(403, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: `Access denied: no permission for \"${requiredModule}\" module` }));\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n let toolArgs: Record<string, unknown>;\r\n try {\r\n toolArgs = JSON.parse(Buffer.concat(chunks).toString());\r\n } catch {\r\n res.writeHead(400, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\r\n return;\r\n }\r\n try {\r\n const result = await handleAgentTool(restToolName, toolArgs);\r\n res.writeHead(200, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ ok: true, result }));\r\n } catch (err) {\r\n res.writeHead(500, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));\r\n }\r\n return;\r\n }\r\n\r\n if (url.pathname === '/api/tools' && req.method === 'GET') {\r\n res.writeHead(200, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ tools: Object.keys(REST_TOOL_MAP) }));\r\n return;\r\n }\r\n\r\n if (url.pathname !== '/mcp') {\r\n res.writeHead(404, { 'Content-Type': 'text/plain' });\r\n res.end('Not found');\r\n return;\r\n }\r\n\r\n if (req.method === 'OPTIONS') {\r\n res.writeHead(204, {\r\n 'Access-Control-Allow-Origin': '*',\r\n 'Access-Control-Allow-Methods': 'GET, POST, DELETE, OPTIONS',\r\n 'Access-Control-Allow-Headers': 'Content-Type, mcp-session-id',\r\n 'Access-Control-Expose-Headers': 'mcp-session-id',\r\n });\r\n res.end();\r\n return;\r\n }\r\n\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Expose-Headers', 'mcp-session-id');\r\n\r\n const sessionId = req.headers['mcp-session-id'] as string | undefined;\r\n\r\n let body: Record<string, unknown> | undefined;\r\n if (req.method === 'POST') {\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n try {\r\n body = JSON.parse(Buffer.concat(chunks).toString());\r\n } catch {\r\n res.writeHead(400, { 'Content-Type': 'text/plain' });\r\n res.end('Invalid JSON');\r\n return;\r\n }\r\n }\r\n\r\n if (sessionId && transports.has(sessionId)) {\r\n await transports.get(sessionId)!.handleRequest(req, res, body);\r\n return;\r\n }\r\n\r\n if (req.method === 'POST' && body && (Array.isArray(body) ? body.some(isInitializeRequest) : isInitializeRequest(body))) {\r\n const transport = new StreamableHTTPServerTransport({\r\n sessionIdGenerator: () => randomUUID(),\r\n });\r\n transport.onclose = () => {\r\n if (transport.sessionId) transports.delete(transport.sessionId);\r\n };\r\n const sessionServer = createMcpServer();\r\n await sessionServer.connect(transport);\r\n if (transport.sessionId) transports.set(transport.sessionId, transport);\r\n await transport.handleRequest(req, res, body);\r\n return;\r\n }\r\n\r\n res.writeHead(400, { 'Content-Type': 'text/plain' });\r\n res.end('Bad request — missing or invalid session');\r\n });\r\n\r\n httpServer.listen(httpPort, () => {\r\n console.error(`MCP HTTP server ready on port ${httpPort}. Tools: ${toolNames}`);\r\n });\r\n } else {\r\n console.error('API key validated. Starting stdio transport...');\r\n const transport = new StdioServerTransport();\r\n await server.connect(transport);\r\n console.error(`MCP Server ready. Tools: ${toolNames}`);\r\n }\r\n}\r\n\r\nmain().catch((err) => {\r\n console.error('Fatal error:', err);\r\n process.exit(1);\r\n});\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/proxy-mode.ts","../src/trigger-tools.ts","../src/agent-tools.ts","../src/index.ts"],"names":["args","proxyUrl","apiKey","Client","sshExec","getServerConnection","name","text","getArg","runProxyMode","runProcess","spawn","join","existsSync","SshClient","lines","content","elapsed","cmd","result","acceptable","note","stageIds","Server","ListToolsRequestSchema","CallToolRequestSchema","createHttpServer","StdioServerTransport"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Proxy-mode entry point for the MG dashboard MCP package.\r\n *\r\n * Usage:\r\n * npx @mgsoftwarebv/mg-dashboard-mcp \\\r\n * --proxy-url=https://mg-mcp.mgsoftware.nl/v1/{INSTANCE_ID}/mcp \\\r\n * --api-key=pk_xxx \\\r\n * --ssh-key=$HOME/.ssh/id_ed25519\r\n *\r\n * What it does:\r\n * 1. At startup it does an SSH-key challenge handshake against the proxy\r\n * (POST /v1/auth/ssh/challenge → ssh-keygen -Y sign → POST\r\n * /v1/auth/ssh/verify) and obtains a short-lived `pks_xxx` bearer.\r\n * 2. It then runs as a stdio MCP server, transparently forwarding every\r\n * JSON-RPC message to/from the upstream proxy URL using\r\n * `StreamableHTTPClientTransport` with the bearer attached.\r\n * 3. Before the token expires it re-runs the handshake and swaps in the\r\n * fresh bearer without dropping the connection.\r\n *\r\n * This lets a user point Cursor's mcp.json at the local stdio command with\r\n * both factors: a static `pk_` proxy key plus a linked SSH key proof. The\r\n * static key is only sent during the SSH verify step; normal MCP traffic uses\r\n * the short-lived `pks_` session token.\r\n */\r\n\r\nimport { spawn } from \"node:child_process\";\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\r\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\r\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\r\nimport {\r\n CallToolRequestSchema,\r\n CallToolResultSchema,\r\n EmptyResultSchema,\r\n GetPromptRequestSchema,\r\n GetPromptResultSchema,\r\n ListPromptsRequestSchema,\r\n ListPromptsResultSchema,\r\n ListResourcesRequestSchema,\r\n ListResourcesResultSchema,\r\n ListResourceTemplatesRequestSchema,\r\n ListResourceTemplatesResultSchema,\r\n ListToolsRequestSchema,\r\n ListToolsResultSchema,\r\n ReadResourceRequestSchema,\r\n ReadResourceResultSchema,\r\n SubscribeRequestSchema,\r\n UnsubscribeRequestSchema,\r\n} from \"@modelcontextprotocol/sdk/types.js\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// CLI helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction getArg(args: string[], name: string): string | undefined {\r\n return args.find((a) => a.startsWith(`--${name}=`))?.split(\"=\").slice(1).join(\"=\");\r\n}\r\n\r\nfunction expandHome(path: string): string {\r\n if (!path.startsWith(\"~\")) return path;\r\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\r\n return join(home, path.slice(1));\r\n}\r\n\r\nfunction resolvePubkeyPath(input: string): { pubPath: string; pubText: string } {\r\n const candidate = expandHome(input);\r\n let pubPath: string;\r\n if (candidate.endsWith(\".pub\")) {\r\n pubPath = candidate;\r\n } else if (existsSync(`${candidate}.pub`)) {\r\n pubPath = `${candidate}.pub`;\r\n } else if (existsSync(candidate)) {\r\n pubPath = candidate;\r\n } else {\r\n throw new Error(`SSH key file not found: ${candidate} (also tried ${candidate}.pub)`);\r\n }\r\n const pubText = readFileSync(pubPath, \"utf8\").trim();\r\n if (!pubText) throw new Error(`SSH public-key file is empty: ${pubPath}`);\r\n return { pubPath, pubText };\r\n}\r\n\r\nfunction runProcess(\r\n command: string,\r\n argv: string[],\r\n options: { stdin?: string } = {},\r\n): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve) => {\r\n const child = spawn(command, argv, { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n child.stdout.on(\"data\", (d) => {\r\n stdout += d.toString();\r\n });\r\n child.stderr.on(\"data\", (d) => {\r\n stderr += d.toString();\r\n });\r\n child.on(\"error\", (err) => {\r\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\r\n });\r\n child.on(\"close\", (code) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n if (options.stdin !== undefined) {\r\n child.stdin.write(options.stdin);\r\n child.stdin.end();\r\n } else {\r\n child.stdin.end();\r\n }\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH-key handshake against /v1/auth/ssh/challenge + /v1/auth/ssh/verify\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface HandshakeResult {\r\n token: string;\r\n expiresAt: number; // ms epoch\r\n proxyKeyName: string;\r\n}\r\n\r\nfunction deriveAuthBaseUrl(proxyUrl: string): string {\r\n // proxyUrl looks like https://host/v1/{instanceId}/mcp\r\n // We need to call https://host (base) then /v1/auth/ssh/{challenge|verify}.\r\n const u = new URL(proxyUrl);\r\n return `${u.protocol}//${u.host}`;\r\n}\r\n\r\nasync function performHandshake(\r\n proxyUrl: string,\r\n apiKey: string,\r\n pubPath: string,\r\n pubText: string,\r\n): Promise<HandshakeResult> {\r\n const base = deriveAuthBaseUrl(proxyUrl);\r\n\r\n const challengeRes = await fetch(`${base}/v1/auth/ssh/challenge`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: \"{}\",\r\n });\r\n if (!challengeRes.ok) {\r\n const txt = await challengeRes.text().catch(() => \"\");\r\n throw new Error(`Challenge request failed (${challengeRes.status}): ${txt}`);\r\n }\r\n const challenge = (await challengeRes.json()) as {\r\n challenge_id: string;\r\n nonce: string;\r\n namespace: string;\r\n };\r\n\r\n const sign = await runProcess(\r\n \"ssh-keygen\",\r\n [\"-Y\", \"sign\", \"-f\", pubPath, \"-n\", challenge.namespace, \"-q\"],\r\n { stdin: challenge.nonce },\r\n );\r\n if (sign.code !== 0 || !sign.stdout.includes(\"BEGIN SSH SIGNATURE\")) {\r\n throw new Error(\r\n `ssh-keygen sign failed (exit ${sign.code}). Make sure ssh-agent is running ` +\r\n `and has the matching private key loaded. stderr: ${sign.stderr.trim() || \"(empty)\"}`,\r\n );\r\n }\r\n\r\n const verifyRes = await fetch(`${base}/v1/auth/ssh/verify`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n challenge_id: challenge.challenge_id,\r\n api_key: apiKey,\r\n pubkey: pubText,\r\n signature: sign.stdout,\r\n }),\r\n });\r\n if (!verifyRes.ok) {\r\n const txt = await verifyRes.text().catch(() => \"\");\r\n throw new Error(`Verify request failed (${verifyRes.status}): ${txt}`);\r\n }\r\n const verified = (await verifyRes.json()) as {\r\n token: string;\r\n expires_in_seconds: number;\r\n proxy_key_name: string;\r\n };\r\n\r\n return {\r\n token: verified.token,\r\n expiresAt: Date.now() + verified.expires_in_seconds * 1000,\r\n proxyKeyName: verified.proxy_key_name,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Bidirectional message forwarding\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Bridge between a stdio MCP server (talking to e.g. Cursor) and a remote\r\n * Streamable-HTTP MCP server (the proxy). Each incoming JSON-RPC message\r\n * is forwarded verbatim, and responses / notifications stream back.\r\n */\r\nasync function runBridge(handshake: HandshakeResult, proxyUrl: string, refresh: () => Promise<HandshakeResult>) {\r\n let currentToken = handshake.token;\r\n const requestHeaders: Record<string, string> = {\r\n Authorization: `Bearer ${currentToken}`,\r\n };\r\n\r\n const upstreamTransport = new StreamableHTTPClientTransport(new URL(proxyUrl), {\r\n requestInit: { headers: requestHeaders },\r\n });\r\n const upstream = new Client({ name: \"mg-dashboard-mcp-proxy-bridge\", version: \"1.0.0\" });\r\n\r\n // Schedule a refresh 2 minutes before expiry.\r\n const scheduleRefresh = (result: HandshakeResult) => {\r\n const msUntilRefresh = Math.max(30_000, result.expiresAt - Date.now() - 120_000);\r\n setTimeout(async () => {\r\n try {\r\n const fresh = await refresh();\r\n currentToken = fresh.token;\r\n requestHeaders.Authorization = `Bearer ${currentToken}`;\r\n console.error(`[Proxy] Token refreshed (key: ${fresh.proxyKeyName})`);\r\n scheduleRefresh(fresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Token refresh failed: ${err instanceof Error ? err.message : String(err)}`);\r\n // Try again sooner on failure.\r\n setTimeout(() => scheduleRefresh({ ...result, expiresAt: Date.now() + 60_000 }), 30_000);\r\n }\r\n }, msUntilRefresh).unref();\r\n };\r\n scheduleRefresh(handshake);\r\n\r\n // Server-side stdio transport faces Cursor.\r\n const stdioServer = new Server(\r\n { name: \"mg-dashboard-mcp-proxy\", version: \"1.0.0\" },\r\n { capabilities: { tools: {}, prompts: {}, resources: {}, logging: {} } },\r\n );\r\n\r\n const forwardRequest =\r\n (resultSchema: Parameters<typeof upstream.request>[1]) =>\r\n async (request: unknown) =>\r\n upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n resultSchema,\r\n );\r\n\r\n // Explicitly forward first-class MCP methods. The SDK fallback only covers\r\n // truly unknown methods; Cursor's standard discovery calls need registered\r\n // handlers or the client sees an empty server.\r\n stdioServer.setRequestHandler(\r\n ListToolsRequestSchema,\r\n forwardRequest(ListToolsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n CallToolRequestSchema,\r\n forwardRequest(CallToolResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListPromptsRequestSchema,\r\n forwardRequest(ListPromptsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n GetPromptRequestSchema,\r\n forwardRequest(GetPromptResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourcesRequestSchema,\r\n forwardRequest(ListResourcesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ReadResourceRequestSchema,\r\n forwardRequest(ReadResourceResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourceTemplatesRequestSchema,\r\n forwardRequest(ListResourceTemplatesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n SubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n UnsubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n\r\n // Dumb forwarder: any request from Cursor → forward to upstream → return result.\r\n stdioServer.fallbackRequestHandler = async (request: unknown) => {\r\n return await upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n // We don't care about the schema check on the way through — let the\r\n // upstream's actual response flow back unmodified.\r\n undefined as unknown as Parameters<typeof upstream.request>[1],\r\n );\r\n };\r\n // Same for notifications.\r\n stdioServer.fallbackNotificationHandler = async (notification: unknown) => {\r\n await upstream.notification(notification as Parameters<typeof upstream.notification>[0]);\r\n };\r\n\r\n await upstream.connect(upstreamTransport);\r\n\r\n // Forward upstream notifications back to Cursor.\r\n upstream.fallbackNotificationHandler = async (notification: unknown) => {\r\n await stdioServer.notification(notification as Parameters<typeof stdioServer.notification>[0]);\r\n };\r\n\r\n await stdioServer.connect(new StdioServerTransport());\r\n console.error(`[Proxy] Bridge ready. Forwarding stdio → ${proxyUrl}`);\r\n\r\n // In proxy mode this function is the long-lived process. Some SDK transports\r\n // finish their async `connect()` setup without leaving an obvious foreground\r\n // handle behind, which can make Node exit immediately after \"Bridge ready\".\r\n // Keep the process alive until Cursor closes stdin or the process receives a\r\n // termination signal.\r\n await new Promise<void>((resolve) => {\r\n const keepAlive = setInterval(() => undefined, 2_147_483_647);\r\n const done = () => {\r\n clearInterval(keepAlive);\r\n resolve();\r\n };\r\n process.stdin.once(\"close\", done);\r\n process.stdin.once(\"end\", done);\r\n process.once(\"SIGINT\", done);\r\n process.once(\"SIGTERM\", done);\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public entry point\r\n// ---------------------------------------------------------------------------\r\n\r\nexport async function runProxyMode(args: string[]): Promise<void> {\r\n const proxyUrl = getArg(args, \"proxy-url\") || process.env.MG_DASHBOARD_PROXY_URL;\r\n const apiKey = getArg(args, \"api-key\") || process.env.MG_DASHBOARD_API_KEY;\r\n const sshKey = getArg(args, \"ssh-key\") || process.env.MG_DASHBOARD_SSH_KEY;\r\n\r\n if (!proxyUrl) {\r\n console.error(\"--proxy-url is required (or set MG_DASHBOARD_PROXY_URL)\");\r\n process.exit(1);\r\n }\r\n if (!apiKey) {\r\n console.error(\"--api-key is required in proxy mode (or set MG_DASHBOARD_API_KEY)\");\r\n process.exit(1);\r\n }\r\n if (!sshKey) {\r\n console.error(\"--ssh-key is required in proxy mode (or set MG_DASHBOARD_SSH_KEY)\");\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Starting in proxy-bridge mode → ${proxyUrl}`);\r\n\r\n let resolved: { pubPath: string; pubText: string };\r\n try {\r\n resolved = resolvePubkeyPath(sshKey);\r\n } catch (err) {\r\n console.error(`[Proxy] ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n const refresh = () => performHandshake(proxyUrl, apiKey, resolved.pubPath, resolved.pubText);\r\n\r\n let handshake: HandshakeResult;\r\n try {\r\n handshake = await refresh();\r\n } catch (err) {\r\n console.error(`[Proxy] Handshake failed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Authenticated as \"${handshake.proxyKeyName}\"`);\r\n console.error(`[Proxy] Token valid for ${Math.floor((handshake.expiresAt - Date.now()) / 60000)} min`);\r\n\r\n try {\r\n await runBridge(handshake, proxyUrl, refresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Bridge crashed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * Trigger.dev MCP Tools\r\n *\r\n * SSH-based tools for managing Trigger.dev projects. All projects run on a\r\n * single Docker Compose instance. The compose project, server, postgres\r\n * container, and webapp port are auto-discovered — callers only need to\r\n * provide the Trigger.dev project slug (from trigger-list).\r\n *\r\n * @module trigger-tools\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types (mirrored from index.ts to avoid circular imports)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface SshConnectionOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\ninterface SshResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n}\r\n\r\ntype SshExecFn = (\r\n conn: SshConnectionOptions,\r\n command: string,\r\n proxy?: SshConnectionOptions,\r\n) => Promise<SshResult>;\r\n\r\ntype GetServerConnectionFn = (\r\n serverId: string,\r\n) => Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions }>;\r\n\r\ninterface ToolResult {\r\n [key: string]: unknown;\r\n content: { type: string; text: string }[];\r\n}\r\n\r\ninterface TriggerToolDeps {\r\n sshExec: SshExecFn;\r\n getServerConnection: GetServerConnectionFn;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Trigger.dev API response shapes (partial, only fields we display)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerRunItem {\r\n id: string;\r\n status: string;\r\n taskIdentifier: string;\r\n version?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n startedAt?: string;\r\n finishedAt?: string;\r\n durationMs?: number;\r\n isTest?: boolean;\r\n}\r\n\r\ninterface TriggerRunDetail extends TriggerRunItem {\r\n payload?: unknown;\r\n output?: unknown;\r\n attempts?: {\r\n id: string;\r\n status: string;\r\n error?: { message: string; name?: string; stackTrace?: string };\r\n startedAt?: string;\r\n completedAt?: string;\r\n }[];\r\n}\r\n\r\nconst TERMINAL_STATUSES = new Set([\r\n 'COMPLETED', 'FAILED', 'CRASHED', 'CANCELED',\r\n 'SYSTEM_FAILURE', 'INTERRUPTED', 'EXPIRED',\r\n]);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Hardcoded infra constants — single Trigger.dev instance\r\n// ---------------------------------------------------------------------------\r\n\r\n/** SSH server that hosts the Trigger.dev Docker Compose stack. */\r\nconst TRIGGER_SERVER_ID = '03659d55-e194-400d-b82a-bf6457371ded';\r\n\r\n/** Docker Compose project name on the server. */\r\nconst COMPOSE_PROJECT = 'mg-dashboard-supabase-trigger';\r\n\r\nconst PG_CONTAINER = `${COMPOSE_PROJECT}-postgres-1`;\r\nconst WA_CONTAINER = `${COMPOSE_PROJECT}-webapp-1`;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\n/** MCP tool definitions for Trigger.dev (list projects, runs, details, test, replay). */\r\nexport const TRIGGER_TOOLS = [\r\n {\r\n name: 'trigger-list',\r\n description:\r\n 'List all Trigger.dev projects. Returns the project slug and name. ' +\r\n 'Use the slug as the \"project\" parameter in other trigger-* tools.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {},\r\n },\r\n },\r\n {\r\n name: 'trigger-runs',\r\n description:\r\n 'List recent task runs for a Trigger.dev project. ' +\r\n 'Returns run ID, task name, status, duration, and timestamps.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list (e.g. \"mg-dashboard-bHfS\")' },\r\n status: {\r\n type: 'string',\r\n description: 'Comma-separated status filter: QUEUED,EXECUTING,COMPLETED,FAILED,CRASHED,CANCELED,SYSTEM_FAILURE',\r\n },\r\n taskIdentifier: { type: 'string', description: 'Filter by task identifier (e.g. \"hello-world\")' },\r\n limit: { type: 'number', description: 'Max runs to return (default 20, max 100)' },\r\n },\r\n required: ['project'],\r\n },\r\n },\r\n {\r\n name: 'trigger-run-detail',\r\n description:\r\n 'Get full details of a specific run: status, payload, output, and error stack traces. ' +\r\n 'Use after trigger-runs or trigger-test-task to inspect results.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list' },\r\n runId: { type: 'string', description: 'Run ID (e.g. run_xxxxx)' },\r\n },\r\n required: ['project', 'runId'],\r\n },\r\n },\r\n {\r\n name: 'trigger-test-task',\r\n description:\r\n 'Trigger a task run and wait for it to complete. Returns the final status, output, ' +\r\n 'or error with stack trace. The main tool for testing trigger tasks from Cursor.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list' },\r\n taskId: { type: 'string', description: 'Task identifier (e.g. \"hello-world\", \"execute-pipeline\")' },\r\n payload: { type: 'string', description: 'JSON payload string to pass to the task (optional)' },\r\n waitSeconds: { type: 'number', description: 'Max seconds to wait for completion (default 60, max 300)' },\r\n },\r\n required: ['project', 'taskId'],\r\n },\r\n },\r\n {\r\n name: 'trigger-replay-run',\r\n description: 'Replay a previously failed or completed run with the same payload. Returns the new run ID.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list' },\r\n runId: { type: 'string', description: 'Run ID to replay (e.g. run_xxxxx)' },\r\n },\r\n required: ['project', 'runId'],\r\n },\r\n },\r\n];\r\n\r\n/** Set of Trigger.dev MCP tool names for fast membership checks in the main server switch. */\r\nexport const TRIGGER_TOOL_NAMES = new Set(TRIGGER_TOOLS.map((t) => t.name));\r\n\r\n/** Maps each Trigger.dev tool name to the dashboard module key required to use it (`ci_cd`). */\r\nexport const TRIGGER_TOOL_MODULE_MAP: Record<string, string> = {\r\n 'trigger-list': 'ci_cd',\r\n 'trigger-runs': 'ci_cd',\r\n 'trigger-run-detail': 'ci_cd',\r\n 'trigger-test-task': 'ci_cd',\r\n 'trigger-replay-run': 'ci_cd',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerInstance {\r\n port: string;\r\n apiKey: string;\r\n}\r\n\r\n/**\r\n * Discover the webapp port and the production API key for a specific\r\n * Trigger.dev project by querying Docker and the Postgres container.\r\n * The API key is resolved via a JOIN on Project → RuntimeEnvironment.\r\n */\r\nasync function discoverInstance(\r\n projectSlug: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<TriggerInstance> {\r\n const sql = `SELECT re.\\\\\"apiKey\\\\\" FROM \\\\\"RuntimeEnvironment\\\\\" re `\r\n + `JOIN \\\\\"Project\\\\\" p ON re.\\\\\"projectId\\\\\" = p.id `\r\n + `WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;\r\n\r\n const cmd = [\r\n `PORT=$(docker port \"${WA_CONTAINER}\" 3000/tcp 2>/dev/null | head -1 | sed 's/.*://')`,\r\n `KEY=$(docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null | tr -d '[:space:]')`,\r\n 'echo \"$PORT|$KEY\"',\r\n ].join(' && ');\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n const sepIdx = output.indexOf('|');\r\n\r\n const port = sepIdx > 0 ? output.substring(0, sepIdx) : '';\r\n const apiKey = sepIdx > 0 ? output.substring(sepIdx + 1) : '';\r\n\r\n if (!port) {\r\n throw new Error(\r\n `Could not find webapp port for ${WA_CONTAINER}. Is the container running?`,\r\n );\r\n }\r\n if (!apiKey) {\r\n throw new Error(\r\n `Could not get API key for project \"${projectSlug}\". ` +\r\n 'Check if the project slug is correct (use trigger-list).',\r\n );\r\n }\r\n\r\n return { port, apiKey };\r\n}\r\n\r\n/**\r\n * Fetch console/logger output for a run from the TaskEvent table in Postgres.\r\n * Returns formatted log lines sorted by time, filtered to user-relevant levels.\r\n */\r\nasync function fetchRunLogs(\r\n runId: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<string> {\r\n const sql = `SELECT level, message, \\\\\"isError\\\\\", \\\\\"createdAt\\\\\" `\r\n + `FROM \\\\\"TaskEvent\\\\\" `\r\n + `WHERE \\\\\"runId\\\\\" = '${runId}' `\r\n + `AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') `\r\n + `ORDER BY \\\\\"startTime\\\\\" ASC LIMIT 200`;\r\n\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) return '';\r\n\r\n return output.split('\\n').map((line) => {\r\n const parts = line.split('|');\r\n const level = (parts[0] || '').padEnd(5);\r\n const message = parts[1] || '';\r\n const isError = parts[2] === 't';\r\n const ts = parts[3] || '';\r\n const time = ts ? ts.split(' ')[1]?.substring(0, 8) || '' : '';\r\n const prefix = isError ? '!' : ' ';\r\n return `${prefix}${time} [${level}] ${message}`;\r\n }).join('\\n');\r\n}\r\n\r\n/**\r\n * Execute a curl request against the Trigger.dev REST API via SSH.\r\n * Uses -g (globoff) to prevent curl from interpreting brackets in URLs.\r\n */\r\nasync function triggerApi(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n method: string,\r\n path: string,\r\n body?: string,\r\n): Promise<string> {\r\n const parts = ['curl', '-s', '-g', '--max-time', '30'];\r\n if (method !== 'GET') parts.push('-X', method);\r\n parts.push(`\"http://localhost:${instance.port}${path}\"`);\r\n parts.push(`-H \"Authorization: Bearer ${instance.apiKey}\"`);\r\n if (body) {\r\n parts.push('-H \"Content-Type: application/json\"');\r\n parts.push(`-d '${body.replace(/'/g, \"'\\\\''\")}'`);\r\n }\r\n\r\n const result = await sshExec(conn, parts.join(' '), proxy);\r\n if (result.exitCode !== 0 && !result.stdout) {\r\n throw new Error(\r\n `Trigger.dev API call failed (${method} ${path}): ${result.stderr || `exit code ${result.exitCode}`}`,\r\n );\r\n }\r\n return result.stdout;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Output formatters\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction formatRunsTable(runs: TriggerRunItem[]): string {\r\n if (runs.length === 0) return 'No runs found';\r\n\r\n const lines = runs.map((r) => {\r\n const duration = r.durationMs != null ? `${(r.durationMs / 1000).toFixed(1)}s` : '-';\r\n const test = r.isTest ? ' [TEST]' : '';\r\n const created = r.createdAt ? new Date(r.createdAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' }) : '';\r\n return `${r.id} ${r.taskIdentifier.padEnd(35)} ${r.status.padEnd(16)} ${duration.padStart(8)} ${created}${test}`;\r\n });\r\n\r\n return `${'ID'.padEnd(20)} ${'TASK'.padEnd(35)} ${'STATUS'.padEnd(16)} ${'DURATION'.padStart(8)} CREATED\\n` +\r\n '-'.repeat(110) + '\\n' +\r\n lines.join('\\n');\r\n}\r\n\r\nfunction formatRunDetail(run: TriggerRunDetail): string {\r\n const sections: string[] = [];\r\n\r\n sections.push(`=== Run ${run.id} ===`);\r\n sections.push(`Task: ${run.taskIdentifier}`);\r\n sections.push(`Status: ${run.status}`);\r\n sections.push(`Version: ${run.version || '-'}`);\r\n\r\n if (run.startedAt) sections.push(`Started: ${new Date(run.startedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.finishedAt) sections.push(`Finished: ${new Date(run.finishedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.durationMs != null) sections.push(`Duration: ${(run.durationMs / 1000).toFixed(2)}s`);\r\n\r\n if (run.payload !== undefined) {\r\n const payloadStr = typeof run.payload === 'string'\r\n ? run.payload\r\n : JSON.stringify(run.payload, null, 2);\r\n sections.push('', '--- Payload ---', payloadStr);\r\n }\r\n\r\n if (run.output !== undefined) {\r\n const outputStr = typeof run.output === 'string'\r\n ? run.output\r\n : JSON.stringify(run.output, null, 2);\r\n sections.push('', '--- Output ---', outputStr);\r\n }\r\n\r\n if (run.attempts && run.attempts.length > 0) {\r\n for (const attempt of run.attempts) {\r\n if (attempt.error) {\r\n sections.push(\r\n '',\r\n `--- Error (${attempt.id}) ---`,\r\n `${attempt.error.name || 'Error'}: ${attempt.error.message}`,\r\n );\r\n if (attempt.error.stackTrace) {\r\n sections.push('', attempt.error.stackTrace);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main handler\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Executes a Trigger.dev–related MCP tool over SSH against the shared Docker Compose stack.\r\n *\r\n * @param name - Tool name (e.g. `trigger-list`, `trigger-runs`).\r\n * @param args - Arguments from the MCP `callTool` request.\r\n * @param deps - Injected `sshExec` and `getServerConnection` implementations.\r\n * @returns MCP-formatted result with human-readable text content.\r\n * @throws {Error} When a JSON payload for `trigger-test-task` is invalid, or discovery/API calls fail critically.\r\n */\r\nexport async function handleTriggerTool(\r\n name: string,\r\n args: Record<string, unknown>,\r\n deps: TriggerToolDeps,\r\n): Promise<ToolResult> {\r\n const { sshExec, getServerConnection } = deps;\r\n const { conn, proxy } = await getServerConnection(TRIGGER_SERVER_ID);\r\n\r\n switch (name) {\r\n // -----------------------------------------------------------------\r\n case 'trigger-list': {\r\n const sql = 'SELECT slug, name FROM \\\\\"Project\\\\\" ORDER BY name';\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) {\r\n return { content: [{ type: 'text', text: 'No Trigger.dev projects found.' }] };\r\n }\r\n\r\n const header = `${'SLUG'.padEnd(25)} NAME`;\r\n const sep = '-'.repeat(55);\r\n const lines = output.split('\\n').map((line) => {\r\n const [slug, name] = line.split('|');\r\n return `${(slug || '').padEnd(25)} ${name || ''}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: `${header}\\n${sep}\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-runs': {\r\n const project = String(args.project);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 100);\r\n const queryParts = [`page%5Bsize%5D=${limit}`];\r\n if (args.status) queryParts.push(`filter%5Bstatus%5D=${String(args.status)}`);\r\n if (args.taskIdentifier) queryParts.push(`filter%5BtaskIdentifier%5D=${String(args.taskIdentifier)}`);\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v1/runs?${queryParts.join('&')}`,\r\n );\r\n\r\n let parsed: { data?: TriggerRunItem[] };\r\n try {\r\n parsed = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runs = parsed.data || [];\r\n return { content: [{ type: 'text', text: formatRunsTable(runs) }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-run-detail': {\r\n const project = String(args.project);\r\n const runId = String(args.runId);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const [rawJson, logs] = await Promise.all([\r\n triggerApi(conn, proxy, sshExec, instance, 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`),\r\n fetchRunLogs(runId, conn, proxy, sshExec),\r\n ]);\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n let text = formatRunDetail(run);\r\n if (logs) {\r\n text += '\\n\\n--- Logs ---\\n' + logs;\r\n }\r\n\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-test-task': {\r\n const project = String(args.project);\r\n const taskId = String(args.taskId);\r\n const waitSeconds = Math.min(Math.max(Number(args.waitSeconds) || 60, 5), 300);\r\n\r\n conn.timeout = (waitSeconds + 30) * 1000;\r\n\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n let payload = '{}';\r\n if (args.payload) {\r\n try {\r\n JSON.parse(String(args.payload));\r\n payload = String(args.payload);\r\n } catch {\r\n throw new Error(`Invalid JSON payload: ${String(args.payload).substring(0, 200)}`);\r\n }\r\n }\r\n\r\n const triggerBody = JSON.stringify({\r\n payload: JSON.parse(payload),\r\n options: { tags: ['mcp-test'], test: true },\r\n });\r\n\r\n const triggerJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/tasks/${encodeURIComponent(taskId)}/trigger`,\r\n triggerBody,\r\n );\r\n\r\n let triggerResp: { id?: string };\r\n try {\r\n triggerResp = JSON.parse(triggerJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Failed to trigger task. API response:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runId = triggerResp.id;\r\n if (!runId) {\r\n return { content: [{ type: 'text', text: `Trigger API did not return a run ID:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const pollInterval = 3000;\r\n const maxPolls = Math.ceil((waitSeconds * 1000) / pollInterval);\r\n\r\n for (let i = 0; i < maxPolls; i++) {\r\n await new Promise((r) => setTimeout(r, pollInterval));\r\n\r\n const pollJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`,\r\n );\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(pollJson);\r\n } catch {\r\n continue;\r\n }\r\n\r\n if (TERMINAL_STATUSES.has(run.status)) {\r\n let text = formatRunDetail(run);\r\n const logs = await fetchRunLogs(runId, conn, proxy, sshExec);\r\n if (logs) text += '\\n\\n--- Logs ---\\n' + logs;\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n }\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Run ${runId} did not complete within ${waitSeconds}s (still running). Use trigger-run-detail to check later.`,\r\n }],\r\n };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-replay-run': {\r\n const project = String(args.project);\r\n const runId = String(args.runId);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/runs/${encodeURIComponent(runId)}/replay`,\r\n );\r\n\r\n let result: { id?: string };\r\n try {\r\n result = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Replay response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: result.id\r\n ? `Run replayed. New run ID: ${result.id}`\r\n : `Replay response:\\n${rawJson.substring(0, 500)}`,\r\n }],\r\n };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n default:\r\n return { content: [{ type: 'text', text: `Unknown trigger tool: ${name}` }] };\r\n }\r\n}\r\n","/**\r\n * Web Tools for MCP Server\r\n *\r\n * Web search, fetch, and contact extraction tools available to both\r\n * human operators (via Cursor MCP) and automated agent workspaces.\r\n *\r\n * @module agent-tools\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ToolResult {\r\n [key: string]: unknown;\r\n content: { type: string; text: string }[];\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction clamp(val: number, min: number, max: number): number {\r\n return Math.max(min, Math.min(max, val));\r\n}\r\n\r\nfunction sanitizeString(val: unknown, maxLen: number): string {\r\n return String(val ?? '').slice(0, maxLen);\r\n}\r\n\r\nexport const AGENT_TOOLS = [\r\n {\r\n name: 'web-search',\r\n description:\r\n 'Search the web using DuckDuckGo. Returns a list of results with title, URL, and snippet. ' +\r\n 'Use this to find companies, websites, directories, etc.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n query: { type: 'string', description: 'Search query (e.g. \"logistiek bedrijf MKB nederland\")' },\r\n max_results: { type: 'number', description: 'Max results to return (default: 15, max: 30)' },\r\n },\r\n required: ['query'],\r\n },\r\n },\r\n {\r\n name: 'web-fetch',\r\n description:\r\n 'Fetch a web page and return its text content (HTML tags stripped). ' +\r\n 'Automatically extracts emails and phone numbers found on the page. ' +\r\n 'Returns at most 15000 characters of cleaned text.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n url: { type: 'string', description: 'Full URL to fetch (e.g. \"https://example.nl/contact\")' },\r\n extract_links: { type: 'boolean', description: 'Also extract all links from the page (default: false)' },\r\n },\r\n required: ['url'],\r\n },\r\n },\r\n {\r\n name: 'web-find-contacts',\r\n description:\r\n 'POWERFUL contact finder. Crawls a company website (homepage + contact/about/team pages), ' +\r\n 'extracts ALL emails, phone numbers, and LinkedIn URLs via regex + mailto/tel parsing. ' +\r\n 'Also searches Google for the company email as fallback. Returns structured contact data. ' +\r\n 'USE THIS for every lead instead of manually browsing contact pages.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n url: {\r\n type: 'string',\r\n description: 'Company website URL or domain (e.g. \"https://example.nl\" or \"example.nl\")',\r\n },\r\n company_name: {\r\n type: 'string',\r\n description: 'Company name (improves Google search accuracy)',\r\n },\r\n include_search: {\r\n type: 'boolean',\r\n description: 'Also search Google for emails (default: true)',\r\n },\r\n },\r\n required: ['url'],\r\n },\r\n },\r\n];\r\n\r\n/** Set of web tool names for dispatch in the main server. */\r\nexport const AGENT_TOOL_NAMES = new Set(AGENT_TOOLS.map((t) => t.name));\r\n\r\n/** Maps each web tool name to the dashboard permission module. */\r\nexport const AGENT_TOOL_MODULE_MAP: Record<string, string> = {\r\n 'web-search': 'agent_reporting',\r\n 'web-fetch': 'agent_reporting',\r\n 'web-find-contacts': 'agent_reporting',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Web Search & Fetch helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface SearchResult {\r\n title: string;\r\n url: string;\r\n snippet: string;\r\n}\r\n\r\nconst WEB_USER_AGENT =\r\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\r\n\r\nasync function webSearch(query: string, maxResults: number): Promise<SearchResult[]> {\r\n const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;\r\n\r\n const response = await fetch(url, {\r\n headers: {\r\n 'User-Agent': WEB_USER_AGENT,\r\n 'Accept': 'text/html',\r\n 'Accept-Language': 'nl,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n });\r\n\r\n if (!response.ok) throw new Error(`Search failed: HTTP ${response.status}`);\r\n const html = await response.text();\r\n\r\n const results: SearchResult[] = [];\r\n const resultBlocks = html.split(/class=\"result\\s/);\r\n\r\n for (let i = 1; i < resultBlocks.length && results.length < maxResults; i++) {\r\n const block = resultBlocks[i];\r\n\r\n const titleMatch = block.match(/class=\"result__a\"[^>]*>([^<]+)</);\r\n const hrefMatch = block.match(/class=\"result__a\"\\s+href=\"([^\"]+)\"/);\r\n const snippetMatch = block.match(/class=\"result__snippet\"[^>]*>([\\s\\S]*?)<\\/a>/);\r\n\r\n if (!hrefMatch) continue;\r\n\r\n let href = hrefMatch[1];\r\n if (href.includes('uddg=')) {\r\n const uddg = new URL(href, 'https://duckduckgo.com').searchParams.get('uddg');\r\n if (uddg) href = uddg;\r\n }\r\n\r\n if (!href.startsWith('http')) continue;\r\n\r\n const title = titleMatch\r\n ? titleMatch[1].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, \"'\").replace(/"/g, '\"').trim()\r\n : href;\r\n\r\n const snippet = snippetMatch\r\n ? snippetMatch[1].replace(/<[^>]+>/g, '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, \"'\").replace(/"/g, '\"').replace(/\\s+/g, ' ').trim()\r\n : '';\r\n\r\n results.push({ title, url: href, snippet });\r\n }\r\n\r\n return results;\r\n}\r\n\r\ninterface WebFetchResult {\r\n text: string;\r\n rawHtml: string;\r\n links: { href: string; text: string }[];\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Contact extraction constants & helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst EMAIL_REGEX = /[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}/g;\r\nconst PHONE_NL_REGEX = /(?:\\+31|0)[\\s\\-.]?\\(?\\d{1,3}\\)?[\\s\\-.]?\\d{3,4}[\\s\\-.]?\\d{2,4}/g;\r\nconst LINKEDIN_REGEX = /https?:\\/\\/(?:www\\.)?linkedin\\.com\\/(?:in|company)\\/[a-zA-Z0-9\\-_%]+\\/?/gi;\r\n\r\nconst NOISE_EMAIL_PATTERNS = [\r\n /noreply@/i, /no-reply@/i, /mailer-daemon@/i, /postmaster@/i,\r\n /@example\\./i, /test@/i, /@wix\\.com$/i, /@sentry\\.io$/i,\r\n /@wordpress\\./i, /@gravatar\\.com$/i, /@schema\\.org$/i,\r\n /@w3\\.org$/i, /@facebook\\.com$/i, /@google\\.com$/i, /@twitter\\.com$/i,\r\n /@github\\.com$/i, /@cloudflare\\./i, /@vercel\\./i, /@netlify\\./i,\r\n /@cookiebot\\./i, /@hotjar\\./i, /@hubspot\\./i, /@mailchimp\\./i,\r\n /@googleusercontent/i, /@gstatic/i, /@youtube/i, /@recaptcha/i,\r\n /@privacy/i, /@cookie/i, /@gdpr/i, /@dynamicweb\\./i,\r\n /@placeholder\\./i, /@yourcompany\\./i, /@company\\./i,\r\n /smith@/i, /doe@/i, /demo@/i, /sample@/i,\r\n /naam@/i, /voorbeeld/i, /your-?email/i, /email@/i,\r\n /@domein\\./i, /@bedrijf\\./i, /@domain\\./i,\r\n /@sentry/i, /@wixpress/i, /@lieferkassen/i, /john@/i, /jane@/i,\r\n];\r\n\r\nconst CONTACT_PATH_KEYWORDS = [\r\n 'contact', 'about', 'over-ons', 'over', 'team', 'medewerker',\r\n 'impressum', 'imprint', 'wie-zijn', 'ons-team', 'werknemers',\r\n 'organisatie', 'zakelijk', 'bedrijfsinfo', 'neem-contact', 'footer',\r\n];\r\n\r\nconst CONTACT_PATHS_TO_TRY = [\r\n '/contact', '/over-ons', '/about', '/about-us', '/team',\r\n '/contact-us', '/over', '/wie-zijn-wij', '/ons-team',\r\n '/zakelijk/over-ons', '/medewerkers', '/organisatie',\r\n '/bedrijfsinformatie', '/impressum',\r\n];\r\n\r\nfunction decodeUnicodeEscapes(text: string): string {\r\n return text.replace(/\\\\u([0-9a-fA-F]{4})/g, (_, hex) =>\r\n String.fromCharCode(parseInt(hex, 16)),\r\n );\r\n}\r\n\r\nfunction decodeHtmlEntities(text: string): string {\r\n return text\r\n .replace(/&#(\\d+);/g, (_, num) => String.fromCharCode(parseInt(num)))\r\n .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) =>\r\n String.fromCharCode(parseInt(hex, 16)),\r\n );\r\n}\r\n\r\nfunction extractEmailsFromHtml(html: string): string[] {\r\n const emails = new Set<string>();\r\n\r\n const decoded = decodeHtmlEntities(decodeUnicodeEscapes(html));\r\n\r\n const mailtoRegex = /mailto:([a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,})/gi;\r\n let m: RegExpExecArray | null;\r\n for (const src of [html, decoded]) {\r\n while ((m = mailtoRegex.exec(src)) !== null) emails.add(m[1]!.toLowerCase());\r\n }\r\n\r\n const noStyles = decoded.replace(/<style[\\s\\S]*?<\\/style>/gi, '');\r\n const textEmails = noStyles.match(EMAIL_REGEX) || [];\r\n for (const e of textEmails) {\r\n const lower = e.toLowerCase();\r\n if (!/\\.(png|jpg|jpeg|gif|svg|webp|css|js|woff|ttf|eot|ico)$/i.test(lower)) {\r\n emails.add(lower);\r\n }\r\n }\r\n\r\n return [...emails].filter(e => !NOISE_EMAIL_PATTERNS.some(p => p.test(e)));\r\n}\r\n\r\nfunction extractPhonesFromHtml(html: string): string[] {\r\n const phones = new Set<string>();\r\n const decoded = decodeHtmlEntities(decodeUnicodeEscapes(html));\r\n\r\n const telRegex = /href=\"tel:([^\"]+)\"/gi;\r\n let m: RegExpExecArray | null;\r\n for (const src of [html, decoded]) {\r\n while ((m = telRegex.exec(src)) !== null) {\r\n const clean = m[1]!.replace(/[\\s\\-().]/g, '');\r\n if (clean.length >= 10 && clean.length <= 14) phones.add(m[1]!.trim());\r\n }\r\n }\r\n\r\n const stripped = decoded\r\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\r\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\r\n .replace(/<[^>]+>/g, ' ');\r\n const textPhones = stripped.match(PHONE_NL_REGEX) || [];\r\n for (const p of textPhones) {\r\n const clean = p.replace(/[\\s\\-().]/g, '');\r\n if (clean.length >= 10 && clean.length <= 14) phones.add(p.trim());\r\n }\r\n\r\n return [...phones].slice(0, 10);\r\n}\r\n\r\nfunction extractLinkedInFromHtml(html: string): string[] {\r\n const links = new Set<string>();\r\n const matches = html.match(LINKEDIN_REGEX) || [];\r\n for (const l of matches) links.add(l.replace(/\\/$/, ''));\r\n return [...links];\r\n}\r\n\r\nfunction discoverContactPages(html: string, baseUrl: string): string[] {\r\n let base: URL;\r\n try { base = new URL(baseUrl); } catch { return []; }\r\n\r\n const pages = new Set<string>();\r\n\r\n for (const path of CONTACT_PATHS_TO_TRY) {\r\n pages.add(`${base.origin}${path}`);\r\n }\r\n\r\n const linkRegex = /<a\\s[^>]*href=\"([^\"#]*)\"[^>]*>/gi;\r\n let m: RegExpExecArray | null;\r\n while ((m = linkRegex.exec(html)) !== null) {\r\n try {\r\n const url = new URL(m[1], baseUrl);\r\n if (url.hostname !== base.hostname) continue;\r\n const path = url.pathname.toLowerCase();\r\n if (CONTACT_PATH_KEYWORDS.some(kw => path.includes(kw))) {\r\n pages.add(url.origin + url.pathname);\r\n }\r\n } catch { /* invalid url, skip */ }\r\n }\r\n\r\n pages.delete(base.origin + base.pathname);\r\n return [...pages].slice(0, 10);\r\n}\r\n\r\nfunction guessCommonEmails(domain: string): string[] {\r\n const d = domain.replace(/^www\\./, '');\r\n return [`info@${d}`, `contact@${d}`, `hello@${d}`, `administratie@${d}`, `verkoop@${d}`];\r\n}\r\n\r\nconst BOT_CHALLENGE_INDICATORS = [\r\n 'sgcaptcha', 'challenge-platform', 'cf-browser-verification',\r\n 'Just a moment', 'Checking your browser', 'Enable JavaScript and cookies',\r\n 'Attention Required', 'DDoS protection by',\r\n];\r\n\r\nfunction isBotChallengePage(html: string): boolean {\r\n if (html.length > 2000) return false;\r\n const lower = html.toLowerCase();\r\n return BOT_CHALLENGE_INDICATORS.some(ind => lower.includes(ind.toLowerCase()));\r\n}\r\n\r\nasync function fetchRawHtml(url: string, timeoutMs = 10000): Promise<string | null> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), timeoutMs);\r\n try {\r\n const res = await fetch(url, {\r\n headers: {\r\n 'User-Agent': WEB_USER_AGENT,\r\n 'Accept': 'text/html,application/xhtml+xml',\r\n 'Accept-Language': 'nl,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n const ct = res.headers.get('content-type') || '';\r\n if (!ct.includes('text/html') && !ct.includes('text/plain') && !ct.includes('xhtml')) return null;\r\n if (!res.ok && res.status !== 403) return null;\r\n const html = await res.text();\r\n if (isBotChallengePage(html)) return null;\r\n return html;\r\n } catch {\r\n return null;\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n}\r\n\r\nasync function fetchWaybackHtml(url: string, timeoutMs = 15000): Promise<string | null> {\r\n const cleanUrl = url.replace(/^https?:\\/\\//, '');\r\n const wbUrl = `https://web.archive.org/web/2024/${cleanUrl}`;\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), timeoutMs);\r\n try {\r\n const res = await fetch(wbUrl, {\r\n headers: { 'User-Agent': WEB_USER_AGENT },\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n if (!res.ok) return null;\r\n const html = await res.text();\r\n if (html.length < 500) return null;\r\n return html;\r\n } catch {\r\n return null;\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n}\r\n\r\nasync function webFetch(url: string, extractLinks: boolean): Promise<WebFetchResult> {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), 15000);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n headers: {\r\n 'User-Agent': WEB_USER_AGENT,\r\n 'Accept': 'text/html,application/xhtml+xml',\r\n 'Accept-Language': 'nl,en;q=0.9',\r\n },\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n\r\n if (!response.ok) throw new Error(`Fetch failed: HTTP ${response.status}`);\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n if (!contentType.includes('text/html') && !contentType.includes('text/plain') && !contentType.includes('application/xhtml')) {\r\n throw new Error(`Unsupported content type: ${contentType}. Only HTML/text pages supported.`);\r\n }\r\n\r\n const html = await response.text();\r\n\r\n const links: { href: string; text: string }[] = [];\r\n if (extractLinks) {\r\n const linkRegex = /<a\\s[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\r\n let match;\r\n while ((match = linkRegex.exec(html)) !== null) {\r\n const href = match[1];\r\n const text = match[2].replace(/<[^>]+>/g, '').trim();\r\n if (href && href.startsWith('http')) {\r\n links.push({ href, text: text.slice(0, 100) });\r\n }\r\n }\r\n }\r\n\r\n let text = html\r\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\r\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\r\n .replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '')\r\n .replace(/<nav[\\s\\S]*?<\\/nav>/gi, ' [NAV] ')\r\n .replace(/<header[\\s\\S]*?<\\/header>/gi, ' [HEADER] ')\r\n .replace(/<footer[\\s\\S]*?<\\/footer>/gi, ' [FOOTER] ')\r\n .replace(/<(br|hr)\\s*\\/?>/gi, '\\n')\r\n .replace(/<\\/(p|div|h[1-6]|li|tr|section|article)>/gi, '\\n')\r\n .replace(/<[^>]+>/g, ' ')\r\n .replace(/ /g, ' ')\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/'/g, \"'\")\r\n .replace(/"/g, '\"')\r\n .replace(/[ \\t]+/g, ' ')\r\n .replace(/\\n\\s*\\n/g, '\\n')\r\n .trim();\r\n\r\n const MAX_TEXT = 15000;\r\n if (text.length > MAX_TEXT) {\r\n text = text.slice(0, MAX_TEXT) + '\\n\\n[... truncated at 15000 chars ...]';\r\n }\r\n\r\n return { text, rawHtml: html, links };\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main handler\r\n// ---------------------------------------------------------------------------\r\n\r\nexport async function handleAgentTool(\r\n name: string,\r\n args: Record<string, unknown>,\r\n): Promise<ToolResult> {\r\n switch (name) {\r\n case 'web-search': {\r\n const query = sanitizeString(args.query, 500);\r\n if (!query) throw new Error('query is required');\r\n const maxResults = clamp(Number(args.max_results) || 15, 1, 30);\r\n\r\n const results = await webSearch(query, maxResults);\r\n\r\n if (results.length === 0) {\r\n return { content: [{ type: 'text', text: `No search results found for: \"${query}\"` }] };\r\n }\r\n\r\n const formatted = results.map((r, i) =>\r\n `${i + 1}. ${r.title}\\n URL: ${r.url}\\n ${r.snippet}`\r\n ).join('\\n\\n');\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Search results for \"${query}\" (${results.length} results):\\n\\n${formatted}`,\r\n }],\r\n };\r\n }\r\n\r\n case 'web-fetch': {\r\n const url = sanitizeString(args.url, 2000);\r\n if (!url) throw new Error('url is required');\r\n if (!/^https?:\\/\\//i.test(url)) throw new Error('url must start with http:// or https://');\r\n\r\n const extractLinks = Boolean(args.extract_links);\r\n const result = await webFetch(url, extractLinks);\r\n\r\n let text = `Content from ${url} (${result.text.length} chars):\\n\\n${result.text}`;\r\n\r\n if (extractLinks && result.links.length > 0) {\r\n const linkList = result.links.slice(0, 50).map(l =>\r\n ` ${l.text ? l.text + ': ' : ''}${l.href}`\r\n ).join('\\n');\r\n text += `\\n\\n--- Links (${result.links.length} found, showing max 50) ---\\n${linkList}`;\r\n }\r\n\r\n const pageEmails = extractEmailsFromHtml(result.rawHtml);\r\n const pagePhones = extractPhonesFromHtml(result.rawHtml);\r\n const pageLinkedIn = extractLinkedInFromHtml(result.rawHtml);\r\n\r\n if (pageEmails.length > 0 || pagePhones.length > 0 || pageLinkedIn.length > 0) {\r\n text += '\\n\\n--- Auto-extracted Contact Info ---';\r\n if (pageEmails.length > 0) text += `\\nEmails: ${pageEmails.join(', ')}`;\r\n if (pagePhones.length > 0) text += `\\nPhones: ${pagePhones.join(', ')}`;\r\n if (pageLinkedIn.length > 0) text += `\\nLinkedIn: ${pageLinkedIn.join(', ')}`;\r\n }\r\n\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n case 'web-find-contacts': {\r\n const inputUrl = sanitizeString(args.url, 2000);\r\n if (!inputUrl) throw new Error('url is required');\r\n const companyName = sanitizeString(args.company_name, 500);\r\n const includeSearch = args.include_search !== false;\r\n\r\n const fullUrl = inputUrl.startsWith('http') ? inputUrl : `https://${inputUrl}`;\r\n let baseUrl: URL;\r\n try { baseUrl = new URL(fullUrl); } catch { throw new Error(`Invalid URL: ${inputUrl}`); }\r\n const domain = baseUrl.hostname.replace(/^www\\./, '');\r\n\r\n const urlsToTry = [fullUrl];\r\n if (!fullUrl.includes('www.')) urlsToTry.push(fullUrl.replace('://', '://www.'));\r\n if (fullUrl.startsWith('https')) {\r\n urlsToTry.push(fullUrl.replace('https', 'http'));\r\n if (!fullUrl.includes('www.')) urlsToTry.push(fullUrl.replace('https://', 'http://www.'));\r\n }\r\n let html: string | null = null;\r\n let usedWayback = false;\r\n for (const tryUrl of urlsToTry) {\r\n html = await fetchRawHtml(tryUrl, 12000);\r\n if (html) break;\r\n }\r\n if (!html) {\r\n html = await fetchWaybackHtml(`https://${domain}`, 15000);\r\n if (html) usedWayback = true;\r\n }\r\n if (!html) throw new Error(`Could not fetch ${fullUrl} (site may be down or blocking)`);\r\n\r\n const contactPages = usedWayback ? [] : discoverContactPages(html, fullUrl);\r\n\r\n const pagePromises = contactPages.map(async (pageUrl) => {\r\n const pageHtml = await fetchRawHtml(pageUrl, 8000);\r\n return { url: pageUrl, html: pageHtml };\r\n });\r\n const pageResults = await Promise.allSettled(pagePromises);\r\n\r\n const successPages: string[] = [usedWayback ? `(wayback) ${domain}` : fullUrl];\r\n const allHtmls = [html];\r\n for (const result of pageResults) {\r\n if (result.status === 'fulfilled' && result.value.html) {\r\n allHtmls.push(result.value.html);\r\n successPages.push(result.value.url);\r\n }\r\n }\r\n\r\n if (usedWayback) {\r\n const waybackContactPaths = ['/contact', '/over-ons', '/about', '/team'];\r\n const wbPromises = waybackContactPaths.map(async (path) => {\r\n const wbHtml = await fetchWaybackHtml(`https://${domain}${path}`, 12000);\r\n return { path, html: wbHtml };\r\n });\r\n const wbResults = await Promise.allSettled(wbPromises);\r\n for (const wr of wbResults) {\r\n if (wr.status === 'fulfilled' && wr.value.html) {\r\n allHtmls.push(wr.value.html);\r\n successPages.push(`(wayback) ${domain}${wr.value.path}`);\r\n }\r\n }\r\n }\r\n\r\n const allEmails = new Set<string>();\r\n const allPhones = new Set<string>();\r\n const allLinkedIn = new Set<string>();\r\n\r\n for (const pageHtml of allHtmls) {\r\n for (const e of extractEmailsFromHtml(pageHtml)) allEmails.add(e);\r\n for (const p of extractPhonesFromHtml(pageHtml)) allPhones.add(p);\r\n for (const l of extractLinkedInFromHtml(pageHtml)) allLinkedIn.add(l);\r\n }\r\n\r\n let searchNote = '';\r\n if (includeSearch) {\r\n try {\r\n const queries = companyName\r\n ? [`\"${companyName}\" \"${domain}\" email`, `\"@${domain}\" email`]\r\n : [`\"${domain}\" email contact`, `\"@${domain}\" email`, `site:${domain} \"@\"`];\r\n\r\n let totalSearchResults = 0;\r\n for (const searchQuery of queries) {\r\n const searchResults = await webSearch(searchQuery, 8);\r\n totalSearchResults += searchResults.length;\r\n\r\n for (const r of searchResults) {\r\n const combined = `${r.title} ${r.snippet}`;\r\n const decoded = decodeHtmlEntities(decodeUnicodeEscapes(combined));\r\n const snippetEmails = decoded.match(EMAIL_REGEX) || [];\r\n for (const e of snippetEmails) {\r\n const lower = e.toLowerCase();\r\n const domainBase = domain.split('.')[0] ?? domain;\r\n if (lower.includes(domainBase) && !NOISE_EMAIL_PATTERNS.some(p => p.test(lower))) {\r\n allEmails.add(lower);\r\n }\r\n }\r\n\r\n const snippetPhones = decoded.match(PHONE_NL_REGEX) || [];\r\n for (const p of snippetPhones) {\r\n const clean = p.replace(/[\\s\\-().]/g, '');\r\n if (clean.length >= 10 && clean.length <= 14) allPhones.add(p.trim());\r\n }\r\n\r\n const snippetLi = decoded.match(LINKEDIN_REGEX) || [];\r\n for (const l of snippetLi) allLinkedIn.add(l.replace(/\\/$/, ''));\r\n }\r\n if (allEmails.size > 0) break;\r\n }\r\n searchNote = ` + ${totalSearchResults} search results`;\r\n } catch { searchNote = ' (search failed)'; }\r\n }\r\n\r\n const foundEmails = [...allEmails];\r\n const generalPatterns = /^(info|contact|hello|admin|office|receptie|secretariaat|verkoop|administratie|support|service|boekingen|reserveringen)@/i;\r\n const generalEmails = foundEmails.filter(e => generalPatterns.test(e));\r\n const personalEmails = foundEmails.filter(e => !generalPatterns.test(e));\r\n\r\n const guessed = guessCommonEmails(domain);\r\n const newGuesses = guessed.filter(g => !allEmails.has(g));\r\n\r\n const lines = [\r\n `=== CONTACT SCAN: ${domain} ===`,\r\n `Pages scanned: ${successPages.length}${searchNote}`,\r\n '',\r\n ];\r\n\r\n if (foundEmails.length > 0) {\r\n lines.push(`EMAILS FOUND (${foundEmails.length}):`);\r\n if (generalEmails.length > 0) {\r\n lines.push(' General:');\r\n for (const e of generalEmails) lines.push(` * ${e}`);\r\n }\r\n if (personalEmails.length > 0) {\r\n lines.push(' Personal/Department:');\r\n for (const e of personalEmails) lines.push(` * ${e}`);\r\n }\r\n } else {\r\n lines.push('EMAILS FOUND: None on website');\r\n lines.push('SUGGESTED EMAILS (common patterns, verify before use):');\r\n for (const e of newGuesses) lines.push(` ? ${e}`);\r\n }\r\n\r\n lines.push('');\r\n if ([...allPhones].length > 0) {\r\n lines.push(`PHONE NUMBERS (${allPhones.size}):`);\r\n for (const p of allPhones) lines.push(` ${p}`);\r\n } else {\r\n lines.push('PHONE NUMBERS: None found');\r\n }\r\n\r\n lines.push('');\r\n if ([...allLinkedIn].length > 0) {\r\n lines.push(`LINKEDIN (${allLinkedIn.size}):`);\r\n for (const l of allLinkedIn) lines.push(` ${l}`);\r\n }\r\n\r\n lines.push('', 'PAGES CHECKED:');\r\n for (const p of successPages) lines.push(` [OK] ${p}`);\r\n const failedPages = contactPages.filter(p => !successPages.includes(p));\r\n for (const p of failedPages) lines.push(` [--] ${p}`);\r\n\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n default:\r\n return { content: [{ type: 'text', text: `Unknown tool: ${name}` }] };\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\r\nimport { CallToolRequestSchema, ListToolsRequestSchema, isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';\r\nimport { createServer as createHttpServer } from 'node:http';\r\nimport { randomUUID } from 'node:crypto';\r\nimport { createClient } from '@supabase/supabase-js';\r\nimport { createHash, randomBytes, createCipheriv, createDecipheriv } from 'crypto';\r\nimport { spawn } from 'node:child_process';\r\nimport { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';\r\nimport { createReadStream, existsSync, statSync } from 'node:fs';\r\nimport { tmpdir } from 'node:os';\r\nimport { isAbsolute, join } from 'node:path';\r\nimport { Readable } from 'node:stream';\r\nimport { Client as SshClient } from 'ssh2';\r\nimport {\r\n TRIGGER_TOOLS,\r\n TRIGGER_TOOL_NAMES,\r\n TRIGGER_TOOL_MODULE_MAP,\r\n handleTriggerTool,\r\n} from './trigger-tools.js';\r\nimport {\r\n AGENT_TOOLS,\r\n AGENT_TOOL_NAMES,\r\n AGENT_TOOL_MODULE_MAP,\r\n handleAgentTool,\r\n} from './agent-tools.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// CLI argument parsing\r\n// ---------------------------------------------------------------------------\r\n\r\nconst args = process.argv.slice(2);\r\n\r\nfunction getArg(name: string): string | undefined {\r\n return args.find(a => a.startsWith(`--${name}=`))?.split('=').slice(1).join('=');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Proxy-bridge mode: when --proxy-url is given we bypass the rest of this\r\n// file entirely and run as a thin SSH-key-authenticated bridge to a remote\r\n// MCP HTTP endpoint (used for the Supabase MCPs behind apps/mcp-proxy).\r\n// ---------------------------------------------------------------------------\r\nconst proxyUrl = getArg('proxy-url') || process.env.MG_DASHBOARD_PROXY_URL;\r\nif (proxyUrl) {\r\n const { runProxyMode } = await import('./proxy-mode.js');\r\n await runProxyMode(args);\r\n // runProxyMode never resolves under normal operation; if it does, exit.\r\n process.exit(0);\r\n}\r\n\r\nconst apiKey = getArg('api-key') || process.env.MG_DASHBOARD_API_KEY;\r\nconst sshKeyPath = getArg('ssh-key') || process.env.MG_DASHBOARD_SSH_KEY;\r\nconst supabaseUrl = getArg('supabase-url') || process.env.SUPABASE_URL;\r\nconst supabaseKey = getArg('supabase-key') || process.env.SUPABASE_SERVICE_ROLE_KEY;\r\nconst encryptionKey = getArg('encryption-key') || process.env.ENCRYPTION_KEY;\r\nconst mijnhostApiKey = getArg('mijnhost-api-key') || process.env.MIJNHOST_API_KEY;\r\nconst httpMode = args.includes('--http');\r\nconst httpPort = Number(getArg('port')) || 3100;\r\n\r\nif (!apiKey || !sshKeyPath) {\r\n console.error('Authentication required. Use both --api-key=dk_xxx and --ssh-key=PATH (path to your SSH private or public key), or set MG_DASHBOARD_API_KEY and MG_DASHBOARD_SSH_KEY.');\r\n process.exit(1);\r\n}\r\n\r\nif (!supabaseUrl || !supabaseKey) {\r\n console.error('Supabase credentials required. Use --supabase-url and --supabase-key or set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY');\r\n process.exit(1);\r\n}\r\n\r\nconst supabase = createClient(supabaseUrl, supabaseKey);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Rate limiting\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface RateLimitEntry {\r\n count: number;\r\n resetAt: number;\r\n}\r\n\r\nclass RateLimiter {\r\n private buckets = new Map<string, RateLimitEntry>();\r\n private readonly maxAttempts: number;\r\n private readonly windowMs: number;\r\n\r\n constructor(maxAttempts: number, windowMs: number) {\r\n this.maxAttempts = maxAttempts;\r\n this.windowMs = windowMs;\r\n }\r\n\r\n /**\r\n * Check if an action is allowed for the given key.\r\n * Increments the counter and returns whether the action should proceed.\r\n */\r\n check(key: string): { allowed: boolean; remaining: number; retryAfterMs: number } {\r\n const now = Date.now();\r\n const entry = this.buckets.get(key);\r\n\r\n if (!entry || now >= entry.resetAt) {\r\n this.buckets.set(key, { count: 1, resetAt: now + this.windowMs });\r\n return { allowed: true, remaining: this.maxAttempts - 1, retryAfterMs: 0 };\r\n }\r\n\r\n entry.count++;\r\n\r\n if (entry.count > this.maxAttempts) {\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n retryAfterMs: entry.resetAt - now,\r\n };\r\n }\r\n\r\n return {\r\n allowed: true,\r\n remaining: this.maxAttempts - entry.count,\r\n retryAfterMs: 0,\r\n };\r\n }\r\n\r\n /** Periodically remove expired entries to prevent unbounded growth. */\r\n cleanup(): void {\r\n const now = Date.now();\r\n for (const [key, entry] of this.buckets) {\r\n if (now >= entry.resetAt) this.buckets.delete(key);\r\n }\r\n }\r\n}\r\n\r\nconst authRateLimiter = new RateLimiter(5, 15 * 60 * 1000);\r\n\r\n// Cleanup expired rate limit entries every 5 minutes\r\nsetInterval(() => {\r\n authRateLimiter.cleanup();\r\n}, 5 * 60 * 1000).unref();\r\n\r\n// Tool-level rate limiting was previously gated per category (ssh / sftp / db\r\n// / default) with hourly buckets. Removed because legitimate dev sessions\r\n// regularly burst over those caps and the resulting \"MCP Rate Limit\" stalls\r\n// were strictly noise — auth-level rate limiting (failed login attempts)\r\n// remains in place above for the actual security concern.\r\n\r\n// ---------------------------------------------------------------------------\r\n// Audit logging\r\n// ---------------------------------------------------------------------------\r\n\r\nconst SENSITIVE_KEYS = new Set(['password', 'private_key', 'passphrase', 'secret', 'token', 'key', 'api_key', 'credentials']);\r\n\r\nfunction redactSensitiveArgs(args: Record<string, unknown>): Record<string, unknown> {\r\n const redacted: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(args)) {\r\n if (SENSITIVE_KEYS.has(k.toLowerCase())) {\r\n redacted[k] = '[REDACTED]';\r\n } else if (typeof v === 'string' && v.length > 500) {\r\n redacted[k] = v.slice(0, 500) + '...[truncated]';\r\n } else {\r\n redacted[k] = v;\r\n }\r\n }\r\n return redacted;\r\n}\r\n\r\nasync function writeAuditLog(entry: {\r\n toolName: string;\r\n arguments?: Record<string, unknown>;\r\n ipAddress?: string;\r\n serverId?: string;\r\n resultStatus: 'success' | 'error';\r\n errorMessage?: string;\r\n durationMs?: number;\r\n}): Promise<void> {\r\n if (!authContext) return;\r\n try {\r\n await supabase.from('mcp_audit_log').insert({\r\n api_key_id: authContext.apiKeyId,\r\n user_id: authContext.userId,\r\n tool_name: entry.toolName,\r\n arguments: entry.arguments ? redactSensitiveArgs(entry.arguments) : null,\r\n ip_address: entry.ipAddress || null,\r\n server_id: entry.serverId || null,\r\n result_status: entry.resultStatus,\r\n error_message: entry.errorMessage?.slice(0, 1000) || null,\r\n duration_ms: entry.durationMs || null,\r\n });\r\n } catch (err) {\r\n console.error('[Audit] Failed to write audit log:', err instanceof Error ? err.message : err);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Permission model (mirrors packages/supabase/src/utils/permissions.ts)\r\n// ---------------------------------------------------------------------------\r\n\r\nconst MODULE_KEYS = [\r\n 'users', 'ssh_servers', 'supabase',\r\n 'wiki', 'ci_cd', 'domains',\r\n 'settings', 'agent_reporting',\r\n] as const;\r\n\r\ntype ModuleKey = (typeof MODULE_KEYS)[number];\r\n\r\ninterface ModulePermissions {\r\n users?: boolean;\r\n ssh_servers?: boolean;\r\n supabase?: boolean;\r\n wiki?: boolean;\r\n ci_cd?: boolean;\r\n\r\n domains?: boolean;\r\n settings?: boolean;\r\n agent_reporting?: boolean;\r\n}\r\n\r\ninterface ResourcePermissions {\r\n ssh_servers: string[];\r\n supabase_instances: string[];\r\n}\r\n\r\ninterface UserPermissions {\r\n modules: ModulePermissions;\r\n resources: ResourcePermissions;\r\n}\r\n\r\nconst FULL_PERMISSIONS: UserPermissions = {\r\n modules: Object.fromEntries(MODULE_KEYS.map((k) => [k, true])) as ModulePermissions,\r\n resources: { ssh_servers: ['*'], supabase_instances: ['*'] },\r\n};\r\n\r\nfunction parsePermissions(raw: unknown): Partial<UserPermissions> | null {\r\n if (!raw || typeof raw !== 'object') return null;\r\n return raw as Partial<UserPermissions>;\r\n}\r\n\r\nfunction resolvePermissions(\r\n roleName: string,\r\n roleDefaults: unknown,\r\n userOverrides: unknown,\r\n): UserPermissions {\r\n if (roleName === 'superadmin') return FULL_PERMISSIONS;\r\n\r\n const base = parsePermissions(roleDefaults);\r\n const overrides = parsePermissions(userOverrides);\r\n\r\n const modules: ModulePermissions = {} as ModulePermissions;\r\n for (const key of MODULE_KEYS) {\r\n const userVal = overrides?.modules?.[key];\r\n const roleVal = base?.modules?.[key];\r\n (modules as Record<string, boolean>)[key] =\r\n userVal !== undefined ? userVal : roleVal !== undefined ? roleVal : false;\r\n }\r\n\r\n const resources: ResourcePermissions = {\r\n ssh_servers: overrides?.resources?.ssh_servers ?? base?.resources?.ssh_servers ?? [],\r\n supabase_instances: overrides?.resources?.supabase_instances ?? base?.resources?.supabase_instances ?? [],\r\n };\r\n\r\n return { modules, resources };\r\n}\r\n\r\n/**\r\n * Intersect key-level server restrictions with user permission resources.\r\n * Most restrictive wins: if both specify lists, return the overlap.\r\n */\r\nfunction intersectServerAccess(\r\n keyServerIds: string[] | null,\r\n permissionServerIds: string[],\r\n): string[] | null {\r\n const keyHasRestriction = keyServerIds !== null;\r\n const permWildcard = permissionServerIds.includes('*');\r\n const permEmpty = permissionServerIds.length === 0;\r\n\r\n if (!keyHasRestriction && permWildcard) return null; // unrestricted\r\n if (!keyHasRestriction && permEmpty) return [];\r\n if (!keyHasRestriction) return permissionServerIds;\r\n if (permWildcard) return keyServerIds;\r\n if (permEmpty) return [];\r\n return keyServerIds.filter((id) => permissionServerIds.includes(id));\r\n}\r\n\r\n/** Maps each MCP tool to the module permission it requires. */\r\nconst TOOL_MODULE_MAP: Partial<Record<string, ModuleKey>> = {\r\n 'list-servers': 'ssh_servers',\r\n 'ssh-execute': 'ssh_servers',\r\n 'sftp-list': 'ssh_servers',\r\n 'sftp-read': 'ssh_servers',\r\n 'sftp-write': 'ssh_servers',\r\n 'sftp-delete': 'ssh_servers',\r\n 'docker-list': 'ssh_servers',\r\n 'docker-logs': 'ssh_servers',\r\n 'docker-exec': 'ssh_servers',\r\n 'docker-compose': 'ssh_servers',\r\n 'db-discover': 'ssh_servers',\r\n 'db-tables': 'ssh_servers',\r\n 'db-describe': 'ssh_servers',\r\n 'db-query': 'ssh_servers',\r\n 'cache-purge': 'ssh_servers',\r\n 'env-list': 'ci_cd',\r\n 'env-get': 'ci_cd',\r\n 'env-store': 'ci_cd',\r\n 'domain-list': 'domains',\r\n 'dns-list': 'domains',\r\n 'dns-create': 'domains',\r\n 'dns-update': 'domains',\r\n 'dns-delete': 'domains',\r\n ...TRIGGER_TOOL_MODULE_MAP,\r\n ...AGENT_TOOL_MODULE_MAP,\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Auth context\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface AuthContext {\r\n apiKeyId: string;\r\n apiKeyName: string;\r\n userId: string;\r\n allowedServerIds: string[] | null;\r\n permissions: UserPermissions;\r\n roleName: string;\r\n}\r\n\r\nlet authContext: AuthContext | null = null;\r\n\r\nasync function validateApiKey(key: string): Promise<AuthContext | null> {\r\n if (!key.startsWith('dk_') || key.length !== 67) {\r\n console.error('Invalid API key format (expected dk_ + 64 hex chars)');\r\n return null;\r\n }\r\n\r\n const keyHash = createHash('sha256').update(key).digest('hex');\r\n\r\n const rateCheck = authRateLimiter.check(keyHash);\r\n if (!rateCheck.allowed) {\r\n const retryMin = Math.ceil(rateCheck.retryAfterMs / 60_000);\r\n console.error(`Rate limited: too many failed auth attempts. Retry in ${retryMin} minute(s).`);\r\n return null;\r\n }\r\n\r\n const { data, error } = await supabase\r\n .from('dashboard_mcp_api_key')\r\n .select('id, name, created_by, allowed_server_ids, is_active, expires_at')\r\n .eq('api_key_hash', keyHash)\r\n .eq('is_active', true)\r\n .single();\r\n\r\n if (error || !data) {\r\n console.error(`API key not found or inactive (${rateCheck.remaining} attempts remaining)`);\r\n return null;\r\n }\r\n\r\n if (data.expires_at && new Date(data.expires_at) < new Date()) {\r\n console.error(`API key has expired (${rateCheck.remaining} attempts remaining)`);\r\n return null;\r\n }\r\n\r\n // Load user + role permissions\r\n const { data: userData, error: userError } = await supabase\r\n .from('user')\r\n .select('permissions, role:role!role_id(name, default_permissions)')\r\n .eq('id', data.created_by)\r\n .single();\r\n\r\n if (userError || !userData) {\r\n console.error(`User not found for API key creator: ${data.created_by}`);\r\n return null;\r\n }\r\n\r\n const roleName = (userData.role as { name?: string })?.name || 'user';\r\n const roleDefaults = (userData.role as { default_permissions?: unknown })?.default_permissions ?? {};\r\n const userOverrides = userData.permissions ?? null;\r\n const permissions = resolvePermissions(roleName, roleDefaults, userOverrides);\r\n\r\n const allowedServerIds = intersectServerAccess(\r\n data.allowed_server_ids,\r\n permissions.resources.ssh_servers,\r\n );\r\n\r\n await supabase\r\n .from('dashboard_mcp_api_key')\r\n .update({ last_used_at: new Date().toISOString() })\r\n .eq('id', data.id);\r\n\r\n const moduleCount = MODULE_KEYS.filter((k) => permissions.modules[k]).length;\r\n console.error(`Authenticated as user ${data.created_by} (role: ${roleName}, modules: ${moduleCount}/${MODULE_KEYS.length})`);\r\n\r\n return {\r\n apiKeyId: data.id,\r\n apiKeyName: data.name || 'Unknown',\r\n userId: data.created_by,\r\n allowedServerIds,\r\n permissions,\r\n roleName,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH-key authentication\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Run a child process and return { stdout, stderr, code }. Never throws. */\r\nfunction runProcess(\r\n command: string,\r\n argv: string[],\r\n options: { stdin?: string; cwd?: string } = {},\r\n): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve) => {\r\n const child = spawn(command, argv, { cwd: options.cwd, stdio: ['pipe', 'pipe', 'pipe'] });\r\n let stdout = '';\r\n let stderr = '';\r\n child.stdout.on('data', (d) => { stdout += d.toString(); });\r\n child.stderr.on('data', (d) => { stderr += d.toString(); });\r\n child.on('error', (err) => {\r\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\r\n });\r\n child.on('close', (code) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n if (options.stdin !== undefined) {\r\n child.stdin.write(options.stdin);\r\n child.stdin.end();\r\n } else {\r\n child.stdin.end();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Resolve the user's SSH public-key file from the path they passed.\r\n *\r\n * Accepts either a `.pub` file directly, or a private-key path (in which case\r\n * we look for `${path}.pub` next to it). Returns the public-key file path and\r\n * its contents trimmed.\r\n */\r\nasync function resolvePubkeyFile(input: string): Promise<{ pubPath: string; pubText: string }> {\r\n const expand = (p: string) => p.startsWith('~')\r\n ? join(process.env.HOME || process.env.USERPROFILE || '', p.slice(1))\r\n : p;\r\n const candidate = expand(input);\r\n let pubPath: string;\r\n if (candidate.endsWith('.pub')) {\r\n pubPath = candidate;\r\n } else if (existsSync(`${candidate}.pub`)) {\r\n pubPath = `${candidate}.pub`;\r\n } else if (existsSync(candidate)) {\r\n // Caller passed a public-key file without `.pub` extension; tolerate it.\r\n pubPath = candidate;\r\n } else {\r\n throw new Error(`SSH key file not found: ${candidate} (also tried ${candidate}.pub)`);\r\n }\r\n const pubText = (await readFile(pubPath, 'utf8')).trim();\r\n if (!pubText) {\r\n throw new Error(`SSH public-key file is empty: ${pubPath}`);\r\n }\r\n return { pubPath, pubText };\r\n}\r\n\r\n/**\r\n * Compute the OpenSSH SHA256 fingerprint (\"SHA256:abc...\") of a public-key\r\n * line. This matches the format that `ssh-keygen -lf <pubkey>` prints and\r\n * what we store in `dashboard_mcp_ssh_key.fingerprint_sha256`.\r\n */\r\nfunction computeOpenSshFingerprint(pubkeyLine: string): string {\r\n const parts = pubkeyLine.trim().split(/\\s+/);\r\n if (parts.length < 2 || !parts[1]) {\r\n throw new Error('Invalid SSH public-key line (expected \"<type> <base64> [comment]\")');\r\n }\r\n const bodyBytes = Buffer.from(parts[1], 'base64');\r\n const hash = createHash('sha256').update(bodyBytes).digest('base64').replace(/=+$/, '');\r\n return `SHA256:${hash}`;\r\n}\r\n\r\n/**\r\n * Sign a challenge with the user's SSH key (via ssh-agent or on-disk key).\r\n * Uses `ssh-keygen -Y sign` (SSHSIG format, OpenSSH >= 8.2).\r\n *\r\n * Returns the armored signature (\"-----BEGIN SSH SIGNATURE----- ...\").\r\n */\r\nasync function sshKeygenSign(pubkeyPath: string, challenge: string, namespace: string): Promise<string> {\r\n const result = await runProcess(\r\n 'ssh-keygen',\r\n ['-Y', 'sign', '-f', pubkeyPath, '-n', namespace, '-q'],\r\n { stdin: challenge },\r\n );\r\n if (result.code !== 0) {\r\n throw new Error(\r\n `ssh-keygen sign failed (exit ${result.code}). ` +\r\n `Make sure ssh-agent is running and has the matching private key loaded ` +\r\n `(or that the private key is at the path next to the .pub file). ` +\r\n `stderr: ${result.stderr.trim() || '(empty)'}`,\r\n );\r\n }\r\n if (!result.stdout.includes('BEGIN SSH SIGNATURE')) {\r\n throw new Error(`ssh-keygen sign produced no signature (stderr: ${result.stderr.trim() || '(empty)'})`);\r\n }\r\n return result.stdout;\r\n}\r\n\r\n/**\r\n * Verify an SSHSIG armored signature against a known public-key line.\r\n * Returns true if the signature is valid.\r\n */\r\nasync function sshKeygenVerify(\r\n pubkeyLine: string,\r\n signature: string,\r\n challenge: string,\r\n namespace: string,\r\n): Promise<boolean> {\r\n const dir = await mkdtemp(join(tmpdir(), 'mcp-ssh-verify-'));\r\n try {\r\n const allowedSigners = `mcp@local ${pubkeyLine.trim()}\\n`;\r\n const allowedPath = join(dir, 'allowed_signers');\r\n const sigPath = join(dir, 'sig');\r\n await writeFile(allowedPath, allowedSigners, 'utf8');\r\n await writeFile(sigPath, signature, 'utf8');\r\n const result = await runProcess(\r\n 'ssh-keygen',\r\n ['-Y', 'verify', '-f', allowedPath, '-I', 'mcp@local', '-n', namespace, '-s', sigPath, '-q'],\r\n { stdin: challenge },\r\n );\r\n return result.code === 0;\r\n } finally {\r\n await rm(dir, { recursive: true, force: true }).catch(() => undefined);\r\n }\r\n}\r\n\r\n/**\r\n * Authenticate to the dashboard using an SSH key.\r\n *\r\n * 1. Read the user's pubkey file and compute its SHA256 fingerprint.\r\n * 2. Generate a fresh nonce, sign it via `ssh-keygen -Y sign` (uses ssh-agent\r\n * or the private key on disk), then locally verify the signature against\r\n * the pubkey we read. This proves the caller actually possesses the\r\n * private key (or has it loaded in ssh-agent), not just a stolen pubkey.\r\n * 3. Look up the fingerprint in `dashboard_mcp_ssh_key`, require it to be\r\n * linked to the already validated API key, then load permissions exactly\r\n * like the bearer-token path does.\r\n *\r\n * The signature step is optional but defaults to ON. Set\r\n * `MG_DASHBOARD_SSH_SKIP_VERIFY=1` to skip it (e.g. for first-time enrollment\r\n * before the key is registered, where you just want to print the fingerprint).\r\n */\r\nasync function validateSshKey(\r\n pubkeyPathInput: string,\r\n expectedApiKeyId: string,\r\n): Promise<AuthContext | null> {\r\n let pubPath: string;\r\n let pubText: string;\r\n try {\r\n const resolved = await resolvePubkeyFile(pubkeyPathInput);\r\n pubPath = resolved.pubPath;\r\n pubText = resolved.pubText;\r\n } catch (err) {\r\n console.error(`SSH key error: ${err instanceof Error ? err.message : String(err)}`);\r\n return null;\r\n }\r\n\r\n let fingerprint: string;\r\n try {\r\n fingerprint = computeOpenSshFingerprint(pubText);\r\n } catch (err) {\r\n console.error(`SSH key error: ${err instanceof Error ? err.message : String(err)}`);\r\n return null;\r\n }\r\n\r\n const rateCheck = authRateLimiter.check(fingerprint);\r\n if (!rateCheck.allowed) {\r\n const retryMin = Math.ceil(rateCheck.retryAfterMs / 60_000);\r\n console.error(`Rate limited: too many failed SSH-key auth attempts. Retry in ${retryMin} minute(s).`);\r\n return null;\r\n }\r\n\r\n const skipVerify = process.env.MG_DASHBOARD_SSH_SKIP_VERIFY === '1';\r\n if (!skipVerify) {\r\n try {\r\n const challenge = randomBytes(32).toString('hex');\r\n const signature = await sshKeygenSign(pubPath, challenge, 'mg-dashboard-mcp');\r\n const verified = await sshKeygenVerify(pubText, signature, challenge, 'mg-dashboard-mcp');\r\n if (!verified) {\r\n console.error('SSH-key challenge verification failed (signature did not validate against the public key).');\r\n return null;\r\n }\r\n } catch (err) {\r\n console.error(`SSH-key challenge failed: ${err instanceof Error ? err.message : String(err)}`);\r\n console.error('Tip: set MG_DASHBOARD_SSH_SKIP_VERIFY=1 to skip the challenge if you only need to print the fingerprint for enrollment.');\r\n return null;\r\n }\r\n }\r\n\r\n const { data: keyRow, error: keyErr } = await supabase\r\n .from('dashboard_mcp_ssh_key')\r\n .select('id, name, api_key_id, is_active')\r\n .eq('fingerprint_sha256', fingerprint)\r\n .eq('is_active', true)\r\n .maybeSingle();\r\n\r\n if (keyErr || !keyRow) {\r\n console.error(\r\n `SSH key not registered (fingerprint ${fingerprint}; ${rateCheck.remaining} attempts remaining). ` +\r\n `Add it under MCP API Keys → SSH Keys in the dashboard.`,\r\n );\r\n return null;\r\n }\r\n\r\n if (keyRow.api_key_id !== expectedApiKeyId) {\r\n console.error(\r\n `SSH key \"${keyRow.name}\" is registered, but it is not linked to the provided MCP API key. ` +\r\n `Add this SSH key under the same MCP API Key entry used by --api-key.`,\r\n );\r\n return null;\r\n }\r\n\r\n const { data: apiRow, error: apiErr } = await supabase\r\n .from('dashboard_mcp_api_key')\r\n .select('id, name, created_by, allowed_server_ids, is_active, expires_at')\r\n .eq('id', keyRow.api_key_id)\r\n .eq('is_active', true)\r\n .maybeSingle();\r\n\r\n if (apiErr || !apiRow) {\r\n console.error('SSH key is linked to an inactive or missing MCP API key entry.');\r\n return null;\r\n }\r\n\r\n if (apiRow.expires_at && new Date(apiRow.expires_at) < new Date()) {\r\n console.error('Linked MCP API key entry has expired.');\r\n return null;\r\n }\r\n\r\n const { data: userData, error: userError } = await supabase\r\n .from('user')\r\n .select('permissions, role:role!role_id(name, default_permissions)')\r\n .eq('id', apiRow.created_by)\r\n .single();\r\n\r\n if (userError || !userData) {\r\n console.error(`User not found for SSH key creator: ${apiRow.created_by}`);\r\n return null;\r\n }\r\n\r\n const roleName = (userData.role as { name?: string })?.name || 'user';\r\n const roleDefaults = (userData.role as { default_permissions?: unknown })?.default_permissions ?? {};\r\n const userOverrides = userData.permissions ?? null;\r\n const permissions = resolvePermissions(roleName, roleDefaults, userOverrides);\r\n\r\n const allowedServerIds = intersectServerAccess(\r\n apiRow.allowed_server_ids,\r\n permissions.resources.ssh_servers,\r\n );\r\n\r\n const nowIso = new Date().toISOString();\r\n await Promise.all([\r\n supabase.from('dashboard_mcp_ssh_key').update({ last_used_at: nowIso }).eq('id', keyRow.id),\r\n supabase.from('dashboard_mcp_api_key').update({ last_used_at: nowIso }).eq('id', apiRow.id),\r\n ]);\r\n\r\n const moduleCount = MODULE_KEYS.filter((k) => permissions.modules[k]).length;\r\n console.error(\r\n `Authenticated via SSH key \"${keyRow.name}\" (fp ${fingerprint.slice(0, 24)}...) ` +\r\n `as user ${apiRow.created_by} (role: ${roleName}, modules: ${moduleCount}/${MODULE_KEYS.length})`,\r\n );\r\n\r\n return {\r\n apiKeyId: apiRow.id,\r\n apiKeyName: `${apiRow.name || 'Unknown'} (ssh: ${keyRow.name})`,\r\n userId: apiRow.created_by,\r\n allowedServerIds,\r\n permissions,\r\n roleName,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Server access helper\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction assertServerAccess(serverId: string): void {\r\n if (!authContext) throw new Error('Not authenticated');\r\n if (authContext.allowedServerIds === null) return;\r\n if (!authContext.allowedServerIds.includes(serverId)) {\r\n throw new Error(`Access denied: you do not have permission for server ${serverId}`);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Release profile resolution helper\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Resolve a release profile name to its stage IDs.\r\n * Returns { stageIds, profileId } or throws with available profile names.\r\n */\r\nasync function resolveReleaseProfileStageIds(\r\n profileName: string,\r\n): Promise<{ stageIds: string[]; profileId: string }> {\r\n const { data: profile, error } = await supabase\r\n .from('release_profile')\r\n .select('id, name')\r\n .ilike('name', profileName)\r\n .maybeSingle();\r\n\r\n if (error) throw new Error(`Failed to look up release profile: ${error.message}`);\r\n\r\n if (!profile) {\r\n const { data: all } = await supabase\r\n .from('release_profile')\r\n .select('name')\r\n .order('name');\r\n const names = (all || []).map((p) => p.name).join(', ');\r\n throw new Error(\r\n `Release profile \"${profileName}\" not found. Available profiles: ${names || '(none)'}`,\r\n );\r\n }\r\n\r\n const { data: stages, error: stageErr } = await supabase\r\n .from('release_profile_stage')\r\n .select('id')\r\n .eq('release_profile_id', profile.id);\r\n\r\n if (stageErr) throw new Error(`Failed to look up stages: ${stageErr.message}`);\r\n if (!stages || stages.length === 0) {\r\n throw new Error(`Release profile \"${profile.name}\" has no stages configured`);\r\n }\r\n\r\n return { stageIds: stages.map((s) => s.id), profileId: profile.id };\r\n}\r\n\r\n/**\r\n * Look up release profile names for a set of stage IDs.\r\n * Returns a map of stageId -> profileName.\r\n */\r\nasync function getProfileNamesForStageIds(\r\n stageIds: string[],\r\n): Promise<Record<string, string>> {\r\n if (stageIds.length === 0) return {};\r\n\r\n const { data: stages } = await supabase\r\n .from('release_profile_stage')\r\n .select('id, release_profile_id')\r\n .in('id', stageIds);\r\n\r\n if (!stages || stages.length === 0) return {};\r\n\r\n const profileIds = [...new Set(stages.map((s) => s.release_profile_id))];\r\n const { data: profiles } = await supabase\r\n .from('release_profile')\r\n .select('id, name')\r\n .in('id', profileIds);\r\n\r\n if (!profiles) return {};\r\n\r\n const profileMap: Record<string, string> = {};\r\n for (const p of profiles) profileMap[p.id] = p.name;\r\n\r\n const result: Record<string, string> = {};\r\n for (const s of stages) {\r\n result[s.id] = profileMap[s.release_profile_id] || 'unknown';\r\n }\r\n return result;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Encryption helpers (AES-256-GCM, compatible with dashboard encryption.ts)\r\n// ---------------------------------------------------------------------------\r\n\r\nconst ENC_ALGORITHM = 'aes-256-gcm';\r\nconst ENC_IV_LENGTH = 16;\r\nconst ENC_TAG_LENGTH = 16;\r\n\r\nfunction getEncryptionKey(): Buffer {\r\n if (!encryptionKey) throw new Error('ENCRYPTION_KEY is required for env operations');\r\n const buf = Buffer.from(encryptionKey, 'hex');\r\n if (buf.length !== 32) throw new Error('ENCRYPTION_KEY must be a 64-character hex string');\r\n return buf;\r\n}\r\n\r\nfunction encrypt(text: string): string {\r\n const key = getEncryptionKey();\r\n const iv = randomBytes(ENC_IV_LENGTH);\r\n const cipher = createCipheriv(ENC_ALGORITHM, new Uint8Array(key), new Uint8Array(iv));\r\n let encrypted = cipher.update(text, 'utf8', 'hex');\r\n encrypted += cipher.final('hex');\r\n const authTag = cipher.getAuthTag();\r\n return Buffer.concat([\r\n new Uint8Array(iv),\r\n new Uint8Array(authTag),\r\n new Uint8Array(Buffer.from(encrypted, 'hex')),\r\n ]).toString('base64');\r\n}\r\n\r\nfunction decrypt(payload: string): string {\r\n const key = getEncryptionKey();\r\n const buf = Buffer.from(payload, 'base64');\r\n const iv = buf.subarray(0, ENC_IV_LENGTH);\r\n const authTag = buf.subarray(ENC_IV_LENGTH, ENC_IV_LENGTH + ENC_TAG_LENGTH);\r\n const encrypted = buf.subarray(ENC_IV_LENGTH + ENC_TAG_LENGTH);\r\n const decipher = createDecipheriv(ENC_ALGORITHM, new Uint8Array(key), new Uint8Array(iv));\r\n decipher.setAuthTag(new Uint8Array(authTag));\r\n let decrypted = decipher.update(encrypted.toString('hex'), 'hex', 'utf8');\r\n decrypted += decipher.final('utf8');\r\n return decrypted;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Vercel env sync helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst VERCEL_API = 'https://api.vercel.com';\r\n\r\n/**\r\n * Parse a .env content string into key-value pairs.\r\n * Lines starting with # and empty lines are skipped.\r\n */\r\nfunction parseEnvContent(content: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const line of content.split('\\n')) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n const eqIdx = trimmed.indexOf('=');\r\n if (eqIdx === -1) continue;\r\n const key = trimmed.slice(0, eqIdx).trim();\r\n let value = trimmed.slice(eqIdx + 1).trim();\r\n if (\r\n (value.startsWith('\"') && value.endsWith('\"')) ||\r\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\r\n ) {\r\n value = value.slice(1, -1);\r\n }\r\n if (key) result[key] = value;\r\n }\r\n return result;\r\n}\r\n\r\ninterface VercelEnvVar {\r\n key: string;\r\n value: string;\r\n type: 'encrypted';\r\n target?: ('production' | 'preview' | 'development')[];\r\n customEnvironmentIds?: string[];\r\n}\r\n\r\ninterface StageApp {\r\n path: string;\r\n label: string;\r\n deployMethod: string;\r\n enabled: boolean;\r\n vercelProjectId?: string | null;\r\n vercelCustomEnvId?: string | null;\r\n}\r\n\r\n/**\r\n * Map stage type to Vercel target environments or custom environment ID.\r\n */\r\nfunction stageToVercelTargets(\r\n stageType: 'dev' | 'staging' | 'prod',\r\n customEnvId?: string | null,\r\n): { target?: ('production' | 'preview' | 'development')[]; customEnvironmentIds?: string[] } {\r\n if (stageType === 'prod') return { target: ['production'] };\r\n if (customEnvId) return { customEnvironmentIds: [customEnvId] };\r\n return { target: ['preview'] };\r\n}\r\n\r\n/** Dev stages also sync to built-in `development` for `vercel dev` (matches dashboard). */\r\nfunction getVercelEnvSyncTargetings(\r\n stageType: 'dev' | 'staging' | 'prod',\r\n customEnvId?: string | null,\r\n): Array<{ target?: ('production' | 'preview' | 'development')[]; customEnvironmentIds?: string[] }> {\r\n const primary = stageToVercelTargets(stageType, customEnvId);\r\n if (stageType !== 'dev') return [primary];\r\n return [primary, { target: ['development'] }];\r\n}\r\n\r\n/**\r\n * Push env vars to a Vercel project using upsert.\r\n */\r\nasync function syncEnvVarsToVercel(\r\n token: string,\r\n projectId: string,\r\n envVars: VercelEnvVar[],\r\n): Promise<{ created: number; error: string | null }> {\r\n if (envVars.length === 0) return { created: 0, error: null };\r\n\r\n const res = await fetch(\r\n `${VERCEL_API}/v10/projects/${encodeURIComponent(projectId)}/env?upsert=true`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(envVars),\r\n },\r\n );\r\n\r\n if (!res.ok) {\r\n const body = await res.text().catch(() => '');\r\n return { created: 0, error: `Vercel API ${res.status}: ${body}` };\r\n }\r\n\r\n const data = await res.json().catch(() => ({}));\r\n return { created: (data as any)?.created?.length ?? envVars.length, error: null };\r\n}\r\n\r\n/**\r\n * After an env_config upsert, attempt to sync env vars to Vercel for the\r\n * linked stage. Resolves the stage via `release_profile_stage_id` on the\r\n * record or by looking up siblings with the same `app_name`.\r\n *\r\n * Returns a status string for inclusion in the MCP response.\r\n */\r\nasync function attemptVercelSync(appName: string, environment: string, knownStageId?: string): Promise<string> {\r\n try {\r\n // 1. Find the stage linked to this app_name\r\n let stageId = knownStageId;\r\n if (!stageId) {\r\n const { data: direct } = await supabase\r\n .from('env_config')\r\n .select('release_profile_stage_id')\r\n .eq('app_name', appName)\r\n .not('release_profile_stage_id', 'is', null)\r\n .limit(1)\r\n .single();\r\n\r\n stageId = direct?.release_profile_stage_id;\r\n }\r\n if (!stageId) return 'Vercel sync skipped: no stage link found';\r\n\r\n // 2. Get Vercel token\r\n const { data: settings } = await supabase\r\n .from('app_setting')\r\n .select('vercel_token_encrypted')\r\n .maybeSingle();\r\n\r\n if (!settings?.vercel_token_encrypted) return 'Vercel sync skipped: no Vercel token configured';\r\n\r\n let token: string;\r\n try {\r\n token = decrypt(settings.vercel_token_encrypted);\r\n } catch {\r\n return 'Vercel sync failed: could not decrypt Vercel token';\r\n }\r\n\r\n // 3. Fetch stage + stage_apps\r\n const { data: stage } = await supabase\r\n .from('release_profile_stage')\r\n .select('id, stage, stage_apps')\r\n .eq('id', stageId)\r\n .single();\r\n\r\n if (!stage) return 'Vercel sync skipped: stage not found';\r\n\r\n const stageType = stage.stage as 'dev' | 'staging' | 'prod';\r\n const stageApps: StageApp[] = (stage.stage_apps as StageApp[]) || [];\r\n const vercelApps = stageApps.filter(\r\n (a) => a.deployMethod === 'vercel' && a.enabled && a.vercelProjectId,\r\n );\r\n\r\n if (vercelApps.length === 0) return 'Vercel sync skipped: no Vercel apps in stage';\r\n\r\n // 4. Fetch all env_configs for the stage\r\n const { data: envConfigs } = await supabase\r\n .from('env_config')\r\n .select('*')\r\n .eq('release_profile_stage_id', stageId);\r\n\r\n if (!envConfigs || envConfigs.length === 0) return 'Vercel sync skipped: no env configs for stage';\r\n\r\n const variantMap: Record<string, string> = {\r\n dev: 'development',\r\n staging: 'staging',\r\n prod: 'production',\r\n };\r\n const deployedVariant = variantMap[stageType] ?? stageType;\r\n\r\n // 5. Sync each Vercel app\r\n const syncResults: string[] = [];\r\n for (const app of vercelApps) {\r\n const name = app.path.replace('apps/', '');\r\n const config = envConfigs.find(\r\n (c: any) => c.app_name === name && c.variant === deployedVariant,\r\n );\r\n\r\n if (!config) {\r\n syncResults.push(`${app.label}: skipped (no config for variant \"${deployedVariant}\")`);\r\n continue;\r\n }\r\n\r\n let envContent: string;\r\n try {\r\n envContent = decrypt((config as any).env_data_encrypted);\r\n } catch {\r\n syncResults.push(`${app.label}: decrypt failed`);\r\n continue;\r\n }\r\n\r\n const pairs = parseEnvContent(envContent);\r\n const keys = Object.keys(pairs);\r\n if (keys.length === 0) {\r\n syncResults.push(`${app.label}: empty config`);\r\n continue;\r\n }\r\n\r\n const targetings = getVercelEnvSyncTargetings(stageType, app.vercelCustomEnvId);\r\n let createdTotal = 0;\r\n let lastErr: string | null = null;\r\n\r\n for (const targeting of targetings) {\r\n const envVars: VercelEnvVar[] = keys.map((key) => ({\r\n key,\r\n value: pairs[key]!,\r\n type: 'encrypted' as const,\r\n ...targeting,\r\n }));\r\n\r\n const { created, error } = await syncEnvVarsToVercel(token, app.vercelProjectId!, envVars);\r\n if (error) lastErr = error;\r\n else createdTotal += created;\r\n }\r\n\r\n if (lastErr) {\r\n syncResults.push(`${app.label}: FAILED - ${lastErr}`);\r\n } else {\r\n syncResults.push(`${app.label}: ${createdTotal} var upsert(s) synced`);\r\n }\r\n }\r\n\r\n return `Vercel sync: ${syncResults.join('; ')}`;\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n return `Vercel sync error: ${msg}`;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n// ---------------------------------------------------------------------------\r\n// Shell quoting / OS-aware command builders\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * POSIX shell single-quote escape. Wraps in `'...'` and escapes any embedded\r\n * `'` as `'\\''`. Bare-word fast-path for safe characters skips quoting.\r\n * Used by ssh-execute (linux mode), docker-exec, sftp-list pattern building,\r\n * and anywhere we previously relied on the LLM to escape `$`, `#`, spaces,\r\n * etc. inside command strings.\r\n */\r\nfunction posixQuote(arg: string): string {\r\n if (arg === '') return \"''\";\r\n if (/^[A-Za-z0-9._\\/=:@%+\\-]+$/.test(arg)) return arg;\r\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\r\n}\r\n\r\n/**\r\n * Build a POSIX shell command line from a program + argv. The program itself\r\n * is NOT quoted if it's a simple identifier/path (so `cd` / `docker compose`\r\n * keep working when passed as `command: 'docker compose'` with args).\r\n */\r\nfunction buildPosixCommand(command: string, args: string[]): string {\r\n const program = /^[A-Za-z0-9._\\/\\- ]+$/.test(command) ? command : posixQuote(command);\r\n if (args.length === 0) return program;\r\n return `${program} ${args.map(posixQuote).join(' ')}`;\r\n}\r\n\r\n/**\r\n * Build a PowerShell `-EncodedCommand` invocation. PowerShell decodes the\r\n * UTF-16LE-base64 payload itself, so embedded `$`, `'`, `\"`, `#`, spaces, etc.\r\n * never see cmd.exe parsing — this is the only quoting-safe way to call\r\n * PowerShell over SSH on Windows servers.\r\n */\r\nfunction buildPowerShellEncodedCommand(command: string, args: string[]): string {\r\n const psSingleQuote = (s: string) => \"'\" + s.replace(/'/g, \"''\") + \"'\";\r\n let body: string;\r\n if (args.length === 0) {\r\n body = command;\r\n } else {\r\n body = `& ${psSingleQuote(command)} ${args.map(psSingleQuote).join(' ')}`;\r\n }\r\n // Suppress PowerShell's progress CLIXML stream that otherwise pollutes stderr\r\n // with `<Objs Version=\"1.1.0.1\" ...>` blobs on first use of certain cmdlets.\r\n const psExpr = `$ProgressPreference='SilentlyContinue'; ${body}`;\r\n const utf16 = Buffer.from(psExpr, 'utf16le');\r\n const b64 = utf16.toString('base64');\r\n // -OutputFormat Text disables PowerShell's CLIXML serialization of errors/objects\r\n // when run as a subprocess (default is XML for non-interactive). Combined with\r\n // $ProgressPreference above, this gives clean text on stdout/stderr.\r\n return `powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand ${b64}`;\r\n}\r\n\r\ninterface SshConnectionOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\ninterface SshResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n}\r\n\r\nconst SSH_PROXY_SERVER_ID = '03659d55-e194-400d-b82a-bf6457371ded';\r\nlet _proxyConnCache: SshConnectionOptions | null = null;\r\n\r\nasync function getProxyConnection(): Promise<SshConnectionOptions> {\r\n if (_proxyConnCache) return _proxyConnCache;\r\n\r\n const { data, error } = await supabase\r\n .from('ssh_server')\r\n .select('hostname, port, username, password_encrypted, ssh_key_encrypted, ssh_key_passphrase_encrypted')\r\n .eq('id', SSH_PROXY_SERVER_ID)\r\n .single();\r\n\r\n if (error || !data) throw new Error('SSH Proxy server not found in database');\r\n if (!encryptionKey) throw new Error('ENCRYPTION_KEY required to decrypt server credentials');\r\n\r\n _proxyConnCache = {\r\n hostname: data.hostname,\r\n port: data.port || 22,\r\n username: data.username,\r\n password: data.password_encrypted ? decrypt(data.password_encrypted) : undefined,\r\n privateKey: data.ssh_key_encrypted ? decrypt(data.ssh_key_encrypted) : undefined,\r\n passphrase: data.ssh_key_passphrase_encrypted ? decrypt(data.ssh_key_passphrase_encrypted) : undefined,\r\n };\r\n return _proxyConnCache;\r\n}\r\n\r\ntype ServerOs = 'linux' | 'windows';\r\n\r\n/**\r\n * Get connection options for a server. When `allowed_ssh_ips` is configured,\r\n * also returns proxy options so callers can route through the SSH Proxy.\r\n *\r\n * Also returns the server's `os_type` so callers (notably ssh-execute) can\r\n * pick the right shell wrapper (bash vs PowerShell -EncodedCommand).\r\n */\r\nasync function getServerConnection(\r\n serverId: string,\r\n): Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions; os: ServerOs }> {\r\n assertServerAccess(serverId);\r\n\r\n const { data, error } = await supabase\r\n .from('ssh_server')\r\n .select('hostname, port, username, password_encrypted, ssh_key_encrypted, ssh_key_passphrase_encrypted, allowed_ssh_ips, os_type')\r\n .eq('id', serverId)\r\n .single();\r\n\r\n if (error || !data) throw new Error(`Server not found: ${serverId}`);\r\n if (!encryptionKey) throw new Error('ENCRYPTION_KEY required to decrypt server credentials');\r\n\r\n const conn: SshConnectionOptions = {\r\n hostname: data.hostname,\r\n port: data.port || 22,\r\n username: data.username,\r\n password: data.password_encrypted ? decrypt(data.password_encrypted) : undefined,\r\n privateKey: data.ssh_key_encrypted ? decrypt(data.ssh_key_encrypted) : undefined,\r\n passphrase: data.ssh_key_passphrase_encrypted ? decrypt(data.ssh_key_passphrase_encrypted) : undefined,\r\n };\r\n\r\n const needsProxy = data.allowed_ssh_ips !== null && serverId !== SSH_PROXY_SERVER_ID;\r\n const proxy = needsProxy ? await getProxyConnection() : undefined;\r\n const os: ServerOs = (data as { os_type?: string }).os_type === 'windows' ? 'windows' : 'linux';\r\n\r\n return { conn, proxy, os };\r\n}\r\n\r\n/**\r\n * Execute an SSH command, optionally tunnelling through a proxy (ProxyJump).\r\n * When proxy is provided, the target server only sees the proxy's IP.\r\n *\r\n * `stdin` lets callers pipe data into the remote process (used by ssh-execute\r\n * smart mode + db-* helpers to avoid command-line escape hell with passwords,\r\n * SQL queries, scripts containing `$` or `#`, etc.).\r\n */\r\nasync function sshExec(\r\n opts: SshConnectionOptions,\r\n command: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { stdin?: string; pty?: boolean },\r\n): Promise<SshResult> {\r\n if (proxy) return sshExecViaProxy(proxy, opts, command, options);\r\n\r\n return new Promise((resolve) => {\r\n const ssh = new SshClient();\r\n let stdout = '';\r\n let stderr = '';\r\n let done = false;\r\n const timeout = opts.timeout || 60_000;\r\n\r\n const timer = setTimeout(() => {\r\n if (!done) { done = true; ssh.end(); resolve({ stdout, stderr, exitCode: -1 }); }\r\n }, timeout);\r\n\r\n ssh.on('ready', () => {\r\n // Allocating a PTY collapses stderr into stdout (a real terminal has no\r\n // separate stderr fd) which is exactly what callers want for tty-mode\r\n // commands like `psql`/`mysql`/`bash`. Without pty: stderr is captured\r\n // separately so structured tools still get clean stderr.\r\n const execOpts = options?.pty ? { pty: true } : {};\r\n ssh.exec(command, execOpts, (err, stream) => {\r\n if (err) {\r\n if (!done) { done = true; clearTimeout(timer); ssh.end(); resolve({ stdout, stderr, exitCode: -1 }); }\r\n return;\r\n }\r\n stream.on('data', (d: Buffer) => { stdout += d.toString(); });\r\n stream.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\r\n stream.on('close', (code: number | null) => {\r\n if (!done) { done = true; clearTimeout(timer); ssh.end(); resolve({ stdout, stderr, exitCode: code ?? 0 }); }\r\n });\r\n if (options?.stdin !== undefined) {\r\n stream.end(options.stdin);\r\n }\r\n });\r\n });\r\n\r\n ssh.on('error', (err) => {\r\n if (!done) { done = true; clearTimeout(timer); resolve({ stdout, stderr: err.message, exitCode: -1 }); }\r\n });\r\n\r\n ssh.connect({\r\n host: opts.hostname, port: opts.port, username: opts.username,\r\n password: opts.password, privateKey: opts.privateKey, passphrase: opts.passphrase,\r\n readyTimeout: timeout,\r\n });\r\n });\r\n}\r\n\r\nfunction sshExecViaProxy(\r\n proxyOpts: SshConnectionOptions,\r\n targetOpts: SshConnectionOptions,\r\n command: string,\r\n options?: { stdin?: string; pty?: boolean },\r\n): Promise<SshResult> {\r\n return new Promise((resolve) => {\r\n const proxyClient = new SshClient();\r\n let done = false;\r\n const timeout = targetOpts.timeout || 60_000;\r\n\r\n const timer = setTimeout(() => {\r\n if (!done) { done = true; proxyClient.end(); resolve({ stdout: '', stderr: 'SSH proxy command timeout', exitCode: -1 }); }\r\n }, timeout);\r\n\r\n const cleanup = () => { clearTimeout(timer); proxyClient.end(); };\r\n\r\n proxyClient.on('ready', () => {\r\n proxyClient.forwardOut('127.0.0.1', 0, targetOpts.hostname, targetOpts.port, (err, tunnel) => {\r\n if (err) {\r\n if (!done) { done = true; cleanup(); resolve({ stdout: '', stderr: err.message, exitCode: -1 }); }\r\n return;\r\n }\r\n\r\n const targetClient = new SshClient();\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n targetClient.on('ready', () => {\r\n const execOpts = options?.pty ? { pty: true } : {};\r\n targetClient.exec(command, execOpts, (execErr, stream) => {\r\n if (execErr) {\r\n if (!done) { done = true; targetClient.end(); cleanup(); resolve({ stdout, stderr, exitCode: -1 }); }\r\n return;\r\n }\r\n stream.on('data', (d: Buffer) => { stdout += d.toString(); });\r\n stream.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\r\n stream.on('close', (code: number | null) => {\r\n if (!done) { done = true; targetClient.end(); cleanup(); resolve({ stdout, stderr, exitCode: code ?? 0 }); }\r\n });\r\n if (options?.stdin !== undefined) {\r\n stream.end(options.stdin);\r\n }\r\n });\r\n });\r\n\r\n targetClient.on('error', (targetErr) => {\r\n if (!done) { done = true; targetClient.end(); cleanup(); resolve({ stdout, stderr: targetErr.message, exitCode: -1 }); }\r\n });\r\n\r\n targetClient.connect({\r\n sock: tunnel,\r\n username: targetOpts.username, password: targetOpts.password,\r\n privateKey: targetOpts.privateKey, passphrase: targetOpts.passphrase,\r\n readyTimeout: timeout,\r\n });\r\n });\r\n });\r\n\r\n proxyClient.on('error', (err) => {\r\n if (!done) { done = true; cleanup(); resolve({ stdout: '', stderr: err.message, exitCode: -1 }); }\r\n });\r\n\r\n proxyClient.connect({\r\n host: proxyOpts.hostname, port: proxyOpts.port, username: proxyOpts.username,\r\n password: proxyOpts.password, privateKey: proxyOpts.privateKey, passphrase: proxyOpts.passphrase,\r\n readyTimeout: proxyOpts.timeout || 30_000,\r\n });\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Shared SSH connection helper (supports proxy tunnelling)\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction connectSshClient(\r\n opts: SshConnectionOptions,\r\n proxy?: SshConnectionOptions,\r\n readyTimeout = 60_000,\r\n extraConnect?: { compress?: boolean | 'force' },\r\n): Promise<{ client: SshClient; cleanup: () => void }> {\r\n const compress = extraConnect?.compress;\r\n if (!proxy) {\r\n return new Promise((resolve, reject) => {\r\n const ssh = new SshClient();\r\n ssh.on('ready', () => resolve({ client: ssh, cleanup: () => ssh.end() }));\r\n ssh.on('error', (e) => reject(e));\r\n ssh.connect({\r\n host: opts.hostname, port: opts.port, username: opts.username,\r\n password: opts.password, privateKey: opts.privateKey, passphrase: opts.passphrase,\r\n readyTimeout,\r\n ...(compress ? { compress } : {}),\r\n });\r\n });\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const proxyClient = new SshClient();\r\n\r\n proxyClient.on('ready', () => {\r\n proxyClient.forwardOut('127.0.0.1', 0, opts.hostname, opts.port, (err, tunnel) => {\r\n if (err) { proxyClient.end(); reject(err); return; }\r\n\r\n const targetClient = new SshClient();\r\n targetClient.on('ready', () =>\r\n resolve({\r\n client: targetClient,\r\n cleanup: () => { targetClient.end(); proxyClient.end(); },\r\n }),\r\n );\r\n targetClient.on('error', (e) => { proxyClient.end(); reject(e); });\r\n targetClient.connect({\r\n sock: tunnel,\r\n username: opts.username, password: opts.password,\r\n privateKey: opts.privateKey, passphrase: opts.passphrase,\r\n readyTimeout,\r\n ...(compress ? { compress } : {}),\r\n });\r\n });\r\n });\r\n\r\n proxyClient.on('error', (e) => reject(e));\r\n proxyClient.connect({\r\n host: proxy.hostname, port: proxy.port, username: proxy.username,\r\n password: proxy.password, privateKey: proxy.privateKey, passphrase: proxy.passphrase,\r\n readyTimeout: proxy.timeout || 30_000,\r\n });\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// R2 (Cloudflare S3-compatible) helpers\r\n//\r\n// The four sftp-* tools route to R2 instead of an SSH server when the caller\r\n// passes `bucket: <name>`. Credentials come from env vars (R2_ENDPOINT +\r\n// R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY), so the MCP runs against any\r\n// Cloudflare R2 account without per-call config. The bucket *name* is part of\r\n// the call so the same MCP can address multiple buckets (backup, assets, etc.).\r\n// ---------------------------------------------------------------------------\r\n\r\nimport {\r\n S3Client,\r\n ListObjectsV2Command,\r\n GetObjectCommand,\r\n PutObjectCommand,\r\n DeleteObjectCommand,\r\n DeleteObjectsCommand,\r\n HeadObjectCommand,\r\n CreateMultipartUploadCommand,\r\n UploadPartCommand,\r\n CompleteMultipartUploadCommand,\r\n AbortMultipartUploadCommand,\r\n type _Object,\r\n type CommonPrefix,\r\n} from '@aws-sdk/client-s3';\r\n\r\nlet _r2Client: S3Client | null = null;\r\n\r\nfunction getR2Client(): S3Client {\r\n if (_r2Client) return _r2Client;\r\n const endpoint = process.env.R2_ENDPOINT;\r\n const accessKeyId = process.env.R2_ACCESS_KEY_ID;\r\n const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;\r\n if (!endpoint || !accessKeyId || !secretAccessKey) {\r\n throw new Error(\r\n 'R2 not configured. Set R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY in the MCP env (mcp.json).',\r\n );\r\n }\r\n _r2Client = new S3Client({ region: 'auto', endpoint, credentials: { accessKeyId, secretAccessKey } });\r\n return _r2Client;\r\n}\r\n\r\n/** Strip a leading `/` so callers can use familiar paths (`/foo/bar.txt`)\r\n * while R2 keys are stored without the slash (`foo/bar.txt`). */\r\nfunction r2Key(path: string): string {\r\n return path.replace(/^\\/+/, '');\r\n}\r\n\r\ninterface R2ListEntry {\r\n key: string;\r\n size: number;\r\n mtime: string;\r\n isPrefix: boolean;\r\n}\r\n\r\nasync function r2List(\r\n bucket: string,\r\n prefix: string,\r\n options: { recursive: boolean; maxResults: number },\r\n): Promise<R2ListEntry[]> {\r\n const client = getR2Client();\r\n const entries: R2ListEntry[] = [];\r\n let continuationToken: string | undefined;\r\n // Folder mode uses delimiter so we get CommonPrefixes (one entry per \"directory\").\r\n // Recursive mode omits delimiter and walks every key.\r\n const delimiter = options.recursive ? undefined : '/';\r\n\r\n do {\r\n const result = await client.send(new ListObjectsV2Command({\r\n Bucket: bucket,\r\n Prefix: prefix || undefined,\r\n Delimiter: delimiter,\r\n ContinuationToken: continuationToken,\r\n MaxKeys: Math.min(1000, options.maxResults - entries.length),\r\n }));\r\n\r\n for (const cp of (result.CommonPrefixes || []) as CommonPrefix[]) {\r\n if (cp.Prefix) entries.push({ key: cp.Prefix, size: 0, mtime: '', isPrefix: true });\r\n if (entries.length >= options.maxResults) break;\r\n }\r\n for (const obj of (result.Contents || []) as _Object[]) {\r\n if (entries.length >= options.maxResults) break;\r\n entries.push({\r\n key: obj.Key || '',\r\n size: obj.Size || 0,\r\n mtime: obj.LastModified ? obj.LastModified.toISOString() : '',\r\n isPrefix: false,\r\n });\r\n }\r\n continuationToken = result.IsTruncated ? result.NextContinuationToken : undefined;\r\n } while (continuationToken && entries.length < options.maxResults);\r\n\r\n return entries;\r\n}\r\n\r\nasync function r2GetObject(bucket: string, key: string, maxBytes: number): Promise<string> {\r\n const client = getR2Client();\r\n // Cheap HEAD first so we can refuse oversized objects without downloading them.\r\n const head = await client.send(new HeadObjectCommand({ Bucket: bucket, Key: key }));\r\n const size = head.ContentLength || 0;\r\n if (size > maxBytes) {\r\n throw new Error(`Object too large: ${size} bytes (max ${maxBytes} for inline read; use sftp-write with sourcePath to mirror locally instead, or pass { offset, length } for a ranged read)`);\r\n }\r\n const result = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));\r\n const body = result.Body as unknown as { transformToString?: () => Promise<string> };\r\n if (!body?.transformToString) throw new Error('R2 returned no readable body');\r\n return body.transformToString();\r\n}\r\n\r\nasync function r2GetObjectRange(\r\n bucket: string,\r\n key: string,\r\n range: { offset: number; length?: number },\r\n): Promise<string> {\r\n const client = getR2Client();\r\n const head = await client.send(new HeadObjectCommand({ Bucket: bucket, Key: key }));\r\n const size = head.ContentLength || 0;\r\n if (range.offset >= size && size > 0) throw new Error(`offset ${range.offset} is past end of object (size ${size})`);\r\n const MAX = 1_048_576;\r\n const remaining = Math.max(0, size - range.offset);\r\n const effectiveLen = range.length !== undefined ? Math.min(range.length, remaining, MAX) : Math.min(remaining, MAX);\r\n const end = range.offset + effectiveLen - 1;\r\n // S3 Range header is inclusive on both ends.\r\n const result = await client.send(new GetObjectCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n Range: `bytes=${range.offset}-${end}`,\r\n }));\r\n const body = result.Body as unknown as { transformToString?: () => Promise<string> };\r\n if (!body?.transformToString) throw new Error('R2 returned no readable body');\r\n const text = await body.transformToString();\r\n const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;\r\n return `${header}\\n${text}`;\r\n}\r\n\r\nasync function r2PutObject(bucket: string, key: string, body: Buffer | Readable, contentLength?: number): Promise<void> {\r\n const client = getR2Client();\r\n await client.send(new PutObjectCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n Body: body,\r\n ContentLength: contentLength,\r\n ContentType: 'application/octet-stream',\r\n }));\r\n}\r\n\r\nasync function r2DeleteObject(bucket: string, key: string): Promise<void> {\r\n const client = getR2Client();\r\n await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));\r\n}\r\n\r\n/** Delete all objects under a prefix. R2's DeleteObjects supports up to 1000\r\n * keys per request, so we loop list→delete in pages. Returns deleted count. */\r\nasync function r2DeletePrefix(bucket: string, prefix: string): Promise<number> {\r\n const client = getR2Client();\r\n let deleted = 0;\r\n let continuationToken: string | undefined;\r\n do {\r\n const list = await client.send(new ListObjectsV2Command({\r\n Bucket: bucket,\r\n Prefix: prefix,\r\n ContinuationToken: continuationToken,\r\n MaxKeys: 1000,\r\n }));\r\n const keys = (list.Contents || []).map(o => o.Key).filter((k): k is string => !!k);\r\n if (keys.length === 0) break;\r\n await client.send(new DeleteObjectsCommand({\r\n Bucket: bucket,\r\n Delete: { Objects: keys.map(k => ({ Key: k })), Quiet: true },\r\n }));\r\n deleted += keys.length;\r\n continuationToken = list.IsTruncated ? list.NextContinuationToken : undefined;\r\n } while (continuationToken);\r\n return deleted;\r\n}\r\n\r\n/** Multipart upload for files larger than ~4.5 GB (R2 single-PUT limit is 5 GB\r\n * with a safety margin). Streams the local file in 100 MB parts. */\r\nconst R2_MULTIPART_THRESHOLD = 4.5 * 1024 * 1024 * 1024; // 4.5 GB\r\nconst R2_MULTIPART_PART_SIZE = 100 * 1024 * 1024; // 100 MB\r\n\r\nasync function r2PutObjectMultipart(\r\n bucket: string,\r\n key: string,\r\n localPath: string,\r\n totalBytes: number,\r\n onProgress?: (bytes: number) => void,\r\n): Promise<void> {\r\n const client = getR2Client();\r\n const create = await client.send(new CreateMultipartUploadCommand({ Bucket: bucket, Key: key }));\r\n const uploadId = create.UploadId;\r\n if (!uploadId) throw new Error('R2 returned no UploadId for multipart create');\r\n\r\n const parts: { PartNumber: number; ETag: string }[] = [];\r\n try {\r\n let partNumber = 1;\r\n let uploaded = 0;\r\n let offset = 0;\r\n while (offset < totalBytes) {\r\n const end = Math.min(offset + R2_MULTIPART_PART_SIZE, totalBytes);\r\n // Read this part into memory (100 MB max). Streaming a single part with\r\n // unknown length is unreliable across SDK versions; buffering keeps us\r\n // simple and predictable.\r\n const chunk = await new Promise<Buffer>((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n const rs = createReadStream(localPath, { start: offset, end: end - 1 });\r\n rs.on('data', (c: string | Buffer) => { chunks.push(typeof c === 'string' ? Buffer.from(c) : c); });\r\n rs.on('end', () => resolve(Buffer.concat(chunks.map(b => new Uint8Array(b)))));\r\n rs.on('error', reject);\r\n });\r\n const partResult = await client.send(new UploadPartCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n UploadId: uploadId,\r\n PartNumber: partNumber,\r\n Body: chunk,\r\n ContentLength: chunk.length,\r\n }));\r\n if (!partResult.ETag) throw new Error(`Part ${partNumber} returned no ETag`);\r\n parts.push({ PartNumber: partNumber, ETag: partResult.ETag });\r\n uploaded += chunk.length;\r\n onProgress?.(uploaded);\r\n offset = end;\r\n partNumber++;\r\n }\r\n await client.send(new CompleteMultipartUploadCommand({\r\n Bucket: bucket,\r\n Key: key,\r\n UploadId: uploadId,\r\n MultipartUpload: { Parts: parts },\r\n }));\r\n } catch (e) {\r\n // Best-effort abort to avoid orphaned parts (R2 charges for them).\r\n try { await client.send(new AbortMultipartUploadCommand({ Bucket: bucket, Key: key, UploadId: uploadId })); } catch { /* ignore */ }\r\n throw e;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SFTP helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction sanitizePath(path: string): string {\r\n let normalized = path.replace(/\\\\/g, '/').replace(/\\0/g, '');\r\n const parts = normalized.split('/');\r\n const resolved: string[] = [];\r\n for (const part of parts) {\r\n if (part === '..') { if (resolved.length > 0 && resolved[resolved.length - 1] !== '') resolved.pop(); }\r\n else if (part !== '.' && part !== '') resolved.push(part);\r\n }\r\n return '/' + resolved.join('/');\r\n}\r\n\r\nconst PROTECTED_PATHS = ['/etc/', '/boot/', '/usr/', '/bin/', '/sbin/', '/lib/', '/lib64/'];\r\n\r\nfunction assertWritablePath(path: string): void {\r\n const safe = sanitizePath(path);\r\n for (const p of PROTECTED_PATHS) {\r\n if (safe === p.slice(0, -1) || safe.startsWith(p)) {\r\n throw new Error(`Write access denied to protected path: ${safe}`);\r\n }\r\n }\r\n}\r\n\r\n/** Convert a glob pattern (`*`, `?`, character classes) to a RegExp anchored\r\n * to the basename only. Used by sftp-list for filtering. */\r\nfunction globToRegExp(pattern: string): RegExp {\r\n let re = '';\r\n for (const c of pattern) {\r\n if (c === '*') re += '.*';\r\n else if (c === '?') re += '.';\r\n else if (/[.+^${}()|[\\]\\\\]/.test(c)) re += '\\\\' + c;\r\n else re += c;\r\n }\r\n return new RegExp(`^${re}$`);\r\n}\r\n\r\ninterface SftpEntry {\r\n kind: 'd' | '-';\r\n size: number;\r\n mtime: string; // ISO; '' if unknown\r\n mtimeMs: number; // 0 if unknown; used for sorting\r\n path: string; // full or basename (depending on recursive mode)\r\n}\r\n\r\nasync function sftpReaddir(\r\n opts: SshConnectionOptions,\r\n dirPath: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { recursive?: boolean; maxDepth?: number; pattern?: string; maxResults?: number },\r\n): Promise<{ entries: SftpEntry[]; truncated: boolean; error?: string }> {\r\n const recursive = options?.recursive === true;\r\n const maxDepth = Math.max(1, Math.min(20, options?.maxDepth ?? 5));\r\n const maxResults = Math.max(1, Math.min(50_000, options?.maxResults ?? 5_000));\r\n const matcher = options?.pattern ? globToRegExp(options.pattern) : null;\r\n const rootSafe = sanitizePath(dirPath);\r\n\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 30_000);\r\n cleanup = c;\r\n return await new Promise<{ entries: SftpEntry[]; truncated: boolean; error?: string }>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve({ entries: [], truncated: false, error: 'timeout' }); cleanup = undefined; }, 60_000);\r\n\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve({ entries: [], truncated: false, error: err.message }); return; }\r\n\r\n const entries: SftpEntry[] = [];\r\n let truncated = false;\r\n const errors: string[] = [];\r\n\r\n const readOne = (path: string, depth: number): Promise<void> =>\r\n new Promise((resolveOne) => {\r\n sftp.readdir(path, (err2, list) => {\r\n if (err2) {\r\n errors.push(`error reading ${path}: ${err2.message}`);\r\n return resolveOne();\r\n }\r\n const subdirs: string[] = [];\r\n for (const item of list) {\r\n if (entries.length >= maxResults) { truncated = true; break; }\r\n const mode = item.attrs.mode || 0;\r\n const isDir = (mode & 0o170000) === 0o040000;\r\n const size = item.attrs.size || 0;\r\n const mtimeMs = item.attrs.mtime ? item.attrs.mtime * 1000 : 0;\r\n const mtime = mtimeMs ? new Date(mtimeMs).toISOString() : '';\r\n const fullPath = path === '/' ? `/${item.filename}` : `${path}/${item.filename}`;\r\n const include = !matcher || matcher.test(item.filename);\r\n if (include) {\r\n entries.push({ kind: isDir ? 'd' : '-', size, mtime, mtimeMs, path: recursive ? fullPath : item.filename });\r\n }\r\n if (isDir && recursive && depth < maxDepth) subdirs.push(fullPath);\r\n }\r\n if (truncated || subdirs.length === 0) return resolveOne();\r\n // Walk subdirs sequentially to keep one SFTP session calm.\r\n (async () => {\r\n for (const sub of subdirs) {\r\n if (truncated) break;\r\n await readOne(sub, depth + 1);\r\n }\r\n resolveOne();\r\n })();\r\n });\r\n });\r\n\r\n readOne(rootSafe, 1).then(() => {\r\n clearTimeout(timer);\r\n cleanup?.(); cleanup = undefined;\r\n resolve({ entries, truncated, error: errors.length ? errors.join('; ') : undefined });\r\n });\r\n });\r\n });\r\n } catch (e: any) {\r\n cleanup?.();\r\n return { entries: [], truncated: false, error: e.message };\r\n }\r\n}\r\n\r\nasync function sftpRead(\r\n opts: SshConnectionOptions,\r\n filePath: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { offset?: number; length?: number },\r\n): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n const offset = Math.max(0, Math.floor(options?.offset ?? 0));\r\n // Cap at 1 MiB regardless of how much the caller asks for; LLM context can't\r\n // sensibly absorb more than that and large reads should use SFTP→local file.\r\n const MAX = 1_048_576;\r\n const requestedLen = options?.length !== undefined ? Math.max(0, Math.floor(options.length)) : undefined;\r\n\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 60_000);\r\n cleanup = c;\r\n return await new Promise<string>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve('Error: timeout'); cleanup = undefined; }, 60_000);\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\r\n sftp.stat(safe, (err2, stats) => {\r\n if (err2) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err2.message}`); return; }\r\n const total = stats.size || 0;\r\n if (offset >= total && total > 0) {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Error: offset ${offset} is past end of file (size ${total})`);\r\n return;\r\n }\r\n const remaining = Math.max(0, total - offset);\r\n // Effective read length = caller-requested OR remaining-from-offset,\r\n // whichever is smaller, but never above MAX. In whole-file mode (no\r\n // offset/length) we still refuse files >MAX so the contract matches.\r\n const effectiveLen = requestedLen !== undefined\r\n ? Math.min(requestedLen, remaining, MAX)\r\n : Math.min(remaining, MAX);\r\n const isWholeFileRequest = options === undefined || (offset === 0 && requestedLen === undefined);\r\n if (isWholeFileRequest && total > MAX) {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Error: file too large (${total} bytes, max ${MAX}). Use { offset, length } for ranged reads.`);\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n // ssh2 createReadStream supports `start` (inclusive) and `end` (inclusive).\r\n const rs = sftp.createReadStream(safe, { start: offset, end: offset + effectiveLen - 1 });\r\n rs.on('data', (ch: Buffer) => chunks.push(ch));\r\n rs.on('end', () => {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n const text = Buffer.concat(chunks.map(ch => new Uint8Array(ch))).toString('utf-8');\r\n // For ranged reads, prepend a one-line header so the LLM knows the\r\n // window. Whole-file reads stay unchanged for backwards compat.\r\n if (!isWholeFileRequest) {\r\n const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;\r\n resolve(`${header}\\n${text}`);\r\n } else {\r\n resolve(text);\r\n }\r\n });\r\n rs.on('error', (e: Error) => { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${e.message}`); });\r\n });\r\n });\r\n });\r\n } catch (e: any) {\r\n cleanup?.();\r\n return `Error: ${e.message}`;\r\n }\r\n}\r\n\r\n// SFTP tuning. ssh2 fastPut uses 64 concurrent in-flight WRITE packets which\r\n// gives near-linerate throughput on modern OpenSSH (>= 8.6). The 64 KiB chunk\r\n// size is the safe upper bound for servers without the limits@openssh.com\r\n// extension; with it most OpenSSH builds happily accept up to 256 KiB.\r\nconst SFTP_FASTPUT_CONCURRENCY = 64;\r\nconst SFTP_FASTPUT_CHUNK_SIZE = 65_536;\r\n// Watchdog: kill the upload if no progress is observed for this long. Reset on\r\n// every fastPut step callback. Tighter than a wall-clock timeout because it\r\n// adapts to file size automatically.\r\nconst SFTP_IDLE_TIMEOUT_MS = 120_000;\r\n// Inline writes have no progress events, so we use a wall-clock cap.\r\nconst SFTP_INLINE_TIMEOUT_MS = 60_000;\r\nconst SFTP_PROGRESS_LOG_BYTES = 50 * 1024 * 1024;\r\n\r\nexport type SftpWriteInput =\r\n | { content: string }\r\n | { sourcePath: string };\r\n\r\nfunction formatBytes(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;\r\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;\r\n}\r\n\r\nasync function sftpWrite(\r\n opts: SshConnectionOptions,\r\n filePath: string,\r\n input: SftpWriteInput,\r\n proxy?: SshConnectionOptions,\r\n meta?: { fileMode?: number; mtimeMs?: number },\r\n): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\r\n\r\n // File permission bits: caller may override (e.g. 0o755 for executable).\r\n // Default 0o644 keeps existing behaviour for plain config writes.\r\n const fileMode = meta?.fileMode !== undefined ? (meta.fileMode & 0o7777) : 0o644;\r\n\r\n // Validate source up-front so the LLM gets a clear error before we open SSH.\r\n let mode: 'content' | 'sourcePath';\r\n let inlineBuffer: Buffer | undefined;\r\n let localPath: string | undefined;\r\n let expectedBytes = 0;\r\n\r\n if ('content' in input && typeof input.content === 'string') {\r\n mode = 'content';\r\n inlineBuffer = Buffer.from(input.content, 'utf-8');\r\n expectedBytes = inlineBuffer.length;\r\n } else if ('sourcePath' in input && typeof input.sourcePath === 'string') {\r\n mode = 'sourcePath';\r\n localPath = input.sourcePath;\r\n if (!isAbsolute(localPath)) return `Error: sourcePath must be an absolute path: ${localPath}`;\r\n if (!existsSync(localPath)) return `Error: sourcePath does not exist: ${localPath}`;\r\n const st = statSync(localPath);\r\n if (!st.isFile()) return `Error: sourcePath is not a regular file: ${localPath}`;\r\n expectedBytes = st.size;\r\n } else {\r\n return 'Error: sftp-write requires exactly one of: content (string) or sourcePath (absolute local path)';\r\n }\r\n\r\n // For inline text we leave SSH compression enabled (cheap, often 5-10x for\r\n // configs/scripts). For sourcePath we disable it: large files are usually\r\n // already-compressed (zip/jpg/mp4/dump.gz) and SSH-level compression then\r\n // wastes CPU and slows the transfer.\r\n const compress = mode === 'content';\r\n const startedAt = Date.now();\r\n let cleanup: (() => void) | undefined;\r\n\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 60_000, { compress });\r\n cleanup = c;\r\n\r\n return await new Promise<string>((resolve) => {\r\n let resolved = false;\r\n let bytesWritten = 0;\r\n\r\n const finish = (msg: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n watchdog?.cancel();\r\n wallTimer && clearTimeout(wallTimer);\r\n cleanup?.();\r\n cleanup = undefined;\r\n resolve(msg);\r\n };\r\n\r\n // For sourcePath: idle watchdog reset on every fastPut step.\r\n // For content: simple wall-clock timeout.\r\n let watchdog: { reset: () => void; cancel: () => void } | undefined;\r\n let wallTimer: NodeJS.Timeout | undefined;\r\n\r\n if (mode === 'sourcePath') {\r\n const armWatchdog = () => {\r\n let timer: NodeJS.Timeout = setTimeout(\r\n () => finish(`Error: idle timeout (no SFTP progress for ${SFTP_IDLE_TIMEOUT_MS / 1000}s, wrote ${formatBytes(bytesWritten)} of ${formatBytes(expectedBytes)})`),\r\n SFTP_IDLE_TIMEOUT_MS,\r\n );\r\n return {\r\n reset: () => { clearTimeout(timer); timer = setTimeout(\r\n () => finish(`Error: idle timeout (no SFTP progress for ${SFTP_IDLE_TIMEOUT_MS / 1000}s, wrote ${formatBytes(bytesWritten)} of ${formatBytes(expectedBytes)})`),\r\n SFTP_IDLE_TIMEOUT_MS,\r\n ); },\r\n cancel: () => clearTimeout(timer),\r\n };\r\n };\r\n watchdog = armWatchdog();\r\n } else {\r\n wallTimer = setTimeout(\r\n () => finish(`Error: timeout after ${SFTP_INLINE_TIMEOUT_MS / 1000}s`),\r\n SFTP_INLINE_TIMEOUT_MS,\r\n );\r\n }\r\n\r\n client.sftp((err, sftp) => {\r\n if (err) return finish(`Error: ${err.message}`);\r\n\r\n // Apply mtime after a successful write. SFTP `setstat` with atime+mtime\r\n // is the standard way; we leave atime equal to mtime (close enough for\r\n // tooling that cares about freshness). Errors are surfaced as a warning\r\n // suffix so the upload itself is still considered successful.\r\n const applyMtime = (then: (suffix: string) => void) => {\r\n if (meta?.mtimeMs === undefined) return then('');\r\n const secs = Math.floor(meta.mtimeMs / 1000);\r\n sftp.setstat(safe, { atime: secs, mtime: secs }, (statErr) => {\r\n then(statErr ? ` (mtime set failed: ${statErr.message})` : ` (mtime=${new Date(meta.mtimeMs!).toISOString()})`);\r\n });\r\n };\r\n\r\n if (mode === 'content') {\r\n const ws = sftp.createWriteStream(safe, { mode: fileMode });\r\n ws.on('error', (e: Error) => finish(`Error: ${e.message}`));\r\n ws.on('close', () => {\r\n const elapsed = Date.now() - startedAt;\r\n applyMtime((suffix) => finish(`Written ${expectedBytes} bytes to ${safe} in ${elapsed}ms (mode=0o${fileMode.toString(8)})${suffix}`));\r\n });\r\n ws.end(inlineBuffer!);\r\n return;\r\n }\r\n\r\n // sourcePath path: ssh2 fastPut does the heavy lifting (parallel\r\n // pipelined SFTP_WRITE packets). Step callback gives us progress for\r\n // the watchdog and periodic logs.\r\n let nextProgressLog = SFTP_PROGRESS_LOG_BYTES;\r\n sftp.fastPut(\r\n localPath!,\r\n safe,\r\n {\r\n concurrency: SFTP_FASTPUT_CONCURRENCY,\r\n chunkSize: SFTP_FASTPUT_CHUNK_SIZE,\r\n mode: fileMode,\r\n fileSize: expectedBytes,\r\n step: (transferred: number) => {\r\n bytesWritten = transferred;\r\n watchdog?.reset();\r\n if (transferred >= nextProgressLog) {\r\n console.error(\r\n `[sftp-write] ${formatBytes(transferred)} / ${formatBytes(expectedBytes)} → ${safe}`,\r\n );\r\n nextProgressLog += SFTP_PROGRESS_LOG_BYTES;\r\n }\r\n },\r\n },\r\n (fpErr) => {\r\n if (fpErr) return finish(`Error: ${fpErr.message}`);\r\n const elapsed = Date.now() - startedAt;\r\n const mbps = expectedBytes / (1024 * 1024) / Math.max(0.001, elapsed / 1000);\r\n applyMtime((suffix) => finish(\r\n `Uploaded ${formatBytes(expectedBytes)} from ${localPath} to ${safe} ` +\r\n `in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s, mode=0o${fileMode.toString(8)})${suffix}`,\r\n ));\r\n },\r\n );\r\n });\r\n });\r\n } catch (e: unknown) {\r\n cleanup?.();\r\n return `Error: ${e instanceof Error ? e.message : String(e)}`;\r\n }\r\n}\r\n\r\nasync function sftpDelete(\r\n opts: SshConnectionOptions,\r\n filePath: string,\r\n proxy?: SshConnectionOptions,\r\n options?: { recursive?: boolean },\r\n): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\r\n const recursive = options?.recursive === true;\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 30_000);\r\n cleanup = c;\r\n return await new Promise<string>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve('Error: timeout'); cleanup = undefined; }, 60_000);\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\r\n\r\n // Recursive directory removal: walk the tree depth-first via SFTP and\r\n // unlink files / rmdir dirs from the bottom up. Pure SFTP — no shell\r\n // shenanigans, so it works on Windows OpenSSH too.\r\n if (recursive) {\r\n const removeTree = async (target: string): Promise<{ files: number; dirs: number }> => {\r\n return new Promise((resolveTree) => {\r\n sftp.stat(target, (statErr, stats) => {\r\n if (statErr) return resolveTree({ files: 0, dirs: 0 });\r\n const mode = stats.mode || 0;\r\n const isDir = (mode & 0o170000) === 0o040000;\r\n if (!isDir) {\r\n sftp.unlink(target, () => resolveTree({ files: 1, dirs: 0 }));\r\n return;\r\n }\r\n sftp.readdir(target, async (rdErr, list) => {\r\n if (rdErr) return resolveTree({ files: 0, dirs: 0 });\r\n let files = 0; let dirs = 0;\r\n for (const item of list) {\r\n const child = target === '/' ? `/${item.filename}` : `${target}/${item.filename}`;\r\n const r = await removeTree(child);\r\n files += r.files; dirs += r.dirs;\r\n }\r\n sftp.rmdir(target, () => resolveTree({ files, dirs: dirs + 1 }));\r\n });\r\n });\r\n });\r\n };\r\n removeTree(safe).then(({ files, dirs }) => {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Removed ${safe} recursively (${files} files, ${dirs} directories)`);\r\n });\r\n return;\r\n }\r\n\r\n sftp.unlink(safe, (unlinkErr) => {\r\n if (unlinkErr) {\r\n sftp.rmdir(safe, (rmdirErr) => {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(rmdirErr ? `Error: ${unlinkErr.message}` : `Deleted directory ${safe}`);\r\n });\r\n } else {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Deleted file ${safe}`);\r\n }\r\n });\r\n });\r\n });\r\n } catch (e: any) {\r\n cleanup?.();\r\n return `Error: ${e.message}`;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Safety: dangerous command blocklist\r\n// ---------------------------------------------------------------------------\r\n\r\nconst BLOCKED_COMMANDS = [\r\n 'rm -rf /', 'rm -fr /', 'mkfs', 'dd if=', ':(){ :|:& };:',\r\n 'shutdown', 'halt', 'init 0', 'init 6',\r\n '> /dev/sda', 'mv /* /dev/null', 'chmod -R 000 /',\r\n];\r\n\r\nfunction assertSafeCommand(command: string): void {\r\n const lower = command.toLowerCase().trim();\r\n for (const blocked of BLOCKED_COMMANDS) {\r\n if (lower.includes(blocked)) {\r\n throw new Error(`Blocked dangerous command pattern: \"${blocked}\"`);\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// MySQL / Database helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface DbCredentials {\r\n host: string;\r\n user: string;\r\n password: string;\r\n database: string;\r\n port: number;\r\n sitePath: string;\r\n appType: string;\r\n}\r\n\r\n/**\r\n * Discovers web applications under /var/www and extracts DB credentials\r\n * from their config files (WordPress, PrestaShop, Laravel, custom .env).\r\n */\r\nasync function discoverSiteDatabases(conn: SshConnectionOptions, proxy?: SshConnectionOptions): Promise<DbCredentials[]> {\r\n const script = `\r\ncheck_dir() {\r\n local base=\"$1\" root=\"$2\"\r\n # WordPress\r\n if [ -f \"$root/wp-config.php\" ]; then\r\n echo \"WP|$base|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_NAME'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_USER'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_PASSWORD'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_HOST'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\"\r\n return\r\n fi\r\n # PrestaShop 1.7+\r\n if [ -f \"$root/app/config/parameters.php\" ]; then\r\n echo \"PS|$base|$(grep -oP \"'database_name'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_user'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_password'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_host'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\"\r\n return\r\n fi\r\n # PrestaShop 1.6\r\n if [ -f \"$root/config/settings.inc.php\" ]; then\r\n echo \"PS|$base|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_NAME_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_USER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_PASSWD_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_SERVER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\"\r\n return\r\n fi\r\n # Laravel / generic .env\r\n if [ -f \"$root/.env\" ]; then\r\n DB_CONN=$(grep -oP '^DB_CONNECTION=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n if [ -n \"$DB_CONN\" ] && [ \"$DB_CONN\" != \"sqlite\" ]; then\r\n echo \"ENV|$base|$(grep -oP '^DB_DATABASE=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_USERNAME=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_PASSWORD=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_HOST=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_PORT=\\\\K.*' \"$root/.env\" 2>/dev/null)\"\r\n return\r\n fi\r\n fi\r\n}\r\nfor dir in /var/www/*/; do\r\n [ -d \"$dir\" ] || continue\r\n check_dir \"$dir\" \"$dir\"\r\n # Also check common subdirectories: html, public_html, public, httpdocs\r\n for sub in html public_html public httpdocs; do\r\n [ -d \"$dir$sub\" ] && check_dir \"$dir\" \"$dir$sub\"\r\n done\r\ndone\r\n`.trim();\r\n\r\n const result = await sshExec(conn, script, proxy);\r\n const sites: DbCredentials[] = [];\r\n\r\n for (const line of result.stdout.split('\\n')) {\r\n if (!line.trim()) continue;\r\n const parts = line.split('|');\r\n if (parts.length < 6) continue;\r\n\r\n const [type, sitePath, database, user, password, host, port] = parts;\r\n if (!database || !user || !type || !sitePath) continue;\r\n\r\n const appTypes: Record<string, string> = { WP: 'WordPress', PS: 'PrestaShop', ENV: 'Laravel/.env' };\r\n\r\n sites.push({\r\n appType: appTypes[type] || type,\r\n sitePath: sitePath.replace(/\\/$/, ''),\r\n database,\r\n user,\r\n password: password || '',\r\n host: host || 'localhost',\r\n port: parseInt(port || '3306', 10),\r\n });\r\n }\r\n\r\n return sites;\r\n}\r\n\r\nfunction escapeMysqlShell(value: string): string {\r\n return value.replace(/'/g, \"'\\\\''\");\r\n}\r\n\r\nconst BLOCKED_SQL_PATTERNS = [\r\n /\\bDROP\\s+DATABASE\\b/i,\r\n /\\bDROP\\s+TABLE\\b/i,\r\n /\\bDROP\\s+INDEX\\b/i,\r\n /\\bTRUNCATE\\b/i,\r\n /\\bALTER\\s+TABLE\\s+\\w+\\s+DROP\\b/i,\r\n /\\bDELETE\\s+FROM\\s+\\w+\\s*$/i,\r\n];\r\n\r\nfunction assertSafeSql(query: string): void {\r\n const trimmed = query.trim();\r\n for (const pattern of BLOCKED_SQL_PATTERNS) {\r\n if (pattern.test(trimmed)) {\r\n throw new Error(`Blocked destructive SQL pattern: ${pattern.source}`);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Builds a shell snippet that discovers DB credentials for a site path\r\n * and then executes a MySQL query, all in a single SSH session.\r\n */\r\nfunction buildSiteMysqlCommand(sitePath: string, query: string): string {\r\n const safePath = escapeMysqlShell(sitePath.replace(/\\/$/, ''));\r\n const safeQuery = escapeMysqlShell(query);\r\n\r\n return `\r\nSITE='${safePath}'\r\nDB_USER=\"\" DB_PASS=\"\" DB_NAME=\"\" DB_HOST=\"localhost\" DB_PORT=\"3306\"\r\nfor root in \"$SITE\" \"$SITE/html\" \"$SITE/public_html\" \"$SITE/public\" \"$SITE/httpdocs\"; do\r\n [ -d \"$root\" ] || continue\r\n if [ -f \"$root/wp-config.php\" ]; then\r\n DB_NAME=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_NAME'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n DB_USER=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_USER'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n DB_PASS=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_PASSWORD'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n DB_HOST=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_HOST'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\r\n break\r\n elif [ -f \"$root/app/config/parameters.php\" ]; then\r\n DB_NAME=$(grep -oP \"'database_name'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n DB_USER=$(grep -oP \"'database_user'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n DB_PASS=$(grep -oP \"'database_password'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n DB_HOST=$(grep -oP \"'database_host'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\r\n break\r\n elif [ -f \"$root/config/settings.inc.php\" ]; then\r\n DB_NAME=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_NAME_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n DB_USER=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_USER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n DB_PASS=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_PASSWD_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n DB_HOST=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_SERVER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\r\n break\r\n elif [ -f \"$root/.env\" ]; then\r\n DB_CONN=$(grep -oP '^DB_CONNECTION=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n if [ -n \"$DB_CONN\" ] && [ \"$DB_CONN\" != \"sqlite\" ]; then\r\n DB_NAME=$(grep -oP '^DB_DATABASE=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_USER=$(grep -oP '^DB_USERNAME=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_PASS=$(grep -oP '^DB_PASSWORD=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_HOST=$(grep -oP '^DB_HOST=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n DB_PORT=$(grep -oP '^DB_PORT=\\\\K.*' \"$root/.env\" 2>/dev/null)\r\n break\r\n fi\r\n fi\r\ndone\r\n[ -z \"$DB_NAME\" ] || [ -z \"$DB_USER\" ] && echo \"ERROR: No database config found at $SITE\" && exit 1\r\nDB_HOST=\\${DB_HOST:-localhost}\r\nDB_PORT=\\${DB_PORT:-3306}\r\nmysql --user=\"$DB_USER\" --password=\"$DB_PASS\" --host=\"$DB_HOST\" --port=\"$DB_PORT\" -t -e '${safeQuery}' \"$DB_NAME\" 2>&1 | grep -v \"\\\\[Warning\\\\].*password\"\r\n`.trim();\r\n}\r\n\r\n/**\r\n * Execute a MySQL query for a site in a single SSH session.\r\n * Discovers credentials and runs the query in one command.\r\n */\r\nasync function execSiteMysql(conn: SshConnectionOptions, sitePath: string, query: string, proxy?: SshConnectionOptions): Promise<string> {\r\n const cmd = buildSiteMysqlCommand(sitePath, query);\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = (result.stdout || '').trim();\r\n if (output.startsWith('ERROR: No database config found')) {\r\n throw new Error(output);\r\n }\r\n if (result.exitCode !== 0 && !output) {\r\n throw new Error(result.stderr || 'MySQL command failed');\r\n }\r\n return output;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// mijn.host API helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst MIJNHOST_BASE_URL = 'https://mijn.host/api/v2';\r\n\r\ninterface MijnHostApiResponse<T = unknown> {\r\n status: number;\r\n status_description: string;\r\n data: T;\r\n}\r\n\r\nfunction requireMijnhostApiKey(): string {\r\n if (!mijnhostApiKey) {\r\n throw new Error('mijn.host API key not configured. Use --mijnhost-api-key=xxx or set MIJNHOST_API_KEY');\r\n }\r\n return mijnhostApiKey;\r\n}\r\n\r\nasync function mijnhostFetch<T>(path: string, options: RequestInit = {}): Promise<MijnHostApiResponse<T>> {\r\n const key = requireMijnhostApiKey();\r\n\r\n const res = await fetch(`${MIJNHOST_BASE_URL}${path}`, {\r\n ...options,\r\n headers: {\r\n 'API-Key': key,\r\n 'Accept': 'application/json',\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': 'mg-dashboard-mcp/2.2.0',\r\n ...((options.headers as Record<string, string>) || {}),\r\n },\r\n });\r\n\r\n const json: unknown = await res.json();\r\n const body = json as MijnHostApiResponse<T>;\r\n\r\n if (!res.ok) {\r\n throw new Error(body?.status_description || `mijn.host API error: ${res.status}`);\r\n }\r\n\r\n return body;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\nconst TOOLS = [\r\n {\r\n name: 'list-servers',\r\n description:\r\n 'List all SSH servers you have access to. Returns id, name, hostname, tags, and os_type per server. ' +\r\n 'Pass `includeStats: true` to also probe each server in parallel for container count, disk-free, and uptime ' +\r\n '(skips unreachable hosts gracefully).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n includeStats: { type: 'boolean', description: 'When true, probe each server (in parallel, with timeout) for container count, disk-free, and uptime.' },\r\n statsParallelism: { type: 'number', description: 'Max parallel probes when includeStats is true (default 8, cap 20).' },\r\n statsTimeoutMs: { type: 'number', description: 'Per-server probe timeout in ms when includeStats is true (default 6000, range 1000-30000).' },\r\n },\r\n },\r\n },\r\n {\r\n name: 'ssh-execute',\r\n description:\r\n 'Execute a command on a remote server via SSH. OS-aware: bash on linux, `powershell -EncodedCommand` (UTF-16LE base64) on windows, so $, #, quotes, spaces inside `args` are never re-interpreted by a shell. Some dangerous commands are blocked. Use `list-servers` first to see each server\\'s os_type.\\n' +\r\n 'Two ways to invoke (use `args` for anything with passwords or special chars):\\n' +\r\n '- Quick: `command` only, e.g. `command: \"df -h\"`.\\n' +\r\n '- Safe: `command` + `args[]`, e.g. `command: \"mysql\"`, `args: [\"-u\",\"root\",\"-p$tr@nge#pwd\",\"-e\",\"SELECT 1\"]`.\\n' +\r\n '`stdin` pipes data into the remote process (queries, scripts, secrets) without putting it on the command line.\\n' +\r\n '`cwd` sets the working directory (auto `cd` on Linux / `Set-Location` on Windows).\\n' +\r\n 'Fan-out: pass `serverIds: [id1, id2, ...]` (instead of `serverId`) to run the same command across multiple servers in parallel. Each server\\'s output is grouped under its own `=== name (os, exit N) ===` header.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of one SSH server. Mutually exclusive with serverIds.' },\r\n serverIds: { type: 'array', items: { type: 'string' }, description: 'Fan-out: list of server UUIDs to run the command on in parallel. Mutually exclusive with serverId.' },\r\n command: { type: 'string', description: 'Program/command to run (e.g. \"mysql\", \"Get-Service\", \"df\"). Required.' },\r\n args: { type: 'array', items: { type: 'string' }, description: 'Optional argv list. When provided, each entry is safely quoted/encoded for the target OS.' },\r\n stdin: { type: 'string', description: 'Optional data piped to the remote process stdin.' },\r\n cwd: { type: 'string', description: 'Working directory on the remote (cd <cwd> on Linux, Set-Location on Windows).' },\r\n shell: { type: 'string', enum: ['auto', 'bash', 'powershell'], description: 'Override shell selection (default \"auto\" uses the server\\'s os_type).' },\r\n parallelism: { type: 'number', description: 'Max concurrent SSH sessions when using serverIds[] (default 5, max 20).' },\r\n timeout: { type: 'number', description: 'Per-server timeout in milliseconds (default: 60000)' },\r\n },\r\n required: ['command'],\r\n },\r\n },\r\n {\r\n name: 'sftp-list',\r\n description:\r\n 'List files in remote storage. Two backends (provide exactly one of `serverId` or `bucket`):\\n' +\r\n '- `serverId`: list a directory on an SSH server via SFTP. Supports recursive traversal, depth cap, and glob filtering (no need for `ssh-execute \"find ...\"`).\\n' +\r\n '- `bucket`: list objects in a Cloudflare R2 bucket. `path` becomes the key prefix. Default folder mode groups by `/` delimiter; pass `recursive: true` for a flat listing of all keys under the prefix. Requires R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY env vars on the MCP.\\n\\n' +\r\n 'Sorting/summary applies to both backends: `sortBy` (name|size|mtime) + `reverse`. `summary: true` returns just totals (file count, dir count, total bytes) — useful as a cheap pre-flight before pulling a full listing.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'Directory path (SSH) or key prefix (R2). Default: /' },\r\n recursive: { type: 'boolean', description: 'Walk into subdirectories / list all keys flat (default false)' },\r\n maxDepth: { type: 'number', description: 'Maximum recursion depth for SSH mode (1-20, default 5). Ignored for R2.' },\r\n pattern: { type: 'string', description: 'Glob pattern to filter basenames (e.g. \"*.conf\", \"wp-*.php\").' },\r\n maxResults: { type: 'number', description: 'Cap total entries returned (default 5000, max 50000)' },\r\n sortBy: { type: 'string', enum: ['name', 'size', 'mtime'], description: 'Sort order (default `name`). Directories always come first within each ordering.' },\r\n reverse: { type: 'boolean', description: 'Reverse sort direction (e.g. largest-first or newest-first).' },\r\n summary: { type: 'boolean', description: 'Return only totals (file count, directory count, total bytes) instead of the full listing.' },\r\n },\r\n },\r\n },\r\n {\r\n name: 'sftp-read',\r\n description:\r\n 'Read a text file from remote storage (max 1 MiB). Two backends (provide exactly one of `serverId` or `bucket`):\\n' +\r\n '- `serverId`: read from an SSH server via SFTP.\\n' +\r\n '- `bucket`: read an object from a Cloudflare R2 bucket. `path` is the object key.\\n\\n' +\r\n 'Use `offset` and/or `length` for ranged reads — perfect for sampling a slice of a multi-MB log/dump without exceeding the 1 MiB inline limit. Ranged reads include a `# range: bytes A-B of TOTAL` header so you know what window you got.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'File path (SSH) or object key (R2)' },\r\n offset: { type: 'number', description: 'Byte offset to start reading from (0-indexed). Triggers ranged read mode.' },\r\n length: { type: 'number', description: 'Number of bytes to read (capped at 1 MiB). Defaults to remaining-from-offset when omitted.' },\r\n },\r\n required: ['path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-write',\r\n description:\r\n 'Write a file to remote storage. Two backends (provide exactly one of `serverId` or `bucket`) and two source modes (provide exactly one of `content` or `sourcePath`):\\n\\n' +\r\n 'Backends:\\n' +\r\n '- `serverId`: SSH server via SFTP. Protected system paths blocked. Optional `mode` sets POSIX permission bits (e.g. 0o755 for executables) and `mtime` sets the modification time.\\n' +\r\n '- `bucket`: Cloudflare R2 bucket (S3-compatible). Single PUT for files <4.5 GB, automatic multipart upload (100 MB parts) for larger files up to ~5 TB. `mode`/`mtime` are ignored on R2.\\n\\n' +\r\n 'Sources:\\n' +\r\n '- `content` (string): inline UTF-8 text. Practical max ~1 MB.\\n' +\r\n '- `sourcePath` (absolute local path): streams the local file. SSH uses ssh2 fastPut (64 parallel pipelined writes); R2 uses streamed PUT or multipart depending on size. Both handle GB-scale files. Only usable when the MCP runs locally.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'Remote file path (SSH) or object key (R2)' },\r\n content: { type: 'string', description: 'Inline UTF-8 file content (mutually exclusive with sourcePath)' },\r\n sourcePath: { type: 'string', description: 'Absolute local file path to upload (mutually exclusive with content). Use for files >1 MB or any binary.' },\r\n mode: { oneOf: [{ type: 'number' }, { type: 'string' }], description: 'POSIX file permission bits (SSH only). Number (0o755 / 493) or octal string (\"755\" / \"0o755\"). Default 0o644.' },\r\n mtime: { oneOf: [{ type: 'number' }, { type: 'string' }], description: 'File modification time (SSH only). ms-since-epoch number or ISO-8601 date string.' },\r\n },\r\n required: ['path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-delete',\r\n description:\r\n 'Delete a file (or directory tree) from remote storage. Two backends (provide exactly one of `serverId` or `bucket`):\\n' +\r\n '- `serverId`: delete a file or empty directory on an SSH server via SFTP. Protected system paths blocked. With `recursive: true` walks the tree depth-first via SFTP and removes files + empty dirs from the bottom up (works on Windows OpenSSH too — no shell tricks).\\n' +\r\n '- `bucket`: delete an object from a Cloudflare R2 bucket. `path` is the object key. With `recursive: true`, treats `path` as a key prefix and batch-deletes every object beneath it (R2 caps at 1000 keys per call; we loop pages automatically).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server (mutually exclusive with bucket)' },\r\n bucket: { type: 'string', description: 'Cloudflare R2 bucket name (mutually exclusive with serverId)' },\r\n path: { type: 'string', description: 'File path / object key (or directory / key prefix when recursive)' },\r\n recursive: { type: 'boolean', description: 'Recursively remove a directory tree (SSH) or all objects under a key prefix (R2).' },\r\n },\r\n required: ['path'],\r\n },\r\n },\r\n {\r\n name: 'docker-list',\r\n description:\r\n 'List Docker containers on a remote server. Sorted by compose project then name, with a HEALTH column (healthy / unhealthy / starting / no-check). Filter by `nameFilter` (string OR array of substring/glob entries — passes if ANY entry matches), restrict to compose containers with `composeOnly`, or group output per project with `groupByProject`.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n format: { type: 'string', enum: ['table', 'json'], description: 'Output format: human table (default) or NDJSON (one JSON object per line, includes labels).' },\r\n composeOnly: { type: 'boolean', description: 'Only show containers that have a docker-compose project label.' },\r\n nameFilter: { oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }], description: 'Filter by container name. Single entry or array; each entry is glob (* or ?) or substring. A row passes when ANY entry matches.' },\r\n groupByProject: { type: 'boolean', description: 'Group output per compose project with a `=== project (count) ===` header.' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'docker-logs',\r\n description:\r\n 'Get logs from one or more Docker containers. `containerName` accepts a string OR an array — multi-container output is line-prefixed with `[name]` so you can read related services together (e.g. `[\"refront-rest-1\", \"refront-kong-1\", \"refront-db-1\"]`). Supports time-window (`since`), server-side `grep`, line-count (`tail`), and real-time follow (`followSeconds`). Always merges stderr into stdout.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n containerName: { oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }], description: 'Single container name/ID or an array for multi-container tail. Multi mode prefixes each line with [name].' },\r\n tail: { type: 'number', description: 'Number of recent log lines per container (default 100). Alias: `lines`.' },\r\n lines: { type: 'number', description: 'Deprecated alias for `tail`. Prefer `tail`.' },\r\n since: { type: 'string', description: 'Time window, e.g. \"10m\", \"2h\", \"24h\", or an absolute \"2026-05-09T10:00:00\".' },\r\n grep: { type: 'string', description: 'Case-insensitive regex/literal filter applied server-side (saves tokens for noisy containers).' },\r\n followSeconds: { type: 'number', description: 'When >0, stream new log lines for N seconds via `docker logs -f`, then exit (max 300). Multi-container follow runs all streams in parallel.' },\r\n },\r\n required: ['serverId', 'containerName'],\r\n },\r\n },\r\n {\r\n name: 'docker-exec',\r\n description:\r\n 'Run a command inside a running Docker container. `args[]` are quoted safely (no shell-escape hell with $ or quotes). Optional `stdin` pipes data into the container process (for SQL, scripts, etc.). Pass `interactive: true` to allocate a TTY (`docker exec -it`) so commands like `psql`/`mysql`/`bash` produce human-friendly output. Use this instead of `ssh-execute \"docker exec ...\"`.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n container: { type: 'string', description: 'Container name or ID' },\r\n command: { type: 'string', description: 'Program to run inside the container (e.g. \"psql\", \"wp\", \"node\").' },\r\n args: { type: 'array', items: { type: 'string' }, description: 'Argument list, each safely quoted.' },\r\n stdin: { type: 'string', description: 'Optional data piped to the container process stdin.' },\r\n interactive: { type: 'boolean', description: 'Allocate a TTY (`docker exec -it`). Useful for tools that probe isatty(stdout) — collapses stderr into stdout when enabled.' },\r\n workdir: { type: 'string', description: 'Working directory inside the container (-w).' },\r\n user: { type: 'string', description: 'User to run as inside the container (-u).' },\r\n timeout: { type: 'number', description: 'Timeout in milliseconds (default: 60000)' },\r\n },\r\n required: ['serverId', 'container', 'command'],\r\n },\r\n },\r\n {\r\n name: 'docker-compose',\r\n description:\r\n 'Run a docker-compose action against a project on a remote server. Replaces the common `ssh-execute \"cd /opt/x && docker compose ...\"` pattern. Action enum keeps the surface tiny.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n projectPath: { type: 'string', description: 'Absolute path to the directory containing docker-compose.yml.' },\r\n action: { type: 'string', enum: ['up', 'down', 'restart', 'logs', 'ps', 'pull', 'build'], description: 'Compose action.' },\r\n service: { type: 'string', description: 'Optional service name to scope the action to (e.g. \"studio\"). Omit to act on the whole project.' },\r\n tail: { type: 'number', description: 'For `logs`: number of lines (default 200).' },\r\n timeout: { type: 'number', description: 'Timeout in milliseconds (default: 120000 — compose ops can be slow).' },\r\n },\r\n required: ['serverId', 'projectPath', 'action'],\r\n },\r\n },\r\n {\r\n name: 'db-discover',\r\n description: 'Scan /var/www on a server for web applications (WordPress, PrestaShop, Laravel, .env) and list their database credentials. Use this first to find available sites before running other db-* tools.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'db-tables',\r\n description: 'List all tables in a site database with row counts and sizes. Credentials are auto-discovered from the site config files (wp-config.php, parameters.php, .env).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n sitePath: { type: 'string', description: 'Site root path (e.g. /var/www/example.com)' },\r\n },\r\n required: ['serverId', 'sitePath'],\r\n },\r\n },\r\n {\r\n name: 'db-describe',\r\n description: 'Show the structure of a database table (columns, types, keys, defaults). Credentials are auto-discovered from site config files.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n sitePath: { type: 'string', description: 'Site root path (e.g. /var/www/example.com)' },\r\n table: { type: 'string', description: 'Table name' },\r\n },\r\n required: ['serverId', 'sitePath', 'table'],\r\n },\r\n },\r\n {\r\n name: 'db-query',\r\n description: 'Execute a SQL query on a site database. Credentials are auto-discovered from site config files. Destructive operations (DROP, TRUNCATE) are blocked.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n sitePath: { type: 'string', description: 'Site root path (e.g. /var/www/example.com)' },\r\n query: { type: 'string', description: 'SQL query to execute' },\r\n },\r\n required: ['serverId', 'sitePath', 'query'],\r\n },\r\n },\r\n {\r\n name: 'env-list',\r\n description: 'List all stored environment configurations with their release profile names.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n releaseProfile: { type: 'string', description: 'Release profile name to filter by (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Omit to list all.' },\r\n },\r\n },\r\n },\r\n {\r\n name: 'env-get',\r\n description: 'Retrieve the decrypted .env content for a specific app and environment.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n appName: { type: 'string', description: 'Application name (e.g. backoffice, api, web)' },\r\n environment: { type: 'string', enum: ['production', 'staging', 'development', 'local'], description: 'Environment name' },\r\n releaseProfile: { type: 'string', description: 'Release profile name (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Required when multiple profiles exist. Use env-list to discover available profiles.' },\r\n },\r\n required: ['appName', 'environment'],\r\n },\r\n },\r\n {\r\n name: 'env-store',\r\n description: 'Store or update an encrypted .env configuration for an app and environment.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n appName: { type: 'string', description: 'Application name (e.g. backoffice, api, web)' },\r\n environment: { type: 'string', enum: ['production', 'staging', 'development', 'local'], description: 'Environment name' },\r\n content: { type: 'string', description: 'The .env file content to store' },\r\n description: { type: 'string', description: 'Optional description' },\r\n releaseProfile: { type: 'string', description: 'Release profile name (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Required when multiple profiles exist. Use env-list to discover available profiles.' },\r\n },\r\n required: ['appName', 'environment', 'content'],\r\n },\r\n },\r\n {\r\n name: 'cache-purge',\r\n description: 'Purge ALL caches on a server in one operation: OPcache (kills lsphp), LiteSpeed cache, WordPress object cache (wp-cli or file-based), PrestaShop Smarty/app cache, Redis FLUSHALL, and Memcached flush. Returns a per-cache status report.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n serverId: { type: 'string', description: 'UUID of the SSH server' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n // ----- Domains (mijn.host) -----\r\n {\r\n name: 'domain-list',\r\n description: 'List all domains from the mijn.host account. Returns domain name, status, renewal date, and tags. Requires MIJNHOST_API_KEY.',\r\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\r\n },\r\n {\r\n name: 'dns-list',\r\n description: 'List all DNS records for a domain. Returns type (A, AAAA, CNAME, MX, TXT, etc.), name, value, and TTL for each record.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n },\r\n required: ['domain'],\r\n },\r\n },\r\n {\r\n name: 'dns-create',\r\n description: 'Add a new DNS record to a domain. Uses PATCH to add without replacing existing records.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n type: { type: 'string', description: 'Record type: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, or TLSA' },\r\n name: { type: 'string', description: 'Record name (e.g. @ or subdomain)' },\r\n value: { type: 'string', description: 'Record value (e.g. IP address, hostname)' },\r\n ttl: { type: 'number', description: 'TTL in seconds (min 60, default 3600)' },\r\n },\r\n required: ['domain', 'type', 'name', 'value'],\r\n },\r\n },\r\n {\r\n name: 'dns-update',\r\n description: 'Update an existing DNS record. Identifies the record by type+name+oldValue, then replaces it with new values via PATCH.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n type: { type: 'string', description: 'Record type: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, or TLSA' },\r\n name: { type: 'string', description: 'Record name' },\r\n oldValue: { type: 'string', description: 'Current value of the record to update' },\r\n newValue: { type: 'string', description: 'New value for the record' },\r\n ttl: { type: 'number', description: 'New TTL in seconds (min 60)' },\r\n },\r\n required: ['domain', 'type', 'name', 'oldValue', 'newValue'],\r\n },\r\n },\r\n {\r\n name: 'dns-delete',\r\n description: 'Delete a DNS record by type, name, and value. Fetches all records, removes the matching one, then replaces the full set.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n domain: { type: 'string', description: 'Domain name (e.g. example.com)' },\r\n type: { type: 'string', description: 'Record type to delete' },\r\n name: { type: 'string', description: 'Record name to delete' },\r\n value: { type: 'string', description: 'Record value to delete (must match exactly)' },\r\n },\r\n required: ['domain', 'type', 'name', 'value'],\r\n },\r\n },\r\n // ----- Trigger.dev -----\r\n ...TRIGGER_TOOLS,\r\n // ----- Agent Reporting -----\r\n ...AGENT_TOOLS,\r\n];\r\n\r\n// ---------------------------------------------------------------------------\r\n// MCP Server\r\n// ---------------------------------------------------------------------------\r\n\r\nconst MCP_VERSION = '3.7.0';\r\n\r\nasync function handleListTools() {\r\n if (!authContext) return { tools: TOOLS };\r\n\r\n const accessible = TOOLS.filter((tool) => {\r\n const requiredModule = TOOL_MODULE_MAP[tool.name];\r\n if (!requiredModule) return true;\r\n return authContext!.permissions.modules[requiredModule] === true;\r\n });\r\n\r\n return { tools: accessible };\r\n}\r\n\r\nasync function handleCallTool(request: { params: { name: string; arguments?: Record<string, unknown> } }) {\r\n if (!authContext) {\r\n return { content: [{ type: 'text', text: 'Error: not authenticated' }] };\r\n }\r\n\r\n const { name, arguments: toolArgs } = request.params;\r\n const a = (toolArgs || {}) as Record<string, unknown>;\r\n\r\n // Module-level permission check\r\n const requiredModule = TOOL_MODULE_MAP[name];\r\n if (requiredModule && authContext.permissions.modules[requiredModule] !== true) {\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Access denied: you do not have permission for the \"${requiredModule}\" module (tool: ${name})`,\r\n }],\r\n };\r\n }\r\n\r\n const startTime = Date.now();\r\n const serverId = (a.serverId || a.server_id) as string | undefined;\r\n\r\n const result = await executeToolCall(name, a, serverId);\r\n const durationMs = Date.now() - startTime;\r\n const isError = result.content?.[0]?.text?.startsWith('Error:');\r\n void writeAuditLog({\r\n toolName: name,\r\n arguments: a,\r\n serverId,\r\n resultStatus: isError ? 'error' : 'success',\r\n errorMessage: isError ? result.content?.[0]?.text : undefined,\r\n durationMs,\r\n });\r\n return result;\r\n}\r\n\r\nasync function executeToolCall(\r\n name: string,\r\n a: Record<string, unknown>,\r\n _serverId: string | undefined,\r\n): Promise<{ content: { type: string; text: string }[] }> {\r\n const ctx = authContext!;\r\n\r\n try {\r\n switch (name) {\r\n // ----- Servers -----\r\n case 'list-servers': {\r\n let query = supabase\r\n .from('ssh_server')\r\n .select('id, name, hostname, port, username, tags, hosted_by, os_type, created_at')\r\n .order('name');\r\n\r\n if (ctx.allowedServerIds !== null) {\r\n query = query.in('id', ctx.allowedServerIds);\r\n }\r\n\r\n const { data, error } = await query;\r\n if (error) throw new Error(error.message);\r\n\r\n const includeStats = a.includeStats === true;\r\n const servers = data || [];\r\n\r\n // Stats are opt-in because they require an SSH round-trip per server.\r\n // We probe in parallel with a short per-server timeout so a single\r\n // unreachable host can't stall the listing.\r\n type Stats = { containers?: number; diskFreeHuman?: string; uptimeHuman?: string; reachable: boolean; error?: string };\r\n let statsByServer: Map<string, Stats> = new Map();\r\n if (includeStats && servers.length > 0) {\r\n const parallelism = Math.max(1, Math.min(20, Number(a.statsParallelism) || 8));\r\n const probeTimeoutMs = Math.max(1000, Math.min(30_000, Number(a.statsTimeoutMs) || 6000));\r\n\r\n // Combined one-shot probe per server. Three pipe-delimited values:\r\n // <containerCount>|<diskFreeHuman>|<uptimeHuman>\r\n // Missing tools are tolerated (returns 0/N/A).\r\n const linuxProbe =\r\n \"echo \\\"$(docker ps -q 2>/dev/null | wc -l)|$(df -h / 2>/dev/null | awk 'NR==2{print $4}')|$(uptime -p 2>/dev/null || uptime)\\\"\";\r\n const windowsProbe = [\r\n \"$ProgressPreference='SilentlyContinue';\",\r\n \"$c = (docker ps -q 2>$null | Measure-Object).Count;\",\r\n \"$d = try { '{0:N1} GB' -f ((Get-PSDrive C).Free/1GB) } catch { 'N/A' };\",\r\n \"$u = try { (Get-Uptime).ToString() } catch { ((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime).ToString() };\",\r\n \"Write-Output \\\"$c|$d|$u\\\"\",\r\n ].join(' ');\r\n\r\n const probeOne = async (s: typeof servers[number]): Promise<[string, Stats]> => {\r\n try {\r\n const { conn, proxy, os } = await getServerConnection(s.id);\r\n conn.timeout = probeTimeoutMs;\r\n const wrapped = os === 'windows'\r\n ? buildPowerShellEncodedCommand(windowsProbe, [])\r\n : `bash -c ${posixQuote(linuxProbe)}`;\r\n const result = await sshExec(conn, wrapped, proxy);\r\n if (result.exitCode !== 0) {\r\n return [s.id, { reachable: false, error: (result.stderr || result.stdout || 'probe failed').trim().slice(0, 120) }];\r\n }\r\n const parts = result.stdout.trim().split('|');\r\n return [s.id, {\r\n reachable: true,\r\n containers: Number(parts[0]) || 0,\r\n diskFreeHuman: (parts[1] || '').trim() || 'N/A',\r\n uptimeHuman: (parts[2] || '').trim() || 'N/A',\r\n }];\r\n } catch (err) {\r\n return [s.id, { reachable: false, error: err instanceof Error ? err.message.slice(0, 120) : String(err).slice(0, 120) }];\r\n }\r\n };\r\n\r\n // Bounded parallelism so we don't open 50 SSH sessions at once.\r\n const results: Array<[string, Stats]> = [];\r\n for (let i = 0; i < servers.length; i += parallelism) {\r\n const batch = servers.slice(i, i + parallelism);\r\n const chunk = await Promise.all(batch.map(probeOne));\r\n results.push(...chunk);\r\n }\r\n statsByServer = new Map(results);\r\n }\r\n\r\n const lines = servers.map(s => {\r\n const tags = Array.isArray(s.tags) ? (s.tags as string[]).join(', ') : '';\r\n const os = (s as Record<string, unknown>).os_type || 'linux';\r\n const base = `${s.id} ${s.name} ${s.hostname}:${s.port} ${s.username} [${tags}] ${s.hosted_by || ''} os:${os}`;\r\n if (!includeStats) return base;\r\n const st = statsByServer.get(s.id);\r\n if (!st) return `${base} stats:skipped`;\r\n if (!st.reachable) return `${base} UNREACHABLE (${st.error || 'unknown'})`;\r\n return `${base} containers:${st.containers} disk_free:${st.diskFreeHuman} uptime:${st.uptimeHuman}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: lines.length ? lines.join('\\n') : 'No servers found' }] };\r\n }\r\n\r\n // ----- SSH -----\r\n case 'ssh-execute': {\r\n const command = String(a.command);\r\n assertSafeCommand(command);\r\n const args = Array.isArray(a.args) ? (a.args as unknown[]).map(String) : undefined;\r\n const stdin = typeof a.stdin === 'string' ? a.stdin : undefined;\r\n const shellOverride = typeof a.shell === 'string' ? (a.shell as 'auto' | 'bash' | 'powershell') : 'auto';\r\n const cwd = typeof a.cwd === 'string' && a.cwd ? a.cwd : undefined;\r\n const timeoutMs = a.timeout ? Number(a.timeout) : undefined;\r\n\r\n // Resolve target list. `serverIds` (array) wins over `serverId` (single).\r\n // Both forms are supported so the existing `serverId` API stays intact.\r\n const targetIds: string[] = Array.isArray(a.serverIds) && a.serverIds.length > 0\r\n ? (a.serverIds as unknown[]).map(String)\r\n : a.serverId ? [String(a.serverId)] : [];\r\n if (targetIds.length === 0) {\r\n return { content: [{ type: 'text', text: 'Error: pass either `serverId` or `serverIds[]`' }] };\r\n }\r\n\r\n const parallelism = Math.max(1, Math.min(20, Number(a.parallelism) || 5));\r\n\r\n // Per-server runner. Resolves connection, builds OS-aware command, runs.\r\n const runOne = async (serverId: string): Promise<{ serverId: string; serverName: string; os: ServerOs; shell: 'bash' | 'powershell'; result: SshResult }> => {\r\n const { conn, proxy, os } = await getServerConnection(serverId);\r\n if (timeoutMs) conn.timeout = timeoutMs;\r\n const shell = shellOverride === 'auto' ? (os === 'windows' ? 'powershell' : 'bash') : shellOverride;\r\n\r\n // Build the program-with-args portion first, then prepend cwd.\r\n let body: string;\r\n if (args && args.length > 0) {\r\n body = shell === 'powershell'\r\n ? buildPowerShellEncodedCommand(command, args)\r\n : buildPosixCommand(command, args);\r\n } else if (shell === 'powershell' && !/^powershell\\b/i.test(command.trim())) {\r\n // For Windows raw strings, still wrap so $/quotes don't get reinterpreted.\r\n body = buildPowerShellEncodedCommand(command, []);\r\n } else {\r\n body = command;\r\n }\r\n\r\n // Apply cwd. For PowerShell with EncodedCommand, we can't simply\r\n // prepend `cd ... && ...` because `body` is already a full\r\n // `powershell -EncodedCommand <b64>` invocation. Instead we re-encode\r\n // a wrapper script that does `Set-Location` then runs the original.\r\n let finalCmd = body;\r\n if (cwd) {\r\n if (shell === 'bash') {\r\n finalCmd = `cd ${posixQuote(cwd)} && ${body}`;\r\n } else {\r\n // body is `powershell ... -EncodedCommand <b64>`; pull out the b64.\r\n // Wrap as: powershell -EC <NEW_b64>, where NEW = `Set-Location ...; <decoded original>`.\r\n const ecMatch = body.match(/-EncodedCommand\\s+(\\S+)$/);\r\n if (ecMatch) {\r\n const decoded = Buffer.from(ecMatch[1] as string, 'base64').toString('utf16le');\r\n const wrapped = `Set-Location -LiteralPath '${cwd.replace(/'/g, \"''\")}'; ${decoded}`;\r\n const reencoded = Buffer.from(wrapped, 'utf16le').toString('base64');\r\n finalCmd = body.replace(/-EncodedCommand\\s+\\S+$/, `-EncodedCommand ${reencoded}`);\r\n }\r\n }\r\n }\r\n\r\n const result = await sshExec(conn, finalCmd, proxy, stdin !== undefined ? { stdin } : undefined);\r\n // Best-effort fetch of server name for output headers (only matters in fan-out).\r\n let serverName = serverId;\r\n try {\r\n const { data } = await supabase.from('ssh_server').select('name').eq('id', serverId).single();\r\n if (data?.name) serverName = data.name as string;\r\n } catch { /* fall back to id */ }\r\n return { serverId, serverName, os, shell, result };\r\n };\r\n\r\n // Single-target: keep the original output format unchanged.\r\n if (targetIds.length === 1) {\r\n const { os, shell, result } = await runOne(targetIds[0] as string);\r\n const output = [`Exit code: ${result.exitCode} (os: ${os}, shell: ${shell})`];\r\n if (result.stdout) output.push(`--- stdout ---\\n${result.stdout}`);\r\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\r\n return { content: [{ type: 'text', text: output.join('\\n') }] };\r\n }\r\n\r\n // Fan-out: bounded parallel execution. We run in batches of `parallelism`.\r\n const allResults: Array<Awaited<ReturnType<typeof runOne>> | { serverId: string; error: string }> = [];\r\n for (let i = 0; i < targetIds.length; i += parallelism) {\r\n const batch = targetIds.slice(i, i + parallelism);\r\n const settled = await Promise.allSettled(batch.map(id => runOne(id)));\r\n for (let j = 0; j < settled.length; j++) {\r\n const s = settled[j]!;\r\n if (s.status === 'fulfilled') allResults.push(s.value);\r\n else allResults.push({ serverId: batch[j] as string, error: s.reason instanceof Error ? s.reason.message : String(s.reason) });\r\n }\r\n }\r\n\r\n // Render per-server sections + a 1-line summary at the bottom.\r\n const sections: string[] = [];\r\n let okCount = 0;\r\n let failCount = 0;\r\n for (const r of allResults) {\r\n if ('error' in r) {\r\n failCount++;\r\n sections.push(`=== ${r.serverId} === !! connection error: ${r.error}`);\r\n continue;\r\n }\r\n if (r.result.exitCode === 0) okCount++; else failCount++;\r\n const header = `=== ${r.serverName} (${r.os}, exit ${r.result.exitCode}) ===`;\r\n const parts = [header];\r\n if (r.result.stdout) parts.push(r.result.stdout.trimEnd());\r\n if (r.result.stderr) parts.push(`[stderr] ${r.result.stderr.trimEnd()}`);\r\n sections.push(parts.join('\\n'));\r\n }\r\n sections.push(`--- fan-out summary: ${okCount} ok / ${failCount} failed across ${allResults.length} servers (parallelism ${parallelism}) ---`);\r\n return { content: [{ type: 'text', text: sections.join('\\n\\n') }] };\r\n }\r\n\r\n // ----- SFTP -----\r\n case 'sftp-list': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n const recursive = a.recursive === true;\r\n const maxResults = Math.max(1, Math.min(50_000, Number(a.maxResults) || 5_000));\r\n const pattern = typeof a.pattern === 'string' ? a.pattern : '';\r\n const summary = a.summary === true;\r\n // Sort key: 'name' (default), 'size', 'mtime'. `reverse: true` flips.\r\n const sortBy = (a.sortBy === 'size' || a.sortBy === 'mtime' || a.sortBy === 'name') ? a.sortBy : 'name';\r\n const reverse = a.reverse === true;\r\n\r\n // Collect into a backend-agnostic shape so sort/reverse/summary apply\r\n // identically to SSH and R2 listings.\r\n let entries: SftpEntry[];\r\n let truncated = false;\r\n let warning = '';\r\n\r\n if (bucket) {\r\n const prefix = r2Key(String(a.path || ''));\r\n const matcher = pattern ? globToRegExp(pattern) : null;\r\n const r2Entries = await r2List(bucket, prefix, { recursive, maxResults });\r\n const filtered = matcher\r\n ? r2Entries.filter(e => matcher.test(e.key.split('/').pop() || e.key))\r\n : r2Entries;\r\n entries = filtered.map(e => {\r\n const ms = e.mtime ? Date.parse(e.mtime) : 0;\r\n return {\r\n kind: e.isPrefix ? 'd' as const : '-' as const,\r\n size: e.size,\r\n mtime: e.mtime,\r\n mtimeMs: Number.isFinite(ms) ? ms : 0,\r\n path: e.key,\r\n };\r\n });\r\n } else {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sftpReaddir(conn, String(a.path || '/'), proxy, {\r\n recursive,\r\n maxDepth: typeof a.maxDepth === 'number' ? a.maxDepth : undefined,\r\n pattern: pattern || undefined,\r\n maxResults,\r\n });\r\n if (result.error && result.entries.length === 0) {\r\n return { content: [{ type: 'text', text: `Error: ${result.error}` }] };\r\n }\r\n entries = result.entries;\r\n truncated = result.truncated;\r\n if (result.error) warning = result.error;\r\n }\r\n\r\n // Summary mode short-circuits before sorting (we just aggregate).\r\n if (summary) {\r\n const files = entries.filter(e => e.kind === '-');\r\n const dirs = entries.filter(e => e.kind === 'd');\r\n const totalSize = files.reduce((acc, e) => acc + (e.size || 0), 0);\r\n const lines = [\r\n `Files: ${files.length}`,\r\n `Directories: ${dirs.length}`,\r\n `Total size: ${totalSize} bytes (${(totalSize / (1024 * 1024)).toFixed(2)} MB)`,\r\n ];\r\n if (truncated) lines.push(`(truncated at ${maxResults}; counts may be partial)`);\r\n if (warning) lines.push(`(warnings: ${warning})`);\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n // Sort. Directories first within the chosen sort, both ascending by\r\n // default; `reverse: true` flips the secondary order. `name` uses\r\n // localeCompare so digits/dots sort naturally.\r\n entries.sort((x, y) => {\r\n if (x.kind !== y.kind) return x.kind === 'd' ? -1 : 1;\r\n let cmp = 0;\r\n if (sortBy === 'size') cmp = x.size - y.size;\r\n else if (sortBy === 'mtime') cmp = x.mtimeMs - y.mtimeMs;\r\n else cmp = x.path.localeCompare(y.path);\r\n return reverse ? -cmp : cmp;\r\n });\r\n\r\n if (entries.length === 0) return { content: [{ type: 'text', text: 'No entries' }] };\r\n const lines = entries.map(e => {\r\n const sizeCol = e.kind === 'd' && bucket ? '(prefix)' : String(e.size);\r\n return `${e.kind} ${sizeCol.padStart(10)} ${(e.mtime || '').padEnd(24)} ${e.path}`;\r\n });\r\n if (truncated) lines.push(`... (truncated at ${maxResults} entries; raise maxResults or narrow path/pattern)`);\r\n if (warning) lines.push(`! ${warning}`);\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n case 'sftp-read': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n const offset = a.offset !== undefined ? Math.max(0, Number(a.offset)) : undefined;\r\n const length = a.length !== undefined ? Math.max(0, Number(a.length)) : undefined;\r\n const hasRange = offset !== undefined || length !== undefined;\r\n\r\n if (bucket) {\r\n const key = r2Key(String(a.path));\r\n if (!key) return { content: [{ type: 'text', text: 'Error: path is required' }] };\r\n try {\r\n if (hasRange) {\r\n const content = await r2GetObjectRange(bucket, key, { offset: offset ?? 0, length });\r\n return { content: [{ type: 'text', text: content }] };\r\n }\r\n const content = await r2GetObject(bucket, key, 1_048_576);\r\n return { content: [{ type: 'text', text: content }] };\r\n } catch (e) {\r\n return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };\r\n }\r\n }\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const content = await sftpRead(conn, String(a.path), proxy, hasRange ? { offset, length } : undefined);\r\n return { content: [{ type: 'text', text: content }] };\r\n }\r\n\r\n case 'sftp-write': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n // Optional file metadata. `mode` accepts a number (0o755) or a string\r\n // (\"755\" or \"0o755\") so the LLM can write either form. mtime accepts\r\n // ms since epoch or an ISO date string.\r\n let fileMode: number | undefined;\r\n if (typeof a.mode === 'number' && Number.isFinite(a.mode)) fileMode = a.mode & 0o7777;\r\n else if (typeof a.mode === 'string' && a.mode) {\r\n const cleaned = a.mode.replace(/^0o?/i, '');\r\n const parsed = parseInt(cleaned, 8);\r\n if (!Number.isNaN(parsed)) fileMode = parsed & 0o7777;\r\n }\r\n let mtimeMs: number | undefined;\r\n if (typeof a.mtime === 'number' && Number.isFinite(a.mtime)) mtimeMs = a.mtime;\r\n else if (typeof a.mtime === 'string' && a.mtime) {\r\n const parsed = Date.parse(a.mtime);\r\n if (!Number.isNaN(parsed)) mtimeMs = parsed;\r\n }\r\n\r\n if (bucket) {\r\n const key = r2Key(String(a.path));\r\n if (!key) return { content: [{ type: 'text', text: 'Error: path is required' }] };\r\n if (fileMode !== undefined || mtimeMs !== undefined) {\r\n // R2 (S3) has no POSIX mode/mtime. Surface this so the user knows\r\n // the params were ignored rather than silently dropping them.\r\n // We continue with the upload anyway.\r\n }\r\n try {\r\n if (typeof a.sourcePath === 'string' && a.sourcePath.length > 0) {\r\n const local = a.sourcePath;\r\n if (!isAbsolute(local)) return { content: [{ type: 'text', text: `Error: sourcePath must be an absolute path: ${local}` }] };\r\n if (!existsSync(local)) return { content: [{ type: 'text', text: `Error: sourcePath does not exist: ${local}` }] };\r\n const st = statSync(local);\r\n if (!st.isFile()) return { content: [{ type: 'text', text: `Error: sourcePath is not a regular file: ${local}` }] };\r\n const startedAt = Date.now();\r\n if (st.size > R2_MULTIPART_THRESHOLD) {\r\n // Multipart path: streams the local file in 100 MB parts and\r\n // logs progress per part. Up to ~5 TB per object on R2.\r\n let lastLog = 0;\r\n await r2PutObjectMultipart(bucket, key, local, st.size, (uploaded) => {\r\n if (uploaded - lastLog >= 500 * 1024 * 1024) {\r\n console.error(`[r2-write] ${formatBytes(uploaded)} / ${formatBytes(st.size)} → r2://${bucket}/${key}`);\r\n lastLog = uploaded;\r\n }\r\n });\r\n const elapsed = Date.now() - startedAt;\r\n const mbps = st.size / (1024 * 1024) / Math.max(0.001, elapsed / 1000);\r\n const noteParts: string[] = [];\r\n if (fileMode !== undefined) noteParts.push('mode ignored (R2)');\r\n if (mtimeMs !== undefined) noteParts.push('mtime ignored (R2)');\r\n const note = noteParts.length ? ` [${noteParts.join(', ')}]` : '';\r\n return { content: [{ type: 'text', text: `Uploaded ${formatBytes(st.size)} from ${local} to r2://${bucket}/${key} via multipart in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s)${note}` }] };\r\n }\r\n const stream = createReadStream(local);\r\n await r2PutObject(bucket, key, stream, st.size);\r\n const elapsed = Date.now() - startedAt;\r\n return { content: [{ type: 'text', text: `Uploaded ${st.size} bytes from ${local} to r2://${bucket}/${key} in ${elapsed}ms` }] };\r\n }\r\n const buf = Buffer.from(String(a.content ?? ''), 'utf-8');\r\n await r2PutObject(bucket, key, buf, buf.length);\r\n return { content: [{ type: 'text', text: `Wrote ${buf.length} bytes to r2://${bucket}/${key}` }] };\r\n } catch (e) {\r\n return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };\r\n }\r\n }\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const input: SftpWriteInput =\r\n typeof a.sourcePath === 'string' && a.sourcePath.length > 0\r\n ? { sourcePath: a.sourcePath }\r\n : { content: String(a.content ?? '') };\r\n const result = await sftpWrite(conn, String(a.path), input, proxy, { fileMode, mtimeMs });\r\n return { content: [{ type: 'text', text: result }] };\r\n }\r\n\r\n case 'sftp-delete': {\r\n const bucket = typeof a.bucket === 'string' && a.bucket ? a.bucket : '';\r\n const recursive = a.recursive === true;\r\n if (bucket) {\r\n const key = r2Key(String(a.path));\r\n if (!key) return { content: [{ type: 'text', text: 'Error: path is required' }] };\r\n try {\r\n if (recursive) {\r\n // Treat the path as a prefix: delete every object whose key\r\n // starts with it. R2 batches up to 1000 keys per call.\r\n const deleted = await r2DeletePrefix(bucket, key);\r\n return { content: [{ type: 'text', text: `Deleted ${deleted} object(s) under r2://${bucket}/${key}` }] };\r\n }\r\n await r2DeleteObject(bucket, key);\r\n return { content: [{ type: 'text', text: `Deleted r2://${bucket}/${key}` }] };\r\n } catch (e) {\r\n return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };\r\n }\r\n }\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sftpDelete(conn, String(a.path), proxy, { recursive });\r\n return { content: [{ type: 'text', text: result }] };\r\n }\r\n\r\n // ----- Docker -----\r\n case 'docker-list': {\r\n const format = a.format === 'json' ? 'json' : 'table';\r\n const composeOnly = a.composeOnly === true;\r\n const groupByProject = a.groupByProject === true;\r\n // nameFilter accepts string OR string[]. Each entry is matched as glob\r\n // (when it contains * or ?) or as a substring; a row passes if it\r\n // matches ANY entry.\r\n const nameFiltersRaw: string[] = Array.isArray(a.nameFilter)\r\n ? (a.nameFilter as unknown[]).map(v => String(v).trim()).filter(Boolean)\r\n : (typeof a.nameFilter === 'string' && a.nameFilter.trim() ? [a.nameFilter.trim()] : []);\r\n\r\n // Always fetch as NDJSON so we can sort/filter/group locally. This is\r\n // far more flexible than tweaking docker's --format on every variation.\r\n const filterArg = composeOnly ? ` --filter \"label=com.docker.compose.project\"` : '';\r\n const cmd = `docker ps -a${filterArg} --format '{{json .}}'`;\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sshExec(conn, cmd, proxy);\r\n if (result.exitCode !== 0) {\r\n return { content: [{ type: 'text', text: `Error: ${result.stderr || result.stdout}` }] };\r\n }\r\n\r\n type DockerPsRow = { Names?: string; Image?: string; Status?: string; Ports?: string; Labels?: string; Project?: string; Health?: string };\r\n const containers: DockerPsRow[] = [];\r\n for (const line of result.stdout.split('\\n')) {\r\n const trimmed = line.trim();\r\n if (!trimmed) continue;\r\n try { containers.push(JSON.parse(trimmed) as DockerPsRow); } catch { /* ignore malformed line */ }\r\n }\r\n\r\n // Enrich each row: compose project label + health status parsed from\r\n // the Status string (Docker reports \"Up 5 minutes (healthy)\" /\r\n // \"(unhealthy)\" / \"(health: starting)\" when a HEALTHCHECK is defined).\r\n for (const c of containers) {\r\n const m = (c.Labels || '').match(/com\\.docker\\.compose\\.project=([^,]+)/);\r\n c.Project = m ? m[1] : '';\r\n const status = c.Status || '';\r\n if (/\\(unhealthy\\)/i.test(status)) c.Health = 'unhealthy';\r\n else if (/\\(health: starting\\)|\\(starting\\)/i.test(status)) c.Health = 'starting';\r\n else if (/\\(healthy\\)/i.test(status)) c.Health = 'healthy';\r\n else if (/^Up\\b/i.test(status)) c.Health = 'no-check';\r\n else c.Health = ''; // exited / created / dead / paused: blank\r\n }\r\n\r\n // Multi-pattern filter: row passes when ANY pattern matches.\r\n let filtered = containers;\r\n if (nameFiltersRaw.length > 0) {\r\n const matchers = nameFiltersRaw.map(raw => {\r\n if (raw.includes('*') || raw.includes('?')) return { kind: 'glob' as const, re: globToRegExp(raw) };\r\n return { kind: 'sub' as const, lower: raw.toLowerCase() };\r\n });\r\n filtered = containers.filter(c => {\r\n const name = c.Names || '';\r\n const lower = name.toLowerCase();\r\n return matchers.some(m => m.kind === 'glob' ? m.re.test(name) : lower.includes(m.lower));\r\n });\r\n }\r\n\r\n // Default sort: project (empty last), then name.\r\n filtered.sort((x, y) => {\r\n const px = x.Project || '~'; // '~' sorts after letters so empty projects go last\r\n const py = y.Project || '~';\r\n const p = px.localeCompare(py);\r\n return p !== 0 ? p : (x.Names || '').localeCompare(y.Names || '');\r\n });\r\n\r\n if (format === 'json') {\r\n const text = filtered.map(c => JSON.stringify(c)).join('\\n') || '(no containers)';\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n // Table output. Health is a small fixed-width column so unhealthy\r\n // containers jump out visually.\r\n const fmtRow = (r: DockerPsRow) =>\r\n `${(r.Names || '').padEnd(36)} ${(r.Image || '').padEnd(40)} ${(r.Status || '').padEnd(24)} ${(r.Health || '').padEnd(10)} ${(r.Ports || '').padEnd(40)}`;\r\n\r\n if (groupByProject) {\r\n const groups = new Map<string, DockerPsRow[]>();\r\n for (const c of filtered) {\r\n const key = c.Project || '(no compose project)';\r\n const list = groups.get(key);\r\n if (list) list.push(c); else groups.set(key, [c]);\r\n }\r\n const out: string[] = [];\r\n for (const [project, rows] of groups) {\r\n out.push(`=== ${project} (${rows.length}) ===`);\r\n for (const r of rows) out.push(' ' + fmtRow(r));\r\n out.push('');\r\n }\r\n return { content: [{ type: 'text', text: out.join('\\n').trimEnd() || '(no containers)' }] };\r\n }\r\n\r\n const header = `${'NAMES'.padEnd(36)} ${'IMAGE'.padEnd(40)} ${'STATUS'.padEnd(24)} ${'HEALTH'.padEnd(10)} ${'PORTS'.padEnd(40)} PROJECT`;\r\n const body = filtered.map(r => `${fmtRow(r)} ${r.Project || ''}`);\r\n const text = filtered.length === 0 ? '(no containers match)' : [header, ...body].join('\\n');\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n\r\n case 'docker-logs': {\r\n // Accept containerName as string or string[]. Multi-container mode tails\r\n // each container in parallel and prefixes every line with [name] so it\r\n // reads like a unified, deinterleaved stream.\r\n const rawNames = Array.isArray(a.containerName)\r\n ? (a.containerName as unknown[]).map(String)\r\n : [String(a.containerName)];\r\n const containers = rawNames\r\n .map(n => n.replace(/[^a-zA-Z0-9._-]/g, ''))\r\n .filter(n => n.length > 0);\r\n if (containers.length === 0) {\r\n return { content: [{ type: 'text', text: 'Error: no valid containerName provided' }] };\r\n }\r\n\r\n // `tail` is the canonical name for \"last N lines\"; keep `lines` as alias\r\n // for backwards compatibility. Explicit user values (incl. 0) win over\r\n // defaults — important so `tail: 0` in follow mode means \"no backlog\".\r\n const followSeconds = Math.max(0, Math.min(300, Number(a.followSeconds) || 0));\r\n const userTail = a.tail !== undefined ? Number(a.tail) : (a.lines !== undefined ? Number(a.lines) : undefined);\r\n // Default differs by mode: 100 lines in batch mode, 0 in follow mode\r\n // (where you usually only want fresh lines).\r\n const tailArg = userTail !== undefined && Number.isFinite(userTail) && userTail >= 0\r\n ? userTail\r\n : (followSeconds > 0 ? 0 : 100);\r\n const sinceRaw = typeof a.since === 'string' ? a.since.trim() : '';\r\n const grepRaw = typeof a.grep === 'string' ? a.grep : '';\r\n\r\n // Validate `since`: relative (\"10m\"/\"2h\"/\"24h\"/\"30s\"/\"7d\") or ISO-ish absolute.\r\n if (sinceRaw && !/^\\d+[smhd]$/i.test(sinceRaw) && !/^\\d{4}-\\d{2}-\\d{2}/.test(sinceRaw)) {\r\n return { content: [{ type: 'text', text: 'Error: invalid `since` format (expected e.g. \"10m\", \"2h\", or ISO timestamp)' }] };\r\n }\r\n const sinceArg = sinceRaw ? ` --since ${posixQuote(sinceRaw)}` : '';\r\n const grepSuffix = grepRaw ? ` | grep -i -E ${posixQuote(grepRaw)} --line-buffered` : '';\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n // Wall budget: follow mode uses followSeconds, batch mode caps at 30s.\r\n // The server-side `timeout` enforces this so a stuck `docker logs`\r\n // (it happens, e.g. on busy kong/realtime containers) can't hang the\r\n // entire response.\r\n const wallSeconds = followSeconds > 0 ? followSeconds : 30;\r\n conn.timeout = (wallSeconds + 10) * 1000;\r\n\r\n const followFlag = followSeconds > 0 ? ' -f' : '';\r\n\r\n // Single-container: keep the original (unprefixed) output for backwards compat.\r\n if (containers.length === 1) {\r\n const c = containers[0];\r\n const inner = `docker logs${followFlag} --tail ${tailArg}${sinceArg} ${c} 2>&1${grepSuffix}`;\r\n // `timeout --signal=INT N CMD` so docker logs gets a clean SIGINT\r\n // and exits 124 on timeout. In batch mode timeout = safety net only.\r\n const cmd = `timeout --signal=INT ${wallSeconds} sh -c ${posixQuote(inner)}`;\r\n const result = await sshExec(conn, cmd, proxy);\r\n // Treat timeout (124) as success — we got whatever lines made it through\r\n // before the cap. Same for SIGINT (130) and SIGTERM (143).\r\n const acceptable = result.exitCode === 0\r\n || result.exitCode === 124\r\n || result.exitCode === 130\r\n || result.exitCode === 143\r\n || (!!grepRaw && result.exitCode === 1);\r\n if (!acceptable && !result.stdout) {\r\n return { content: [{ type: 'text', text: `Error (exit ${result.exitCode}): ${result.stderr || '(no output)'}` }] };\r\n }\r\n const note = result.exitCode === 124 ? `\\n(note: command exceeded ${wallSeconds}s wall budget; partial output)` : '';\r\n return { content: [{ type: 'text', text: (result.stdout || '(no log lines matched)') + note }] };\r\n }\r\n\r\n // Multi-container path: ALWAYS run sub-shells in parallel with `&` + wait.\r\n // Sequential `;` would let one stuck container block the others; with\r\n // `&` and an outer `timeout`, we get whatever lines each container\r\n // produced, capped by wallSeconds. `sed -u` keeps lines line-buffered\r\n // so parallel output stays atomic per line (mostly — true async streams\r\n // may still rarely interleave mid-line on slow pipes).\r\n const subShells = containers.map(c => {\r\n const inner = `docker logs${followFlag} --tail ${tailArg}${sinceArg} ${c} 2>&1${grepSuffix}`;\r\n return `(${inner} | sed -u -e ${posixQuote(`s/^/[${c}] /`)})`;\r\n });\r\n const innerCmd = subShells.join(' & ') + ' & wait';\r\n const cmd = `timeout --signal=INT ${wallSeconds} sh -c ${posixQuote(innerCmd)}`;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const acceptable = result.exitCode === 0\r\n || result.exitCode === 124\r\n || result.exitCode === 130\r\n || result.exitCode === 143\r\n || (!!grepRaw && result.exitCode === 1);\r\n if (!acceptable && !result.stdout) {\r\n return { content: [{ type: 'text', text: `Error (exit ${result.exitCode}): ${result.stderr || '(no output)'}` }] };\r\n }\r\n const note = result.exitCode === 124 ? `\\n(note: one or more containers exceeded ${wallSeconds}s wall budget; partial output)` : '';\r\n return { content: [{ type: 'text', text: (result.stdout || '(no log lines matched)') + note }] };\r\n }\r\n\r\n case 'docker-exec': {\r\n const container = String(a.container).replace(/[^a-zA-Z0-9._-]/g, '');\r\n if (!container) return { content: [{ type: 'text', text: 'Error: invalid container name' }] };\r\n const command = String(a.command);\r\n const args = Array.isArray(a.args) ? (a.args as unknown[]).map(String) : [];\r\n const stdin = typeof a.stdin === 'string' ? a.stdin : undefined;\r\n const interactive = a.interactive === true;\r\n const workdir = typeof a.workdir === 'string' && a.workdir ? ['-w', a.workdir] : [];\r\n const user = typeof a.user === 'string' && a.user ? ['-u', a.user] : [];\r\n\r\n // Flag matrix:\r\n // - stdin given: -i (attach stdin)\r\n // - interactive: -t (allocate TTY) so commands like psql / mysql / bash\r\n // that probe `isatty(stdout)` produce human-friendly output AND don't\r\n // complain (\"the input device is not a TTY\"). Combine with -i for full\r\n // interactive use; -t alone is allowed for tty-only programs.\r\n const flags: string[] = [];\r\n if (stdin !== undefined || interactive) flags.push('-i');\r\n if (interactive) flags.push('-t');\r\n\r\n // docker exec [-it] [-w DIR] [-u USER] CONTAINER CMD [ARG ...]\r\n const dockerArgs = [...flags, ...workdir, ...user, container, command, ...args];\r\n const fullCmd = buildPosixCommand('docker', ['exec', ...dockerArgs]);\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n if (a.timeout) conn.timeout = Number(a.timeout);\r\n // sshExec needs to allocate a PTY when -t is used; the existing ssh2\r\n // exec call requests a pseudo-terminal when we ask for one explicitly.\r\n const result = await sshExec(conn, fullCmd, proxy, {\r\n stdin,\r\n pty: interactive,\r\n });\r\n const output = [`Exit code: ${result.exitCode}`];\r\n if (result.stdout) output.push(`--- stdout ---\\n${result.stdout}`);\r\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\r\n return { content: [{ type: 'text', text: output.join('\\n') }] };\r\n }\r\n\r\n case 'docker-compose': {\r\n const projectPath = String(a.projectPath);\r\n if (!projectPath || !projectPath.startsWith('/')) {\r\n return { content: [{ type: 'text', text: 'Error: projectPath must be an absolute path' }] };\r\n }\r\n const action = String(a.action);\r\n const allowedActions = ['up', 'down', 'restart', 'logs', 'ps', 'pull', 'build'] as const;\r\n if (!allowedActions.includes(action as typeof allowedActions[number])) {\r\n return { content: [{ type: 'text', text: `Error: invalid action (allowed: ${allowedActions.join(', ')})` }] };\r\n }\r\n const service = typeof a.service === 'string' && a.service ? a.service : '';\r\n const tail = Number(a.tail) > 0 ? Number(a.tail) : 200;\r\n\r\n let composeArgs: string[];\r\n switch (action) {\r\n case 'up': composeArgs = service ? ['up', '-d', service] : ['up', '-d']; break;\r\n case 'down': composeArgs = service ? ['down', service] : ['down']; break;\r\n case 'restart': composeArgs = service ? ['restart', service] : ['restart']; break;\r\n case 'logs': composeArgs = service ? ['logs', '--no-color', `--tail=${tail}`, service] : ['logs', '--no-color', `--tail=${tail}`]; break;\r\n case 'ps': composeArgs = service ? ['ps', service] : ['ps']; break;\r\n case 'pull': composeArgs = service ? ['pull', service] : ['pull']; break;\r\n case 'build': composeArgs = service ? ['build', service] : ['build']; break;\r\n default: composeArgs = []; // unreachable\r\n }\r\n\r\n const composeCmd = buildPosixCommand('docker', ['compose', ...composeArgs]);\r\n const fullCmd = `cd ${posixQuote(projectPath)} && ${composeCmd} 2>&1`;\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n conn.timeout = Number(a.timeout) > 0 ? Number(a.timeout) : 120_000;\r\n const result = await sshExec(conn, fullCmd, proxy);\r\n const output = [`Exit code: ${result.exitCode} (compose ${action}${service ? ` ${service}` : ''} @ ${projectPath})`];\r\n if (result.stdout) output.push(result.stdout);\r\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\r\n return { content: [{ type: 'text', text: output.join('\\n') }] };\r\n }\r\n\r\n // ----- Database -----\r\n case 'db-discover': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const sites = await discoverSiteDatabases(conn, proxy);\r\n if (!sites.length) {\r\n return { content: [{ type: 'text', text: 'No web applications with database configs found in /var/www/' }] };\r\n }\r\n const lines = sites.map(s =>\r\n `${s.sitePath} [${s.appType}] db=${s.database} user=${s.user} host=${s.host}:${s.port}`\r\n );\r\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\r\n }\r\n\r\n case 'db-tables': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const sql = \"SELECT TABLE_NAME, ENGINE, TABLE_ROWS, ROUND(DATA_LENGTH/1024/1024, 2) AS `Size (MB)`, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME\";\r\n const output = await execSiteMysql(conn, String(a.sitePath), sql, proxy);\r\n return { content: [{ type: 'text', text: output || 'No tables found' }] };\r\n }\r\n\r\n case 'db-describe': {\r\n const table = String(a.table).replace(/[^a-zA-Z0-9_]/g, '');\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const output = await execSiteMysql(conn, String(a.sitePath),\r\n `DESCRIBE \\`${table}\\`; SHOW INDEX FROM \\`${table}\\``, proxy);\r\n return { content: [{ type: 'text', text: output }] };\r\n }\r\n\r\n case 'db-query': {\r\n const query = String(a.query).trim();\r\n assertSafeSql(query);\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const output = await execSiteMysql(conn, String(a.sitePath), query, proxy);\r\n return { content: [{ type: 'text', text: output || 'Query executed successfully (no output)' }] };\r\n }\r\n\r\n // ----- Env Config -----\r\n case 'env-list': {\r\n let query = supabase\r\n .from('env_config')\r\n .select('id, app_name, environment, description, updated_at, release_profile_stage_id')\r\n .order('app_name')\r\n .order('environment');\r\n\r\n if (a.releaseProfile) {\r\n const { stageIds } = await resolveReleaseProfileStageIds(String(a.releaseProfile));\r\n query = query.in('release_profile_stage_id', stageIds);\r\n }\r\n\r\n const { data, error } = await query;\r\n if (error) throw new Error(error.message);\r\n\r\n const stageIds = (data || [])\r\n .map((e) => e.release_profile_stage_id)\r\n .filter(Boolean) as string[];\r\n const profileNames = await getProfileNamesForStageIds(stageIds);\r\n\r\n const lines = (data || []).map((e) => {\r\n const profile = e.release_profile_stage_id\r\n ? profileNames[e.release_profile_stage_id] || 'unknown'\r\n : 'unlinked';\r\n return `${e.app_name}/${e.environment} [${profile}] (updated: ${e.updated_at})`;\r\n });\r\n return { content: [{ type: 'text', text: lines.length ? lines.join('\\n') : 'No environment configs stored' }] };\r\n }\r\n\r\n case 'env-get': {\r\n let query = supabase\r\n .from('env_config')\r\n .select('env_data_encrypted, release_profile_stage_id')\r\n .eq('app_name', String(a.appName))\r\n .eq('environment', String(a.environment));\r\n\r\n if (a.releaseProfile) {\r\n const { stageIds } = await resolveReleaseProfileStageIds(String(a.releaseProfile));\r\n query = query.in('release_profile_stage_id', stageIds);\r\n }\r\n\r\n const { data, error } = await query;\r\n\r\n if (error) throw new Error(`Env config query failed: ${error.message}`);\r\n if (!data || data.length === 0) {\r\n throw new Error(`Env config not found: ${a.appName}/${a.environment}${a.releaseProfile ? ` (profile: ${a.releaseProfile})` : ''}`);\r\n }\r\n if (data.length > 1) {\r\n const stageIds = data\r\n .map((r) => r.release_profile_stage_id)\r\n .filter(Boolean) as string[];\r\n const profileNames = await getProfileNamesForStageIds(stageIds);\r\n const names = [...new Set(Object.values(profileNames))].join(', ');\r\n throw new Error(\r\n `Multiple env configs found for ${a.appName}/${a.environment} across profiles: ${names}. ` +\r\n `Pass releaseProfile parameter to select one (e.g. releaseProfile: \"${Object.values(profileNames)[0] || '...'}\")`,\r\n );\r\n }\r\n\r\n const decrypted = decrypt(data[0]!.env_data_encrypted);\r\n return { content: [{ type: 'text', text: decrypted }] };\r\n }\r\n\r\n case 'env-store': {\r\n const appName = String(a.appName);\r\n const environment = String(a.environment);\r\n const encrypted = encrypt(String(a.content));\r\n\r\n let resolvedStageIds: string[] | null = null;\r\n if (a.releaseProfile) {\r\n const { stageIds } = await resolveReleaseProfileStageIds(String(a.releaseProfile));\r\n resolvedStageIds = stageIds;\r\n }\r\n\r\n let existQuery = supabase\r\n .from('env_config')\r\n .select('id, release_profile_stage_id')\r\n .eq('app_name', appName)\r\n .eq('environment', environment);\r\n\r\n if (resolvedStageIds) {\r\n existQuery = existQuery.in('release_profile_stage_id', resolvedStageIds);\r\n }\r\n\r\n const { data: existingRows, error: existErr } = await existQuery;\r\n if (existErr) throw new Error(`Lookup failed: ${existErr.message}`);\r\n\r\n if (existingRows && existingRows.length > 1 && !resolvedStageIds) {\r\n const stageIds = existingRows\r\n .map((r) => r.release_profile_stage_id)\r\n .filter(Boolean) as string[];\r\n const profileNames = await getProfileNamesForStageIds(stageIds);\r\n const names = [...new Set(Object.values(profileNames))].join(', ');\r\n throw new Error(\r\n `Multiple env configs found for ${appName}/${environment} across profiles: ${names}. ` +\r\n `Pass releaseProfile parameter to select one.`,\r\n );\r\n }\r\n\r\n const existing = existingRows?.[0] ?? null;\r\n let saveMsg: string;\r\n if (existing) {\r\n const { error } = await supabase\r\n .from('env_config')\r\n .update({\r\n env_data_encrypted: encrypted,\r\n description: a.description ? String(a.description) : undefined,\r\n updated_by: authContext!.userId,\r\n updated_at: new Date().toISOString(),\r\n })\r\n .eq('id', existing.id);\r\n if (error) throw new Error(error.message);\r\n saveMsg = `Updated env config: ${appName}/${environment}`;\r\n } else {\r\n const insertData: Record<string, unknown> = {\r\n app_name: appName,\r\n environment,\r\n env_data_encrypted: encrypted,\r\n description: a.description ? String(a.description) : null,\r\n created_by: authContext!.userId,\r\n updated_by: authContext!.userId,\r\n };\r\n if (resolvedStageIds?.[0]) {\r\n insertData.release_profile_stage_id = resolvedStageIds[0];\r\n }\r\n const { error } = await supabase.from('env_config').insert(insertData);\r\n if (error) throw new Error(error.message);\r\n saveMsg = `Stored env config: ${appName}/${environment}`;\r\n }\r\n\r\n const syncStageId = existing?.release_profile_stage_id ?? resolvedStageIds?.[0];\r\n const vercelStatus = await attemptVercelSync(appName, environment, syncStageId);\r\n return { content: [{ type: 'text', text: `${saveMsg}. ${vercelStatus}` }] };\r\n }\r\n\r\n // ----- Cache Purge -----\r\n case 'cache-purge': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n conn.timeout = 120_000;\r\n const script = `\r\nR=\"\"\r\n# 1. OPcache – kill lsphp so it respawns with a fresh OPcache\r\nif pgrep -x lsphp >/dev/null 2>&1; then\r\n sudo killall lsphp 2>/dev/null && R=\"\\${R}[OK] OPcache: killed lsphp processes\\\\n\" || R=\"\\${R}[FAIL] OPcache: could not kill lsphp\\\\n\"\r\nelse\r\n R=\"\\${R}[SKIP] OPcache: no lsphp processes running\\\\n\"\r\nfi\r\n# 2. LiteSpeed cache directories\r\nLS=0\r\nfor cdir in /tmp/lshttpd/swap /usr/local/lsws/cachedata; do\r\n if [ -d \"\\$cdir\" ] && [ \"\\$(ls -A \"\\$cdir\" 2>/dev/null)\" ]; then\r\n sudo rm -rf \"\\$cdir\"/* 2>/dev/null && R=\"\\${R}[OK] LS cache: cleared \\$cdir\\\\n\" && LS=1 || R=\"\\${R}[FAIL] LS cache: \\$cdir\\\\n\"\r\n fi\r\ndone\r\n[ \"\\$LS\" -eq 0 ] && R=\"\\${R}[SKIP] LS cache: no cache dirs with content\\\\n\"\r\n# 3. LiteSpeed graceful restart\r\nif [ -x /usr/local/lsws/bin/lswsctrl ]; then\r\n sudo /usr/local/lsws/bin/lswsctrl restart 2>/dev/null && R=\"\\${R}[OK] LiteSpeed: graceful restart\\\\n\" || R=\"\\${R}[FAIL] LiteSpeed: restart failed\\\\n\"\r\nelif systemctl is-active lsws >/dev/null 2>&1 || systemctl is-active lshttpd >/dev/null 2>&1; then\r\n sudo systemctl restart lsws 2>/dev/null || sudo systemctl restart lshttpd 2>/dev/null\r\n R=\"\\${R}[OK] LiteSpeed: restarted via systemctl\\\\n\"\r\nelse\r\n R=\"\\${R}[SKIP] LiteSpeed: not detected\\\\n\"\r\nfi\r\n# 4. WordPress caches\r\nWP=0\r\nfor dir in /var/www/*/; do\r\n [ -d \"\\$dir\" ] || continue\r\n for root in \"\\$dir\" \"\\${dir}html\" \"\\${dir}public_html\" \"\\${dir}public\" \"\\${dir}httpdocs\"; do\r\n [ -f \"\\$root/wp-config.php\" ] || continue\r\n WP=1; SITE=\\$(basename \"\\$dir\")\r\n if command -v wp >/dev/null 2>&1; then\r\n wp cache flush --allow-root --path=\"\\$root\" 2>/dev/null && R=\"\\${R}[OK] WP (\\$SITE): wp cache flush\\\\n\" || R=\"\\${R}[FAIL] WP (\\$SITE): wp cache flush\\\\n\"\r\n elif [ -d \"\\$root/wp-content/cache\" ]; then\r\n rm -rf \"\\$root/wp-content/cache\"/* 2>/dev/null && R=\"\\${R}[OK] WP (\\$SITE): cleared wp-content/cache\\\\n\"\r\n else\r\n R=\"\\${R}[SKIP] WP (\\$SITE): no cache dir, no wp-cli\\\\n\"\r\n fi\r\n break\r\n done\r\ndone\r\n[ \"\\$WP\" -eq 0 ] && R=\"\\${R}[SKIP] WordPress: no sites found\\\\n\"\r\n# 5. PrestaShop caches\r\nPS=0\r\nfor dir in /var/www/*/; do\r\n [ -d \"\\$dir\" ] || continue\r\n for root in \"\\$dir\" \"\\${dir}html\" \"\\${dir}public_html\" \"\\${dir}public\" \"\\${dir}httpdocs\"; do\r\n IS=0\r\n [ -f \"\\$root/app/config/parameters.php\" ] && IS=1\r\n [ -f \"\\$root/config/settings.inc.php\" ] && IS=1\r\n [ \"\\$IS\" -eq 0 ] && continue\r\n PS=1; SITE=\\$(basename \"\\$dir\"); C=\"\"\r\n [ -d \"\\$root/var/cache\" ] && rm -rf \"\\$root/var/cache\"/* 2>/dev/null && C=\"\\${C}var/cache \"\r\n [ -d \"\\$root/cache/smarty/compile\" ] && rm -rf \"\\$root/cache/smarty/compile\"/* 2>/dev/null && C=\"\\${C}smarty/compile \"\r\n [ -d \"\\$root/cache/smarty/cache\" ] && rm -rf \"\\$root/cache/smarty/cache\"/* 2>/dev/null && C=\"\\${C}smarty/cache \"\r\n [ -n \"\\$C\" ] && R=\"\\${R}[OK] PS (\\$SITE): cleared \\${C}\\\\n\" || R=\"\\${R}[SKIP] PS (\\$SITE): no cache dirs\\\\n\"\r\n break\r\n done\r\ndone\r\n[ \"\\$PS\" -eq 0 ] && R=\"\\${R}[SKIP] PrestaShop: no sites found\\\\n\"\r\n# 6. Redis\r\nif command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then\r\n redis-cli FLUSHALL 2>/dev/null && R=\"\\${R}[OK] Redis: FLUSHALL\\\\n\" || R=\"\\${R}[FAIL] Redis: FLUSHALL failed\\\\n\"\r\nelse\r\n R=\"\\${R}[SKIP] Redis: not available\\\\n\"\r\nfi\r\n# 7. Memcached\r\nif systemctl is-active memcached >/dev/null 2>&1; then\r\n if command -v memcflush >/dev/null 2>&1; then\r\n memcflush --servers=localhost 2>/dev/null && R=\"\\${R}[OK] Memcached: flushed\\\\n\" || R=\"\\${R}[FAIL] Memcached: flush failed\\\\n\"\r\n else\r\n echo \"flush_all\" | nc -q1 localhost 11211 2>/dev/null && R=\"\\${R}[OK] Memcached: flushed via nc\\\\n\" || R=\"\\${R}[FAIL] Memcached: flush failed\\\\n\"\r\n fi\r\nelse\r\n R=\"\\${R}[SKIP] Memcached: not active\\\\n\"\r\nfi\r\necho -e \"\\$R\"\r\n`.trim();\r\n const result = await sshExec(conn, script, proxy);\r\n const output = (result.stdout || '').trim();\r\n return { content: [{ type: 'text', text: output || 'Cache purge completed (no output)' }] };\r\n }\r\n\r\n // ----- Domains (mijn.host) -----\r\n case 'domain-list': {\r\n interface DomainListItem {\r\n id: number;\r\n domain: string;\r\n renewal_date: string;\r\n status: string;\r\n status_id: number;\r\n tags: string[];\r\n }\r\n\r\n const res = await mijnhostFetch<{ domains: DomainListItem[] }>('/domains');\r\n const domains = res.data.domains;\r\n\r\n if (!domains.length) {\r\n return { content: [{ type: 'text', text: 'No domains found' }] };\r\n }\r\n\r\n const lines = domains.map(d => {\r\n const tags = d.tags?.length ? ` [${d.tags.join(', ')}]` : '';\r\n return `${d.domain} status=${d.status} renewal=${d.renewal_date}${tags}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: `${domains.length} domain(s):\\n\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n case 'dns-list': {\r\n const domain = String(a.domain);\r\n if (!domain) throw new Error('domain is required');\r\n\r\n interface DnsRecord { type: string; name: string; value: string; ttl: number; }\r\n\r\n const res = await mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n const records = res.data.records;\r\n\r\n if (!records.length) {\r\n return { content: [{ type: 'text', text: `No DNS records found for ${domain}` }] };\r\n }\r\n\r\n const header = 'TYPE NAME VALUE TTL';\r\n const sep = '-'.repeat(90);\r\n const lines = records.map(r =>\r\n `${r.type.padEnd(10)}${r.name.padEnd(31)}${r.value.substring(0, 40).padEnd(41)}${r.ttl}`\r\n );\r\n\r\n return { content: [{ type: 'text', text: `DNS records for ${domain} (${records.length}):\\n\\n${header}\\n${sep}\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n case 'dns-create': {\r\n const domain = String(a.domain);\r\n const type = String(a.type).toUpperCase();\r\n const dnsName = String(a.name);\r\n const value = String(a.value);\r\n const ttl = Number(a.ttl) || 3600;\r\n\r\n if (!domain || !type || !dnsName || !value) {\r\n throw new Error('domain, type, name, and value are required');\r\n }\r\n\r\n interface DnsRecordCreate { type: string; name: string; value: string; ttl: number; }\r\n\r\n const current = await mijnhostFetch<{ domain: string; records: DnsRecordCreate[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n\r\n const records = [...current.data.records, { type, name: dnsName, value, ttl }];\r\n\r\n await mijnhostFetch<void>(`/domains/${encodeURIComponent(domain)}/dns`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ records }),\r\n });\r\n\r\n return { content: [{ type: 'text', text: `DNS record created: ${type} ${dnsName} → ${value} (TTL: ${ttl})` }] };\r\n }\r\n\r\n case 'dns-update': {\r\n const domain = String(a.domain);\r\n const type = String(a.type).toUpperCase();\r\n const dnsName = String(a.name);\r\n const oldValue = String(a.oldValue);\r\n const newValue = String(a.newValue);\r\n const ttl = Number(a.ttl) || undefined;\r\n\r\n if (!domain || !type || !dnsName || !oldValue || !newValue) {\r\n throw new Error('domain, type, name, oldValue, and newValue are required');\r\n }\r\n\r\n interface DnsRecord { type: string; name: string; value: string; ttl: number; }\r\n\r\n const current = await mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n\r\n const idx = current.data.records.findIndex(\r\n r => r.type === type && r.name === dnsName && r.value === oldValue\r\n );\r\n\r\n if (idx === -1) {\r\n throw new Error(`No matching DNS record found: ${type} ${dnsName} = ${oldValue}`);\r\n }\r\n\r\n const updated = [...current.data.records];\r\n const existingTtl = updated[idx]!.ttl;\r\n updated[idx] = {\r\n type,\r\n name: dnsName,\r\n value: newValue,\r\n ttl: ttl ?? existingTtl,\r\n };\r\n\r\n await mijnhostFetch<void>(`/domains/${encodeURIComponent(domain)}/dns`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ records: updated }),\r\n });\r\n\r\n return { content: [{ type: 'text', text: `DNS record updated: ${type} ${dnsName} → ${newValue}${ttl ? ` (TTL: ${ttl})` : ''}` }] };\r\n }\r\n\r\n case 'dns-delete': {\r\n const domain = String(a.domain);\r\n const type = String(a.type).toUpperCase();\r\n const dnsName = String(a.name);\r\n const value = String(a.value);\r\n\r\n if (!domain || !type || !dnsName || !value) {\r\n throw new Error('domain, type, name, and value are required');\r\n }\r\n\r\n interface DnsRecord { type: string; name: string; value: string; ttl: number; }\r\n\r\n const current = await mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\r\n `/domains/${encodeURIComponent(domain)}/dns`\r\n );\r\n\r\n const before = current.data.records.length;\r\n const remaining = current.data.records.filter(\r\n r => !(r.type === type && r.name === dnsName && r.value === value)\r\n );\r\n\r\n if (remaining.length === before) {\r\n throw new Error(`No matching DNS record found: ${type} ${dnsName} = ${value}`);\r\n }\r\n\r\n await mijnhostFetch<void>(`/domains/${encodeURIComponent(domain)}/dns`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ records: remaining }),\r\n });\r\n\r\n return { content: [{ type: 'text', text: `DNS record deleted: ${type} ${dnsName} = ${value} (${remaining.length} records remaining)` }] };\r\n }\r\n\r\n default:\r\n if (TRIGGER_TOOL_NAMES.has(name)) {\r\n return handleTriggerTool(name, a, { sshExec, getServerConnection });\r\n }\r\n if (AGENT_TOOL_NAMES.has(name)) {\r\n return handleAgentTool(name, a);\r\n }\r\n return { content: [{ type: 'text', text: `Unknown tool: ${name}` }] };\r\n }\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : String(err);\r\n return { content: [{ type: 'text', text: `Error: ${message}` }] };\r\n }\r\n}\r\n\r\n/** Create a configured MCP Server instance with handlers attached. */\r\nfunction createMcpServer(): Server {\r\n const s = new Server(\r\n { name: 'mg-dashboard-mcp', version: MCP_VERSION },\r\n { capabilities: { tools: {} } },\r\n );\r\n s.setRequestHandler(ListToolsRequestSchema, handleListTools);\r\n s.setRequestHandler(CallToolRequestSchema, handleCallTool as Parameters<typeof s.setRequestHandler>[1]);\r\n return s;\r\n}\r\n\r\nconst server = createMcpServer();\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main\r\n// ---------------------------------------------------------------------------\r\n\r\nasync function main() {\r\n console.error('Starting MG Dashboard MCP Server...');\r\n\r\n const apiAuthContext = await validateApiKey(apiKey!);\r\n if (!apiAuthContext) {\r\n console.error('API key validation failed');\r\n process.exit(1);\r\n }\r\n\r\n authContext = await validateSshKey(sshKeyPath!, apiAuthContext.apiKeyId);\r\n if (!authContext) {\r\n console.error('SSH-key authentication failed');\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Security] MCP v${MCP_VERSION} | Key: ${authContext.apiKeyName}`);\r\n\r\n const toolNames = TOOLS.map(t => t.name).join(', ');\r\n\r\n if (httpMode) {\r\n console.error(`API key validated. Starting Streamable HTTP transport on port ${httpPort}...`);\r\n\r\n const transports = new Map<string, StreamableHTTPServerTransport>();\r\n\r\n const REST_TOOL_MAP: Record<string, string> = {\r\n '/api/web-search': 'web-search',\r\n '/api/web-fetch': 'web-fetch',\r\n };\r\n\r\n const httpServer = createHttpServer(async (req, res) => {\r\n const url = new URL(req.url ?? '/', `http://localhost:${httpPort}`);\r\n\r\n // ── Simple REST endpoints for agents that can't use MCP protocol ──\r\n const restToolName = REST_TOOL_MAP[url.pathname];\r\n if (restToolName && req.method === 'POST') {\r\n if (!authContext) {\r\n res.writeHead(401, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: 'Not authenticated' }));\r\n return;\r\n }\r\n const requiredModule = TOOL_MODULE_MAP[restToolName];\r\n if (requiredModule && authContext.permissions.modules[requiredModule] !== true) {\r\n res.writeHead(403, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: `Access denied: no permission for \"${requiredModule}\" module` }));\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n let toolArgs: Record<string, unknown>;\r\n try {\r\n toolArgs = JSON.parse(Buffer.concat(chunks).toString());\r\n } catch {\r\n res.writeHead(400, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\r\n return;\r\n }\r\n try {\r\n const result = await handleAgentTool(restToolName, toolArgs);\r\n res.writeHead(200, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ ok: true, result }));\r\n } catch (err) {\r\n res.writeHead(500, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));\r\n }\r\n return;\r\n }\r\n\r\n if (url.pathname === '/api/tools' && req.method === 'GET') {\r\n res.writeHead(200, { 'Content-Type': 'application/json' });\r\n res.end(JSON.stringify({ tools: Object.keys(REST_TOOL_MAP) }));\r\n return;\r\n }\r\n\r\n if (url.pathname !== '/mcp') {\r\n res.writeHead(404, { 'Content-Type': 'text/plain' });\r\n res.end('Not found');\r\n return;\r\n }\r\n\r\n if (req.method === 'OPTIONS') {\r\n res.writeHead(204, {\r\n 'Access-Control-Allow-Origin': '*',\r\n 'Access-Control-Allow-Methods': 'GET, POST, DELETE, OPTIONS',\r\n 'Access-Control-Allow-Headers': 'Content-Type, mcp-session-id',\r\n 'Access-Control-Expose-Headers': 'mcp-session-id',\r\n });\r\n res.end();\r\n return;\r\n }\r\n\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Expose-Headers', 'mcp-session-id');\r\n\r\n const sessionId = req.headers['mcp-session-id'] as string | undefined;\r\n\r\n let body: Record<string, unknown> | undefined;\r\n if (req.method === 'POST') {\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n try {\r\n body = JSON.parse(Buffer.concat(chunks).toString());\r\n } catch {\r\n res.writeHead(400, { 'Content-Type': 'text/plain' });\r\n res.end('Invalid JSON');\r\n return;\r\n }\r\n }\r\n\r\n if (sessionId && transports.has(sessionId)) {\r\n await transports.get(sessionId)!.handleRequest(req, res, body);\r\n return;\r\n }\r\n\r\n if (req.method === 'POST' && body && (Array.isArray(body) ? body.some(isInitializeRequest) : isInitializeRequest(body))) {\r\n const transport = new StreamableHTTPServerTransport({\r\n sessionIdGenerator: () => randomUUID(),\r\n });\r\n transport.onclose = () => {\r\n if (transport.sessionId) transports.delete(transport.sessionId);\r\n };\r\n const sessionServer = createMcpServer();\r\n await sessionServer.connect(transport);\r\n if (transport.sessionId) transports.set(transport.sessionId, transport);\r\n await transport.handleRequest(req, res, body);\r\n return;\r\n }\r\n\r\n res.writeHead(400, { 'Content-Type': 'text/plain' });\r\n res.end('Bad request — missing or invalid session');\r\n });\r\n\r\n httpServer.listen(httpPort, () => {\r\n console.error(`MCP HTTP server ready on port ${httpPort}. Tools: ${toolNames}`);\r\n });\r\n } else {\r\n console.error('API key validated. Starting stdio transport...');\r\n const transport = new StdioServerTransport();\r\n await server.connect(transport);\r\n console.error(`MCP Server ready. Tools: ${toolNames}`);\r\n }\r\n}\r\n\r\nmain().catch((err) => {\r\n console.error('Fatal error:', err);\r\n process.exit(1);\r\n});\r\n"]}
|