@mgsoftwarebv/mg-dashboard-mcp 3.6.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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","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,YAAA,EAAc,SAAA;AAAA,EACd,kBAAA,EAAoB,SAAA;AAAA,EACpB,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,MAAA;AACJ,EAAA,IAAIA,KAAAA,CAAK,WAAW,CAAA,EAAG;AACrB,IAAA,MAAA,GAAS,OAAA;AAAA,EACX,CAAA,MAAO;AACL,IAAA,MAAA,GAAS,CAAA,EAAA,EAAK,aAAA,CAAc,OAAO,CAAC,CAAA,CAAA,EAAIA,KAAAA,CAAK,GAAA,CAAI,aAAa,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,EAC3E;AACA,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,SAAS,CAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA;AACnC,EAAA,OAAO,iFAAiF,GAAG,CAAA,CAAA;AAC7F;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;AACpB,MAAA,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS,CAAC,GAAA,EAAK,MAAA,KAAW;AACjC,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,YAAA,CAAa,IAAA,CAAK,OAAA,EAAS,CAAC,OAAA,EAAS,MAAA,KAAW;AAC9C,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;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;AAEA,eAAe,WAAA,CACb,IAAA,EACA,OAAA,EACA,KAAA,EACA,OAAA,EACiB;AACjB,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,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;AAEvG,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;AAE5G,QAAA,MAAM,QAAkB,EAAC;AACzB,QAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,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,KAAA,CAAM,KAAK,CAAA,gBAAA,EAAmB,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AACrD,cAAA,OAAO,UAAA,EAAW;AAAA,YACpB;AACA,YAAA,MAAM,UAAoB,EAAC;AAC3B,YAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,cAAA,IAAI,KAAA,CAAM,UAAU,UAAA,EAAY;AAAE,gBAAA,SAAA,GAAY,IAAA;AAAM,gBAAA;AAAA,cAAO;AAC3D,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,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAI,CAAA,CAAE,WAAA,EAAY,GAAI,EAAA;AACnF,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,MAAM,OAAA,GAAU,SAAA,GAAY,QAAA,GAAW,IAAA,CAAK,QAAA;AAC5C,gBAAA,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,GAAG,IAAI,MAAA,CAAO,IAAI,CAAA,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAA;AAAA,cACpF;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,IAAI,SAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,kBAAA,EAAqB,UAAU,CAAA,kDAAA,CAAoD,CAAA;AAC7G,UAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAI,IAAI,YAAY,CAAA;AAAA,QACxD,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;AAEA,eAAe,QAAA,CAAS,IAAA,EAA4B,QAAA,EAAkB,KAAA,EAA+C;AACnH,EAAA,MAAM,IAAA,GAAO,aAAa,QAAQ,CAAA;AAClC,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,IAAA,CAAK,KAAA,CAAM,IAAA,IAAQ,CAAA,IAAK,OAAA,EAAW;AACjC,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAC5C,YAAA,OAAA,CAAQ,CAAA,uBAAA,EAA0B,KAAA,CAAM,IAAI,CAAA,gBAAA,CAAkB,CAAA;AAC9D,YAAA;AAAA,UACF;AACA,UAAA,MAAM,SAAmB,EAAC;AAC1B,UAAA,MAAM,EAAA,GAAK,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA;AACrC,UAAA,EAAA,CAAG,GAAG,MAAA,EAAQ,CAAC,OAAe,MAAA,CAAO,IAAA,CAAK,EAAE,CAAC,CAAA;AAC7C,UAAA,EAAA,CAAG,EAAA,CAAG,OAAO,MAAM;AAAE,YAAA,YAAA,CAAa,KAAK,CAAA;AAAG,YAAA,OAAA,IAAU;AAAG,YAAA,OAAA,GAAU,KAAA,CAAA;AAAW,YAAA,OAAA,CAAQ,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAA,EAAA,KAAM,IAAI,UAAA,CAAW,EAAE,CAAC,CAAC,CAAA,CAAE,QAAA,CAAS,OAAO,CAAC,CAAA;AAAA,UAAG,CAAC,CAAA;AAC7J,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,KAAA,EACiB;AACjB,EAAA,MAAM,IAAA,GAAO,aAAa,QAAQ,CAAA;AAClC,EAAA,kBAAA,CAAmB,IAAI,CAAA;AAGvB,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;AAE9C,QAAA,IAAI,SAAS,SAAA,EAAW;AACtB,UAAA,MAAM,KAAK,IAAA,CAAK,iBAAA,CAAkB,MAAM,EAAE,IAAA,EAAM,KAAO,CAAA;AACvD,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,MAAA,CAAO,WAAW,aAAa,CAAA,UAAA,EAAa,IAAI,CAAA,IAAA,EAAO,OAAO,CAAA,EAAA,CAAI,CAAA;AAAA,UACpE,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,GAAA;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,MAAA;AAAA,cACE,YAAY,WAAA,CAAY,aAAa,CAAC,CAAA,MAAA,EAAS,SAAS,OAAO,IAAI,CAAA,IAAA,EAAA,CAC5D,OAAA,GAAU,GAAA,EAAM,QAAQ,CAAC,CAAC,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,MAAA;AAAA,aACxD;AAAA,UACF;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,CAAW,IAAA,EAA4B,QAAA,EAAkB,KAAA,EAA+C;AACrH,EAAA,MAAM,IAAA,GAAO,aAAa,QAAQ,CAAA;AAClC,EAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,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,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,EAAa,gGAAA;AAAA,IACb,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAmB,YAAY,EAAC,EAAG,QAAA,EAAU,EAAC;AAAE,GACvE;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,2yBAAA;AAAA,IAKF,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,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,8IAAA,EAA0I;AAAA,QAChL,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,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0CAAA;AAA2C,OACrF;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,SAAS;AAAA;AAClC,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACE,yKAAA;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,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qCAAA,EAAsC;AAAA,QAC3E,SAAA,EAAW,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,0CAAA,EAA2C;AAAA,QACtF,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2CAAA,EAA4C;AAAA,QACrF,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sFAAA,EAAuF;AAAA,QAC/H,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sDAAA;AAAuD,OACpG;AAAA,MACA,QAAA,EAAU,CAAC,UAAU;AAAA;AACvB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EAAa,yEAAA;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,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,mBAAA;AAAoB,OAC3D;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,MAAM;AAAA;AAC/B,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EACE,oiBAAA;AAAA,IAIF,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,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,2BAAA,EAA4B;AAAA,QACjE,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gEAAA,EAAiE;AAAA,QACzG,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sHAAA;AAAuH,OACpK;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,MAAM;AAAA;AAC/B,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EAAa,mGAAA;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,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,kCAAA;AAAmC,OAC1E;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,MAAM;AAAA;AAC/B,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,8KAAA;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;AAAiE,OAChH;AAAA,MACA,QAAA,EAAU,CAAC,UAAU;AAAA;AACvB,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,oJAAA;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,aAAA,EAAe,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sBAAA,EAAuB;AAAA,QACrE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gDAAA,EAAiD;AAAA,QACvF,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,6EAAA,EAA8E;AAAA,QACpH,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gGAAA;AAAiG,OACxI;AAAA,MACA,QAAA,EAAU,CAAC,UAAA,EAAY,eAAe;AAAA;AACxC,GACF;AAAA,EACA;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACE,4PAAA;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,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,YAAA;AAAA,IACN,WAAA,EAAa,sJAAA;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,kBAAA;AAAA,IACN,WAAA,EAAa,yIAAA;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,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,oDAAA;AAAqD,OAClG;AAAA,MACA,QAAA,EAAU,CAAC,QAAA,EAAU,YAAY;AAAA;AACnC,GACF;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,KAAA,GAAA,CAAS,IAAA,IAAQ,EAAC,EAAG,IAAI,CAAA,CAAA,KAAK;AAClC,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,OAAO,CAAA,EAAG,EAAE,EAAE,CAAA,EAAA,EAAK,EAAE,IAAI,CAAA,EAAA,EAAK,CAAA,CAAE,QAAQ,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,EAAA,EAAK,CAAA,CAAE,QAAQ,CAAA,GAAA,EAAM,IAAI,MAAM,CAAA,CAAE,SAAA,IAAa,EAAE,CAAA,KAAA,EAAQ,EAAE,CAAA,CAAA;AAAA,QAC9G,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;AAElG,QAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,EAAA,EAAG,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACxE,QAAA,IAAI,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,EAAE,OAAO,CAAA;AAG9C,QAAA,MAAM,QAAQ,aAAA,KAAkB,MAAA,GAAU,EAAA,KAAO,SAAA,GAAY,eAAe,MAAA,GAAU,aAAA;AAItF,QAAA,IAAI,QAAA;AACJ,QAAA,IAAIA,KAAAA,IAAQA,KAAAA,CAAK,MAAA,GAAS,CAAA,EAAG;AAC3B,UAAA,QAAA,GAAW,KAAA,KAAU,eACjB,6BAAA,CAA8B,OAAA,EAASA,KAAI,CAAA,GAC3C,iBAAA,CAAkB,SAASA,KAAI,CAAA;AAAA,QACrC,CAAA,MAAA,IAAW,UAAU,YAAA,IAAgB,CAAC,iBAAiB,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,CAAA,EAAG;AAG3E,UAAA,QAAA,GAAW,6BAAA,CAA8B,OAAA,EAAS,EAAE,CAAA;AAAA,QACtD,CAAA,MAAO;AACL,UAAA,QAAA,GAAW,OAAA;AAAA,QACb;AAEA,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,KAAA,KAAU,KAAA,CAAA,GAAY,EAAE,KAAA,EAAM,GAAI,KAAA,CAAS,CAAA;AAC/F,QAAA,MAAM,MAAA,GAAS,CAAC,CAAA,WAAA,EAAc,MAAA,CAAO,QAAQ,CAAA,MAAA,EAAS,EAAE,CAAA,SAAA,EAAY,KAAK,CAAA,CAAA,CAAG,CAAA;AAC5E,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;AAAA,MAGA,KAAK,WAAA,EAAa;AAChB,QAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,mBAAA,CAAoB,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpE,QAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,IAAA,EAAM,OAAO,CAAA,CAAE,IAAA,IAAQ,GAAG,CAAA,EAAG,KAAA,EAAO;AAAA,UACpE,SAAA,EAAW,EAAE,SAAA,KAAc,IAAA;AAAA,UAC3B,UAAU,OAAO,CAAA,CAAE,QAAA,KAAa,QAAA,GAAW,EAAE,QAAA,GAAW,KAAA,CAAA;AAAA,UACxD,SAAS,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,GAAW,EAAE,OAAA,GAAU,KAAA,CAAA;AAAA,UACrD,YAAY,OAAO,CAAA,CAAE,UAAA,KAAe,QAAA,GAAW,EAAE,UAAA,GAAa,KAAA;AAAA,SAC/D,CAAA;AACD,QAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,CAAA,EAAE;AAAA,MACtD;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,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAM,OAAO,CAAA,CAAE,IAAI,GAAG,KAAK,CAAA;AAC1D,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,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,OAAO,CAAA,CAAE,IAAI,CAAA,EAAG,KAAA,EAAO,KAAK,CAAA;AACjE,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,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,OAAO,CAAA,CAAE,IAAI,GAAG,KAAK,CAAA;AAC3D,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,SAAA,GAAY,cAAc,8CAAA,GAAiD,EAAA;AACjF,QAAA,MAAM,MAAA,GACJ,WAAW,MAAA,GACP,CAAA,sBAAA,CAAA;AAAA;AAAA;AAAA,UAGA,CAAA,+GAAA;AAAA,SAAA;AACN,QAAA,MAAM,GAAA,GAAM,CAAA,YAAA,EAAe,SAAS,CAAA,EAAG,MAAM,CAAA,CAAA;AAC7C,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,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,MAAA,CAAO,QAAA,KAAa,CAAA,GAAI,OAAO,MAAA,GAAS,CAAA,OAAA,EAAU,OAAO,MAAM,CAAA,CAAA,EAAI,CAAA,EAAE;AAAA,MAChH;AAAA,MAEA,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,YAAY,MAAA,CAAO,CAAA,CAAE,aAAa,CAAA,CAAE,OAAA,CAAQ,oBAAoB,EAAE,CAAA;AACxE,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA,IAAK,GAAA;AACjC,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;AAGtD,QAAA,IAAI,QAAA,GAAW,EAAA;AACf,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,IAAI,CAAC,eAAe,IAAA,CAAK,QAAQ,KAAK,CAAC,oBAAA,CAAqB,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC1E,YAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,6EAAA,EAA+E,CAAA,EAAE;AAAA,UAC5H;AACA,UAAA,QAAA,GAAW,CAAA,SAAA,EAAY,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAA;AAAA,QAC7C;AAEA,QAAA,MAAM,aAAa,OAAA,GAAU,CAAA,cAAA,EAAiB,UAAA,CAAW,OAAO,CAAC,CAAA,CAAA,GAAK,EAAA;AACtE,QAAA,MAAM,GAAA,GAAM,sBAAsB,KAAK,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,SAAS,QAAQ,UAAU,CAAA,CAAA;AAEjF,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;AAE7C,QAAA,IAAI,OAAO,QAAA,KAAa,CAAA,IAAK,EAAE,OAAA,IAAW,MAAA,CAAO,aAAa,CAAA,CAAA,EAAI;AAChE,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,MAAMA,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,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;AACtE,QAAA,MAAM,YAAY,KAAA,KAAU,KAAA,CAAA,GAAY,CAAC,IAAI,IAAI,EAAC;AAGlD,QAAA,MAAM,UAAA,GAAa,CAAC,GAAG,SAAA,EAAW,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,GAAGA,KAAI,CAAA;AAClF,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;AAC9C,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,KAAA,KAAU,KAAA,CAAA,GAAY,EAAE,KAAA,EAAM,GAAI,KAAA,CAAS,CAAA;AAC9F,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,UAAAe,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,YAAA,EAAc;AACjB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAqBjD,QAAA,MAAM,MAAM,MAAM,aAAA,CAA4B,YAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,CAAE,CAAA;AACtF,QAAA,MAAM,IAAI,GAAA,CAAI,IAAA;AAEd,QAAA,MAAM,QAAA,GAAW;AAAA,UACf,CAAA,IAAA,EAAO,EAAE,MAAM,CAAA,IAAA,CAAA;AAAA,UACf,CAAA,QAAA,EAAW,EAAE,MAAM,CAAA,CAAA;AAAA,UACnB,CAAA,SAAA,EAAY,EAAE,YAAY,CAAA,CAAA;AAAA,UAC1B,CAAA,QAAA,EAAW,EAAE,SAAA,GAAY,KAAA,GAAQ,IAAI,CAAA,YAAA,EAAe,CAAA,CAAE,WAAA,GAAc,KAAA,GAAQ,IAAI,CAAA,CAAA,CAAA;AAAA,UAChF,CAAA,aAAA,EAAgB,CAAA,CAAE,WAAA,GAAc,KAAA,GAAQ,IAAI,CAAA,CAAA;AAAA,UAC5C,CAAA,QAAA,EAAW,CAAA,CAAE,cAAA,GAAiB,SAAA,GAAY,UAAU,CAAA,CAAA;AAAA,UACpD,CAAA,aAAA,EAAgB,CAAA,CAAE,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,UACxC,EAAA;AAAA,UACA,yBAAA;AAAA,UACA,CAAA,OAAA,EAAU,CAAA,CAAE,OAAA,EAAS,KAAA,EAAO,QAAQ,GAAG,CAAA,CAAA;AAAA,UACvC,CAAA,OAAA,EAAU,CAAA,CAAE,OAAA,EAAS,KAAA,EAAO,QAAQ,GAAG,CAAA,CAAA;AAAA,UACvC,CAAA,MAAA,EAAS,CAAA,CAAE,OAAA,EAAS,IAAA,EAAM,QAAQ,GAAG,CAAA,CAAA;AAAA,UACrC,CAAA,UAAA,EAAa,CAAA,CAAE,OAAA,EAAS,QAAA,EAAU,QAAQ,GAAG,CAAA;AAAA,SAC/C;AAEA,QAAA,IAAI,CAAA,CAAE,UAAU,MAAA,EAAQ;AACtB,UAAA,QAAA,CAAS,IAAA,CAAK,EAAA,EAAI,kBAAA,EAAoB,GAAG,EAAE,QAAQ,CAAA;AAAA,QACrD;AAEA,QAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,EAAE;AAAA,MAClE;AAAA,MAEA,KAAK,kBAAA,EAAoB;AACvB,QAAA,MAAM,MAAA,GAAS,MAAA,CAAO,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,MAAM,UAAA,GAAa,MAAA,CAAO,CAAA,CAAE,UAAU,CAAA;AACtC,QAAA,IAAI,CAAC,MAAA,IAAU,CAAC,YAAY,MAAM,IAAI,MAAM,oCAAoC,CAAA;AAEhF,QAAA,MAAM,aAAA,CAAc,CAAA,SAAA,EAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,CAAA,EAAI;AAAA,UAC5D,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,YAAY;AAAA,SACpC,CAAA;AAMD,QAAA,MAAM,SAAS,MAAM,aAAA,CAA4B,YAAY,kBAAA,CAAmB,MAAM,CAAC,CAAA,CAAE,CAAA;AACzF,QAAA,MAAM,EAAA,GAAK,OAAO,IAAA,CAAK,WAAA;AAEvB,QAAA,OAAO;AAAA,UACL,SAAS,CAAC;AAAA,YACR,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,CAAA,gBAAA,EAAmB,MAAM,CAAA,qBAAA,EAAwB,UAAU,CAAA;AAAA,qBAAA,EAA4B,EAAA,CAAG,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,WAC3G;AAAA,SACH;AAAA,MACF;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(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#x27;/g, \"'\").replace(/&quot;/g, '\"').trim()\r\n : href;\r\n\r\n const snippet = snippetMatch\r\n ? snippetMatch[1].replace(/<[^>]+>/g, '').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#x27;/g, \"'\").replace(/&quot;/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(/&nbsp;/g, ' ')\r\n .replace(/&amp;/g, '&')\r\n .replace(/&lt;/g, '<')\r\n .replace(/&gt;/g, '>')\r\n .replace(/&#x27;/g, \"'\")\r\n .replace(/&quot;/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 'domain-get': 'domains',\r\n 'domain-update-ns': '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 psExpr: string;\r\n if (args.length === 0) {\r\n psExpr = command;\r\n } else {\r\n psExpr = `& ${psSingleQuote(command)} ${args.map(psSingleQuote).join(' ')}`;\r\n }\r\n const utf16 = Buffer.from(psExpr, 'utf16le');\r\n const b64 = utf16.toString('base64');\r\n return `powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -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 },\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 ssh.exec(command, (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 },\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 targetClient.exec(command, (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// 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\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<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<string>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve('Error: timeout'); cleanup = undefined; }, 60_000);\r\n\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\r\n\r\n const lines: string[] = [];\r\n let truncated = false;\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 lines.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 (lines.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 mtime = item.attrs.mtime ? new Date(item.attrs.mtime * 1000).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 const display = recursive ? fullPath : item.filename;\r\n lines.push(`${isDir ? 'd' : '-'} ${String(size).padStart(10)} ${mtime} ${display}`);\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 if (truncated) lines.push(`... (truncated at ${maxResults} entries; raise maxResults or narrow path/pattern)`);\r\n resolve(lines.length ? lines.join('\\n') : 'No entries');\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\nasync function sftpRead(opts: SshConnectionOptions, filePath: string, proxy?: SshConnectionOptions): Promise<string> {\r\n const safe = sanitizePath(filePath);\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 if ((stats.size || 0) > 1_048_576) {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Error: file too large (${stats.size} bytes, max 1MB)`);\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n const rs = sftp.createReadStream(safe);\r\n rs.on('data', (ch: Buffer) => chunks.push(ch));\r\n rs.on('end', () => { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(Buffer.concat(chunks.map(ch => new Uint8Array(ch))).toString('utf-8')); });\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): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\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 if (mode === 'content') {\r\n const ws = sftp.createWriteStream(safe, { mode: 0o644 });\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 finish(`Written ${expectedBytes} bytes to ${safe} in ${elapsed}ms`);\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: 0o644,\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 finish(\r\n `Uploaded ${formatBytes(expectedBytes)} from ${localPath} to ${safe} ` +\r\n `in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s)`,\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(opts: SshConnectionOptions, filePath: string, proxy?: SshConnectionOptions): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\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; }, 30_000);\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\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: 'List all SSH servers you have access to. Returns id, name, hostname, and tags for each server.',\r\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\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: automatically wraps in bash on linux servers and `powershell -EncodedCommand` (UTF-16LE base64) on windows servers, 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\"` (raw shell string, OS-dispatched but caller-quoted).\\n' +\r\n '- Safe: `command` + `args[]`, e.g. `command: \"mysql\"`, `args: [\"-u\", \"root\", \"-p$tr@nge#pwd\", \"-e\", \"SELECT 1\"]` — every arg is quoted/encoded for the target OS.\\n' +\r\n '`stdin` lets you pipe data into the remote process (queries, scripts, secrets) without putting it on the command line.',\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 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 (use for SQL queries, scripts, secrets — anything you do NOT want on the command line).' },\r\n shell: { type: 'string', enum: ['auto', 'bash', 'powershell'], description: 'Override shell selection (default \"auto\" uses the server\\'s os_type).' },\r\n timeout: { type: 'number', description: 'Timeout in milliseconds (default: 60000)' },\r\n },\r\n required: ['serverId', 'command'],\r\n },\r\n },\r\n {\r\n name: 'sftp-list',\r\n description:\r\n 'List files and directories on a remote server via SFTP. Supports recursive traversal and glob filtering, eliminating the need to fall back on `ssh-execute \"find ...\"`.',\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 path: { type: 'string', description: 'Directory path to list (default: /)' },\r\n recursive: { type: 'boolean', description: 'Walk into subdirectories (default false)' },\r\n maxDepth: { type: 'number', description: 'Maximum recursion depth (1-20, default 5)' },\r\n pattern: { type: 'string', description: 'Glob pattern to filter filenames (e.g. \"*.conf\", \"wp-*.php\"). Matches basename only.' },\r\n maxResults: { type: 'number', description: 'Cap total entries returned (default 5000, max 50000)' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'sftp-read',\r\n description: 'Read the contents of a text file on a remote server via SFTP (max 1MB).',\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 path: { type: 'string', description: 'File path to read' },\r\n },\r\n required: ['serverId', 'path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-write',\r\n description:\r\n 'Write a file to a remote server via SFTP. Two modes (provide exactly one of `content` or `sourcePath`):\\n' +\r\n '- `content` (string): inline UTF-8 text. Best for configs, scripts, small JSON. Practical max ~1 MB.\\n' +\r\n '- `sourcePath` (absolute local path): streams a local file with ssh2 fastPut (64 parallel pipelined writes, 64 KiB chunks). Handles GB-scale files (zips, dumps, builds) without going through the LLM. Only usable when the MCP server runs locally on your machine (i.e. not via --proxy-url).\\n' +\r\n 'Protected system paths on the remote 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 path: { type: 'string', description: 'Remote file path to write' },\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 via fastPut (mutually exclusive with content). Use for files >1 MB or any binary.' },\r\n },\r\n required: ['serverId', 'path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-delete',\r\n description: 'Delete a file or empty directory on a remote server via SFTP. Protected system paths 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 path: { type: 'string', description: 'File or directory path to delete' },\r\n },\r\n required: ['serverId', 'path'],\r\n },\r\n },\r\n {\r\n name: 'docker-list',\r\n description:\r\n 'List Docker containers on a remote server. Adds the docker-compose project label as the last column so you can immediately see which compose project a container belongs to.',\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 },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'docker-logs',\r\n description:\r\n 'Get logs from a Docker container. Supports time-window (`since`) and server-side `grep` to keep responses small. 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: { type: 'string', description: 'Container name or ID' },\r\n lines: { type: 'number', description: 'Number of log lines to retrieve (default: 100)' },\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 },\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.). 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 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: 'domain-get',\r\n description: 'Get detailed information about a specific domain: status, renewal date, lock state, managed DNS, DNSSEC, nameservers, contact handles, and messages.',\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: 'domain-update-ns',\r\n description: 'Update nameservers for a domain. Use alias \"default-mijnhost\" to reset to mijn.host defaults. Pushes the change to the domain registry.',\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 nameserver: { type: 'string', description: 'Nameserver profile alias (e.g. \"default-mijnhost\")' },\r\n },\r\n required: ['domain', 'nameserver'],\r\n },\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.1.1';\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 lines = (data || []).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 return `${s.id} ${s.name} ${s.hostname}:${s.port} ${s.username} [${tags}] ${s.hosted_by || ''} os:${os}`;\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\r\n const { conn, proxy, os } = await getServerConnection(String(a.serverId));\r\n if (a.timeout) conn.timeout = Number(a.timeout);\r\n\r\n // Decide which shell wrapper. `auto` follows os_type; explicit override wins.\r\n const shell = shellOverride === 'auto' ? (os === 'windows' ? 'powershell' : 'bash') : shellOverride;\r\n\r\n // If args[] was given, build a safely-quoted command line. Otherwise\r\n // honour the raw `command` string for backwards compat (caller-quoted).\r\n let finalCmd: string;\r\n if (args && args.length > 0) {\r\n finalCmd = 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 by an\r\n // intermediate cmd.exe. This produces a deterministic PowerShell exec.\r\n finalCmd = buildPowerShellEncodedCommand(command, []);\r\n } else {\r\n finalCmd = command;\r\n }\r\n\r\n const result = await sshExec(conn, finalCmd, proxy, stdin !== undefined ? { stdin } : undefined);\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 // ----- SFTP -----\r\n case 'sftp-list': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const listing = await sftpReaddir(conn, String(a.path || '/'), proxy, {\r\n recursive: a.recursive === true,\r\n maxDepth: typeof a.maxDepth === 'number' ? a.maxDepth : undefined,\r\n pattern: typeof a.pattern === 'string' ? a.pattern : undefined,\r\n maxResults: typeof a.maxResults === 'number' ? a.maxResults : undefined,\r\n });\r\n return { content: [{ type: 'text', text: listing }] };\r\n }\r\n\r\n case 'sftp-read': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const content = await sftpRead(conn, String(a.path), proxy);\r\n return { content: [{ type: 'text', text: content }] };\r\n }\r\n\r\n case 'sftp-write': {\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);\r\n return { content: [{ type: 'text', text: result }] };\r\n }\r\n\r\n case 'sftp-delete': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sftpDelete(conn, String(a.path), proxy);\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 filterArg = composeOnly ? ' --filter \"label=com.docker.compose.project\"' : '';\r\n const fmtArg =\r\n format === 'json'\r\n ? ` --format '{{json .}}'`\r\n : // Add the compose project as the last column. Docker's --format\r\n // template language uses {{ index .Labels \"key\" }} for label lookup.\r\n ` --format 'table {{.Names}}\\t{{.Image}}\\t{{.Status}}\\t{{.Ports}}\\t{{ index .Labels \"com.docker.compose.project\" }}'`;\r\n const cmd = `docker ps -a${filterArg}${fmtArg}`;\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sshExec(conn, cmd, proxy);\r\n return { content: [{ type: 'text', text: result.exitCode === 0 ? result.stdout : `Error: ${result.stderr}` }] };\r\n }\r\n\r\n case 'docker-logs': {\r\n const container = String(a.containerName).replace(/[^a-zA-Z0-9._-]/g, '');\r\n const lines = 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\r\n // Validate `since` format: relative (\"10m\", \"2h\", \"24h\", \"30s\", \"7d\") or ISO-ish absolute.\r\n let sinceArg = '';\r\n if (sinceRaw) {\r\n if (!/^\\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 sinceArg = ` --since ${posixQuote(sinceRaw)}`;\r\n }\r\n\r\n const grepSuffix = grepRaw ? ` | grep -i -E ${posixQuote(grepRaw)}` : '';\r\n const cmd = `docker logs --tail ${lines}${sinceArg} ${container} 2>&1${grepSuffix}`;\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sshExec(conn, cmd, proxy);\r\n // grep returns exit 1 when no matches — treat that as success with empty output.\r\n if (result.exitCode !== 0 && !(grepRaw && result.exitCode === 1)) {\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 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 const stdinFlag = stdin !== undefined ? ['-i'] : [];\r\n\r\n // docker exec [-i] [-w DIR] [-u USER] CONTAINER CMD [ARG ...]\r\n const dockerArgs = [...stdinFlag, ...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 const result = await sshExec(conn, fullCmd, proxy, stdin !== undefined ? { stdin } : undefined);\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 'domain-get': {\r\n const domain = String(a.domain);\r\n if (!domain) throw new Error('domain is required');\r\n\r\n interface DomainDetail {\r\n domain: string;\r\n renewal_date: string;\r\n is_lockable: boolean;\r\n is_locked: boolean;\r\n dnssec_enabled: number;\r\n nameservers: string[];\r\n managed_dns: boolean;\r\n whitelabel_ns: boolean;\r\n handles: {\r\n owner: { type: string; name: string; handle_id: number };\r\n tech: { type: string; name: string; handle_id: number };\r\n admin: { type: string; name: string; handle_id: number };\r\n reseller: { type: string; name: string; handle_id: number };\r\n };\r\n status: string;\r\n messages: string[];\r\n }\r\n\r\n const res = await mijnhostFetch<DomainDetail>(`/domains/${encodeURIComponent(domain)}`);\r\n const d = res.data;\r\n\r\n const sections = [\r\n `=== ${d.domain} ===`,\r\n `Status: ${d.status}`,\r\n `Renewal: ${d.renewal_date}`,\r\n `Locked: ${d.is_locked ? 'Yes' : 'No'} (lockable: ${d.is_lockable ? 'Yes' : 'No'})`,\r\n `Managed DNS: ${d.managed_dns ? 'Yes' : 'No'}`,\r\n `DNSSEC: ${d.dnssec_enabled ? 'Enabled' : 'Disabled'}`,\r\n `Nameservers: ${d.nameservers.join(', ')}`,\r\n '',\r\n '--- Contact Handles ---',\r\n `Owner: ${d.handles?.owner?.name ?? '-'}`,\r\n `Admin: ${d.handles?.admin?.name ?? '-'}`,\r\n `Tech: ${d.handles?.tech?.name ?? '-'}`,\r\n `Reseller: ${d.handles?.reseller?.name ?? '-'}`,\r\n ];\r\n\r\n if (d.messages?.length) {\r\n sections.push('', '--- Messages ---', ...d.messages);\r\n }\r\n\r\n return { content: [{ type: 'text', text: sections.join('\\n') }] };\r\n }\r\n\r\n case 'domain-update-ns': {\r\n const domain = String(a.domain);\r\n const nameserver = String(a.nameserver);\r\n if (!domain || !nameserver) throw new Error('domain and nameserver are required');\r\n\r\n await mijnhostFetch(`/domains/${encodeURIComponent(domain)}`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ nameserver }),\r\n });\r\n\r\n interface DomainDetail {\r\n domain: string;\r\n nameservers: string[];\r\n }\r\n const verify = await mijnhostFetch<DomainDetail>(`/domains/${encodeURIComponent(domain)}`);\r\n const ns = verify.data.nameservers;\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Nameservers for ${domain} updated to profile \"${nameserver}\".\\nCurrent nameservers: ${ns.join(', ')}`,\r\n }],\r\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","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(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#x27;/g, \"'\").replace(/&quot;/g, '\"').trim()\r\n : href;\r\n\r\n const snippet = snippetMatch\r\n ? snippetMatch[1].replace(/<[^>]+>/g, '').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#x27;/g, \"'\").replace(/&quot;/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(/&nbsp;/g, ' ')\r\n .replace(/&amp;/g, '&')\r\n .replace(/&lt;/g, '<')\r\n .replace(/&gt;/g, '>')\r\n .replace(/&#x27;/g, \"'\")\r\n .replace(/&quot;/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 'domain-get': 'domains',\r\n 'domain-update-ns': '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 return `powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -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 },\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 ssh.exec(command, (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 },\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 targetClient.exec(command, (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// 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\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<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<string>((resolve) => {\r\n const timer = setTimeout(() => { cleanup?.(); resolve('Error: timeout'); cleanup = undefined; }, 60_000);\r\n\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\r\n\r\n const lines: string[] = [];\r\n let truncated = false;\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 lines.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 (lines.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 mtime = item.attrs.mtime ? new Date(item.attrs.mtime * 1000).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 const display = recursive ? fullPath : item.filename;\r\n lines.push(`${isDir ? 'd' : '-'} ${String(size).padStart(10)} ${mtime} ${display}`);\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 if (truncated) lines.push(`... (truncated at ${maxResults} entries; raise maxResults or narrow path/pattern)`);\r\n resolve(lines.length ? lines.join('\\n') : 'No entries');\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\nasync function sftpRead(opts: SshConnectionOptions, filePath: string, proxy?: SshConnectionOptions): Promise<string> {\r\n const safe = sanitizePath(filePath);\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 if ((stats.size || 0) > 1_048_576) {\r\n clearTimeout(timer); cleanup?.(); cleanup = undefined;\r\n resolve(`Error: file too large (${stats.size} bytes, max 1MB)`);\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n const rs = sftp.createReadStream(safe);\r\n rs.on('data', (ch: Buffer) => chunks.push(ch));\r\n rs.on('end', () => { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(Buffer.concat(chunks.map(ch => new Uint8Array(ch))).toString('utf-8')); });\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): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\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 if (mode === 'content') {\r\n const ws = sftp.createWriteStream(safe, { mode: 0o644 });\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 finish(`Written ${expectedBytes} bytes to ${safe} in ${elapsed}ms`);\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: 0o644,\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 finish(\r\n `Uploaded ${formatBytes(expectedBytes)} from ${localPath} to ${safe} ` +\r\n `in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s)`,\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(opts: SshConnectionOptions, filePath: string, proxy?: SshConnectionOptions): Promise<string> {\r\n const safe = sanitizePath(filePath);\r\n assertWritablePath(safe);\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; }, 30_000);\r\n client.sftp((err, sftp) => {\r\n if (err) { clearTimeout(timer); cleanup?.(); cleanup = undefined; resolve(`Error: ${err.message}`); return; }\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: 'List all SSH servers you have access to. Returns id, name, hostname, and tags for each server.',\r\n inputSchema: { type: 'object' as const, properties: {}, required: [] },\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: automatically wraps in bash on linux servers and `powershell -EncodedCommand` (UTF-16LE base64) on windows servers, 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\"` (raw shell string, OS-dispatched but caller-quoted).\\n' +\r\n '- Safe: `command` + `args[]`, e.g. `command: \"mysql\"`, `args: [\"-u\", \"root\", \"-p$tr@nge#pwd\", \"-e\", \"SELECT 1\"]` — every arg is quoted/encoded for the target OS.\\n' +\r\n '`stdin` lets you pipe data into the remote process (queries, scripts, secrets) without putting it on the command line.',\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 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 (use for SQL queries, scripts, secrets — anything you do NOT want on the command line).' },\r\n shell: { type: 'string', enum: ['auto', 'bash', 'powershell'], description: 'Override shell selection (default \"auto\" uses the server\\'s os_type).' },\r\n timeout: { type: 'number', description: 'Timeout in milliseconds (default: 60000)' },\r\n },\r\n required: ['serverId', 'command'],\r\n },\r\n },\r\n {\r\n name: 'sftp-list',\r\n description:\r\n 'List files and directories on a remote server via SFTP. Supports recursive traversal and glob filtering, eliminating the need to fall back on `ssh-execute \"find ...\"`.',\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 path: { type: 'string', description: 'Directory path to list (default: /)' },\r\n recursive: { type: 'boolean', description: 'Walk into subdirectories (default false)' },\r\n maxDepth: { type: 'number', description: 'Maximum recursion depth (1-20, default 5)' },\r\n pattern: { type: 'string', description: 'Glob pattern to filter filenames (e.g. \"*.conf\", \"wp-*.php\"). Matches basename only.' },\r\n maxResults: { type: 'number', description: 'Cap total entries returned (default 5000, max 50000)' },\r\n },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'sftp-read',\r\n description: 'Read the contents of a text file on a remote server via SFTP (max 1MB).',\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 path: { type: 'string', description: 'File path to read' },\r\n },\r\n required: ['serverId', 'path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-write',\r\n description:\r\n 'Write a file to a remote server via SFTP. Two modes (provide exactly one of `content` or `sourcePath`):\\n' +\r\n '- `content` (string): inline UTF-8 text. Best for configs, scripts, small JSON. Practical max ~1 MB.\\n' +\r\n '- `sourcePath` (absolute local path): streams a local file with ssh2 fastPut (64 parallel pipelined writes, 64 KiB chunks). Handles GB-scale files (zips, dumps, builds) without going through the LLM. Only usable when the MCP server runs locally on your machine (i.e. not via --proxy-url).\\n' +\r\n 'Protected system paths on the remote 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 path: { type: 'string', description: 'Remote file path to write' },\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 via fastPut (mutually exclusive with content). Use for files >1 MB or any binary.' },\r\n },\r\n required: ['serverId', 'path'],\r\n },\r\n },\r\n {\r\n name: 'sftp-delete',\r\n description: 'Delete a file or empty directory on a remote server via SFTP. Protected system paths 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 path: { type: 'string', description: 'File or directory path to delete' },\r\n },\r\n required: ['serverId', 'path'],\r\n },\r\n },\r\n {\r\n name: 'docker-list',\r\n description:\r\n 'List Docker containers on a remote server. Adds the docker-compose project label as the last column so you can immediately see which compose project a container belongs to.',\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 },\r\n required: ['serverId'],\r\n },\r\n },\r\n {\r\n name: 'docker-logs',\r\n description:\r\n 'Get logs from a Docker container. Supports time-window (`since`) and server-side `grep` to keep responses small. 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: { type: 'string', description: 'Container name or ID' },\r\n lines: { type: 'number', description: 'Number of log lines to retrieve (default: 100)' },\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 },\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.). 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 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: 'domain-get',\r\n description: 'Get detailed information about a specific domain: status, renewal date, lock state, managed DNS, DNSSEC, nameservers, contact handles, and messages.',\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: 'domain-update-ns',\r\n description: 'Update nameservers for a domain. Use alias \"default-mijnhost\" to reset to mijn.host defaults. Pushes the change to the domain registry.',\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 nameserver: { type: 'string', description: 'Nameserver profile alias (e.g. \"default-mijnhost\")' },\r\n },\r\n required: ['domain', 'nameserver'],\r\n },\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.1.1';\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 lines = (data || []).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 return `${s.id} ${s.name} ${s.hostname}:${s.port} ${s.username} [${tags}] ${s.hosted_by || ''} os:${os}`;\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\r\n const { conn, proxy, os } = await getServerConnection(String(a.serverId));\r\n if (a.timeout) conn.timeout = Number(a.timeout);\r\n\r\n // Decide which shell wrapper. `auto` follows os_type; explicit override wins.\r\n const shell = shellOverride === 'auto' ? (os === 'windows' ? 'powershell' : 'bash') : shellOverride;\r\n\r\n // If args[] was given, build a safely-quoted command line. Otherwise\r\n // honour the raw `command` string for backwards compat (caller-quoted).\r\n let finalCmd: string;\r\n if (args && args.length > 0) {\r\n finalCmd = 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 by an\r\n // intermediate cmd.exe. This produces a deterministic PowerShell exec.\r\n finalCmd = buildPowerShellEncodedCommand(command, []);\r\n } else {\r\n finalCmd = command;\r\n }\r\n\r\n const result = await sshExec(conn, finalCmd, proxy, stdin !== undefined ? { stdin } : undefined);\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 // ----- SFTP -----\r\n case 'sftp-list': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const listing = await sftpReaddir(conn, String(a.path || '/'), proxy, {\r\n recursive: a.recursive === true,\r\n maxDepth: typeof a.maxDepth === 'number' ? a.maxDepth : undefined,\r\n pattern: typeof a.pattern === 'string' ? a.pattern : undefined,\r\n maxResults: typeof a.maxResults === 'number' ? a.maxResults : undefined,\r\n });\r\n return { content: [{ type: 'text', text: listing }] };\r\n }\r\n\r\n case 'sftp-read': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const content = await sftpRead(conn, String(a.path), proxy);\r\n return { content: [{ type: 'text', text: content }] };\r\n }\r\n\r\n case 'sftp-write': {\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);\r\n return { content: [{ type: 'text', text: result }] };\r\n }\r\n\r\n case 'sftp-delete': {\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sftpDelete(conn, String(a.path), proxy);\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 filterArg = composeOnly ? ' --filter \"label=com.docker.compose.project\"' : '';\r\n const fmtArg =\r\n format === 'json'\r\n ? ` --format '{{json .}}'`\r\n : // Add the compose project as the last column. Docker exposes\r\n // labels through the `.Label \"key\"` method (Labels itself is a\r\n // string slice \"k=v,k=v\" in docker ps, not a map — `index` fails).\r\n ` --format 'table {{.Names}}\\t{{.Image}}\\t{{.Status}}\\t{{.Ports}}\\t{{.Label \"com.docker.compose.project\"}}'`;\r\n const cmd = `docker ps -a${filterArg}${fmtArg}`;\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sshExec(conn, cmd, proxy);\r\n return { content: [{ type: 'text', text: result.exitCode === 0 ? result.stdout : `Error: ${result.stderr}` }] };\r\n }\r\n\r\n case 'docker-logs': {\r\n const container = String(a.containerName).replace(/[^a-zA-Z0-9._-]/g, '');\r\n const lines = 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\r\n // Validate `since` format: relative (\"10m\", \"2h\", \"24h\", \"30s\", \"7d\") or ISO-ish absolute.\r\n let sinceArg = '';\r\n if (sinceRaw) {\r\n if (!/^\\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 sinceArg = ` --since ${posixQuote(sinceRaw)}`;\r\n }\r\n\r\n const grepSuffix = grepRaw ? ` | grep -i -E ${posixQuote(grepRaw)}` : '';\r\n const cmd = `docker logs --tail ${lines}${sinceArg} ${container} 2>&1${grepSuffix}`;\r\n\r\n const { conn, proxy } = await getServerConnection(String(a.serverId));\r\n const result = await sshExec(conn, cmd, proxy);\r\n // grep returns exit 1 when no matches — treat that as success with empty output.\r\n if (result.exitCode !== 0 && !(grepRaw && result.exitCode === 1)) {\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 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 const stdinFlag = stdin !== undefined ? ['-i'] : [];\r\n\r\n // docker exec [-i] [-w DIR] [-u USER] CONTAINER CMD [ARG ...]\r\n const dockerArgs = [...stdinFlag, ...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 const result = await sshExec(conn, fullCmd, proxy, stdin !== undefined ? { stdin } : undefined);\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 'domain-get': {\r\n const domain = String(a.domain);\r\n if (!domain) throw new Error('domain is required');\r\n\r\n interface DomainDetail {\r\n domain: string;\r\n renewal_date: string;\r\n is_lockable: boolean;\r\n is_locked: boolean;\r\n dnssec_enabled: number;\r\n nameservers: string[];\r\n managed_dns: boolean;\r\n whitelabel_ns: boolean;\r\n handles: {\r\n owner: { type: string; name: string; handle_id: number };\r\n tech: { type: string; name: string; handle_id: number };\r\n admin: { type: string; name: string; handle_id: number };\r\n reseller: { type: string; name: string; handle_id: number };\r\n };\r\n status: string;\r\n messages: string[];\r\n }\r\n\r\n const res = await mijnhostFetch<DomainDetail>(`/domains/${encodeURIComponent(domain)}`);\r\n const d = res.data;\r\n\r\n const sections = [\r\n `=== ${d.domain} ===`,\r\n `Status: ${d.status}`,\r\n `Renewal: ${d.renewal_date}`,\r\n `Locked: ${d.is_locked ? 'Yes' : 'No'} (lockable: ${d.is_lockable ? 'Yes' : 'No'})`,\r\n `Managed DNS: ${d.managed_dns ? 'Yes' : 'No'}`,\r\n `DNSSEC: ${d.dnssec_enabled ? 'Enabled' : 'Disabled'}`,\r\n `Nameservers: ${d.nameservers.join(', ')}`,\r\n '',\r\n '--- Contact Handles ---',\r\n `Owner: ${d.handles?.owner?.name ?? '-'}`,\r\n `Admin: ${d.handles?.admin?.name ?? '-'}`,\r\n `Tech: ${d.handles?.tech?.name ?? '-'}`,\r\n `Reseller: ${d.handles?.reseller?.name ?? '-'}`,\r\n ];\r\n\r\n if (d.messages?.length) {\r\n sections.push('', '--- Messages ---', ...d.messages);\r\n }\r\n\r\n return { content: [{ type: 'text', text: sections.join('\\n') }] };\r\n }\r\n\r\n case 'domain-update-ns': {\r\n const domain = String(a.domain);\r\n const nameserver = String(a.nameserver);\r\n if (!domain || !nameserver) throw new Error('domain and nameserver are required');\r\n\r\n await mijnhostFetch(`/domains/${encodeURIComponent(domain)}`, {\r\n method: 'PUT',\r\n body: JSON.stringify({ nameserver }),\r\n });\r\n\r\n interface DomainDetail {\r\n domain: string;\r\n nameservers: string[];\r\n }\r\n const verify = await mijnhostFetch<DomainDetail>(`/domains/${encodeURIComponent(domain)}`);\r\n const ns = verify.data.nameservers;\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Nameservers for ${domain} updated to profile \"${nameserver}\".\\nCurrent nameservers: ${ns.join(', ')}`,\r\n }],\r\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"]}